This file is indexed.

/usr/share/psychtoolbox-3/PsychCal/ContrastMatch.m is in psychtoolbox-3-common 3.0.11.20140816.dfsg1-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
function weight=ContrastMatch(device,dimWeight,foreColor,backColor)
% weight=ContrastMatch(device,dimWeight,[foreColor],[backColor])
%
% Displays two gratings. The bright grating alternates white and weight*white,
% producing luminances LMax and LBright.
% The dim grating alternates dimWeight*white and black, producing luminances
% LDim and LMin.
% When the grating contrasts match, LMax/LBright=LDim/LMin.
% In a more compact notation, L1/Lb=Ld/L0. We set the weight wd that produces
% Ld, and the observer adjusts the weight wb that produces Lb. They are related
% by the gamma function, y=g(w), where y is the normalized luminance,
% y=(L-L0)/(L1-L0). We know wb and wd, and we have access to the gamma function,
% so we can compute yb and yd. Solving for L, we have
%	L=y*(L1-L0)+L0
% Our relation at match can be rewritten as
%	L1*L0=Ld*Lb
%	0=Ld*Lb-L1*L0
%	=(yd*(L1-L0)+L0)*(yb*(L1-L0)+L0)-L1*L0
%	Let's divide by L1^2, and define r=L0/L1.
%	=(yd*(1-r)+r)*(yb*(1-r)+r)-r
%	This is a quadratic equation in r
%	=(yd+(1-yd)*r)*(yb+(1-yb)*r)-r
%	=yd*yb+(yb*(1-yd)+yd*(1-yb)-1)*r+(1-yd)*(1-yb)*r^2
%	c=[(1-yd)*(1-yb) yb*(1-yd)+yd*(1-yb)-1 yd*yb]; % coefficients of quadratic polynomial
%	r=roots(c)
% The answer, r, is the desired ratio of L0/L1.
%
% 5/28/96 dgp  Wrote it.
% 5/28/96 dgp  Updated to use new GetMouse, that flushes mouse events.
% 8/4/96  dhb  Changed name to ContrastMatch.
% 8/16/97 dgp  Changed "text" to "theText" to avoid conflict with TEXT function.
% 7/19/98 dgp  Removed obsolete TIMER.
% 6/30/03 dgp Updated Screen OpenScreen to Screen OpenWindow.

PsychDefaultSetup(1);

if nargin<2 || nargout>1
	error('Usage: weight=GratingMatch(device,dimWeight,[foreColor],[backColor])');
end
if nargin<4
	backColor=[0 0 0];
end
if nargin<3
	foreColor=[255 255 255];
end
dpi=67;
distanceM=0.57;
pixelDeg=57/(dpi*distanceM/0.0254);
[win, screenRect] = Screen('OpenWindow', device);
screenRect=reshape(screenRect,1,4);
white=[255 255 255];
black=[0 0 0];
clut=(0:255)';
clut=clut(:,[1 1 1]);
clut(1,:)=white;
clut(256,:)=black;
clut(2,:)=black;
clut(3,:)=white;
clut(4,:)=black;
clut(5,:)=dimWeight*white+(1-dimWeight)*black;
Screen('SetClut', win, clut);

if 0
	blend=1:RectHeight(barRect);
	blend=blend-blendPeriodPix*floor(blend/blendPeriodPix); % modulo the period
	blend=2+(blend >= round(forePart*blendPeriodPix));
	blend=Expand(blend',RectWidth(barRect),1);
	pure=ones(RectHeight(barRect),RectWidth(barRect));
	Screen('BlitImage255',blend,barRect);
	barRect=OffsetRect(barRect,RectWidth(barRect),0);
	Screen('BlitImage255',pure,barRect);
	barRect=OffsetRect(barRect,RectWidth(barRect),0);
end

% Create two 1 c/deg squarewave gratings at different luminances.
% CLUT entries: 1=adjustable, 2=foreColor, 3=backColor
barWidth=max(1,round(0.5/(1*pixelDeg))); % 1 c/deg grating
testRect=ScaleRect(screenRect,0.5,0.5);
testRect=round(AlignRect(testRect,screenRect,RectLeft,RectTop));
barRect=SetRect(0,0,barWidth,RectHeight(testRect));
for color=0:2:2
	barRect=AlignRect(barRect,testRect,RectLeft,RectBottom);
	for i=0:2:ceil(RectWidth(testRect)/RectWidth(barRect))
		Screen('FillRect', win, color+1,barRect);
		barRect=OffsetRect(barRect,RectWidth(barRect),0);
		Screen('FillRect', win, color+2,barRect);
		barRect=OffsetRect(barRect,RectWidth(barRect),0);
	end
	Screen('FillRect', win, 0,AdjoinRect(testRect,testRect,RectRight))
	testRect=AdjoinRect(testRect,testRect,RectBottom);
end

% Print instructions
theText=sprintf(     'Move the mouse up and');
theText=char(theText,'down to match the grating');
theText=char(theText,'contrasts. Click when ');
theText=char(theText,'you see one long grating,');
theText=char(theText,'partly occluded by a dark');
theText=char(theText,'filter.');
s=24;
%Screen('TextFont', win, 'Chicago');
Screen('TextSize', win, s);
s=s+8;
% textRect=SetRect(0,0,Screen('TextWidth',theText(2,:)),size(theText,1)*s);
% textRect=CenterRect(textRect,screenRect);
% textRect=OffsetRect(textRect,RectWidth(screenRect)/4+20/4,0);
% for i=1:size(theText,1)
% 	Screen('DrawText',textRect(RectLeft),textRect(RectTop)+s*i,255,theText(i,:));
% end
DrawFormattedText(win, theText, 0, 'center', 'center', white);

% animate
% track vertical mouse position with vertical slider knob.
sliderRect=SetRect(0,0,20,RectHeight(screenRect));
sliderRect=CenterRect(sliderRect,screenRect);
knobRect=SetRect(0,0,RectWidth(sliderRect),RectWidth(sliderRect));
knobRect=InsetRect(CenterRect(knobRect,sliderRect),1,0);
top=RectTop;
bottom=RectBottom;
Screen('FillRect', win, 0, sliderRect);
Screen('FrameRect', win, 255, sliderRect);
while 1
	[x,y,button]=GetMouse;
	weight=(sliderRect(bottom)-y)/RectHeight(sliderRect);
	Screen('SetClut', win, weight*foreColor+(1-weight)*backColor,1);
	dy=y-(knobRect(top)+knobRect(bottom))/2;
	residue=knobRect;
	if dy>0
		residue(bottom)=residue(top)+dy;
	else
		residue(top)=residue(bottom)+dy;
	end
	knobRect=OffsetRect(knobRect,0,dy);
	Screen('FillRect', win, 0,residue);
	Screen('FillRect', win, 255,knobRect);
	if(button) break; end;
	WaitSecs(.01); % make sure we miss some frames, so mouse gets updated
end
Screen('CloseAll');