function DualAcuity
% Acuity test, with and without noise. The ratio of the two acuities should be 
% diagnostic for amblyopia.
% If varyCheckPix==1 then all letters are at fixed contrast, and the chart is fractal;
% each row is a smaller version of the one above.
% Otherwise the letter are at fixed energy, jacking up the contrast as they get smaller.
% In either case all letters in noise are at the same signal-to-noise ratio.

% 9/15/02 dgp Wrote it.

varyCheckPix=1;
waitForClick=0;
saveToDisk=1;
rmsContrast=0.17; % 0.17
cellWidthPix=8*58; % 8*58 for printed eyechart, 3*58 for viewing on screen
rowScalar=10^-0.1;
rows=30;
columns=6;
chartWidthPix=columns*cellWidthPix;
cellHeightPix=cellWidthPix;
chartHeightPix=sum(round(rowScalar.^(0:rows-1)*cellHeightPix));
rect=[0 0 chartWidthPix chartHeightPix];
window=screen(0,'OpenWindow',[],[],8);
% 	fprintf('free %.1f MB;temp free %.1f MB\n',bytes/1e6,bytes('tempfree')/1e6);
windowRect=screen(window,'Rect');
rectShow=rect;
if RectWidth(rectShow)>RectWidth(windowRect)
	rectShow=round(rectShow*RectWidth(windowRect)/RectWidth(rectShow));
end
if RectHeight(rectShow)>RectHeight(windowRect)
	rectShow=round(rectShow*RectHeight(windowRect)/RectHeight(rectShow));
end
Screen(window,'TextSize',20); % was 32
wSignal=screen(window,'openoffscreenwindow',[],rect,8);
wNoise=screen(window,'openoffscreenwindow',[],rect,8);
wSmall=screen(window,'openoffscreenwindow',[],rect,8);
white=WhiteIndex(window);
black=BlackIndex(window);
gray=round(GrayIndex(window,0.5));
range=abs(white-black);
Screen(wNoise,'FillRect',gray);
top=0;
if varyCheckPix
	c=0.4;
else
	checkPix=1;
	c=0.04*(3*58/cellWidthPix)*(checkPix/1)*(rmsContrast/0.1); % set signal-to-noise ratio
end
rand(100);
for row=1:rows
	if varyCheckPix
		checkPix=round(cellWidthPix/29);
	end
	if checkPix<1 | cellWidthPix<12*checkPix | c>=1
		break
	end
	for column=1:columns
		addNoise=column>columns/2;
		letterInc=round(c*(black-gray));
		noiseFloor=max(0,-letterInc);
		noiseCeil=min(range,range-letterInc);
		cellRect=[0 0 cellWidthPix cellHeightPix];
		cellRectSmall=round(cellRect/checkPix);
		
		% noise
		noiseOriginal=rand([RectHeight(cellRectSmall) RectWidth(cellRectSmall)])-0.5; % zero mean
		noise=noiseOriginal;
		power=mean(mean(noise.^2));
		noise=addNoise*noise*rmsContrast/sqrt(power);
		noise=round(gray+noise*range);
		bad=length(find(noise<noiseFloor | noise>noiseCeil));
		total=length(noise(:));
		if bad/total>0.01
			fprintf('Clipping %.1f%% of noise pixels (%g/%g).\n',100*bad/total,bad,total);
		end
		noise=min(noiseCeil,max(noiseFloor,noise));
		cellRect=OffsetRect(cellRect,cellWidthPix*(column-1),top);
		cellRect=OffsetRect(cellRect,(chartWidthPix-cellWidthPix*columns)/2,0);
		Screen(wNoise,'PutImage',noise,cellRect);
		Screen('CopyWindow',wNoise,window,cellRect,cellRect);
		
		% letter
		letterCheckPix=1;
		letterRect=round(cellRect/2);
		letterRectSmall=round(letterRect/letterCheckPix);
		letterRect=CenterRect(letterRect,cellRect);
% 		letterRect=OffsetRect(letterRect,-mod(letterRect(1),checkPix),-mod(letterRect(2),checkPix));
		Screen(wSmall,'TextFont','Sloan');
		Screen(wSmall,'TextSize',cellHeightPix/2/letterCheckPix);
		Screen(wSmall,'FillRect');
		Screen(wSmall,'DrawText',Sample('CDHKNORSVZ'),letterRectSmall(RectLeft),letterRectSmall(RectBottom),letterInc);
		Screen('CopyWindow',wSmall,wSignal,letterRectSmall,letterRect);
		Screen('CopyWindow',wSignal,window,letterRect,letterRect);
	end
	top=top+cellHeightPix;
	cellWidthPix=round(rowScalar*cellWidthPix);
	cellHeightPix=cellWidthPix;
	if ~varyCheckPix
		c=c/rowScalar;
	end
end
Screen('CopyWindow',wNoise,wSignal,[],[],'addOverQuickly'); % add noise to signal
Screen(window,'FillRect');
Screen('CopyWindow',wSignal,window,rect,rectShow);
if saveToDisk
	% save to disk
	rect=Screen(wSignal,'Rect');
	paperRect=SetRect(0,11*72,8.5*72,0);
	pageRect=rect.*[1,-1,1,-1];% convert from Apple to Adobe coordinates
	pageRect=CenterRect(pageRect,paperRect);
	if varyCheckPix
		insert='C'; % fixed letter contrast
	else
		insert='E'; % fixed letter energy
	end
	filename=sprintf('DualAcuity%s.eps',insert);
	cd(DesktopFolder);
	Screen(wSignal,'SaveAsEps',filename,rect,pageRect)
	filetype(filename,'EPSF','GKON'); % set creator to GraphicConverter <http://www.lemkesoft.com/gcdownload_us.html>
	fprintf('Saving "%s" on desktop.\n',filename);
end
if waitForClick
	Ask(window,'Click to continue.');
end
Screen(wSignal,'Close');
Screen(wNoise,'Close');

Ask(window,'Done. Click to exit.');
Screen(window,'Close');
