Skip to content

Instantly share code, notes, and snippets.

@kleinerm
Created December 25, 2021 19:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kleinerm/63701253e9c7f3d6c08c08885389dba5 to your computer and use it in GitHub Desktop.
Save kleinerm/63701253e9c7f3d6c08c08885389dba5 to your computer and use it in GitHub Desktop.
function debugPseudogray(plotstim)
if nargin < 1
error('Specify plotstim as 0, 1 or 2 !');
end
KbName('UnifyKeyNames');
UpArrow = KbName('UpArrow');
DownArrow = KbName('DownArrow');
LeftArrow = KbName('LeftArrow');
RightArrow = KbName('RightArrow');
esc = KbName('ESCAPE');
space = KbName('space');
GammaIncrease = KbName('i');
GammaDecrease = KbName('d');
try
% This script calls Psychtoolbox commands available only in OpenGL-based
% versions of the Psychtoolbox. The Psychtoolbox command AssertPsychOpenGL will issue
% an error message if someone tries to execute this script on a computer without
% an OpenGL Psychtoolbox
AssertOpenGL;
% Get the list of screens and choose the one with the highest screen number.
% Screen 0 is, by definition, the display with the menu bar. Often when
% two monitors are connected the one without the menu bar is used as
% the stimulus display. Chosing the display with the highest dislay number is
% a best guess about where you want the stimulus displayed.
screenNumber = max(Screen('Screens'));
% Open a double-buffered fullscreen window with a gray (intensity =
% 0.5) background and support for 16- or 32 bpc floating point framebuffers.
PsychImaging('PrepareConfiguration');
[w, h] = Screen('WindowSize', screenNumber);
lrect = [0, 0, w, round(h/2)];
% This will try to get 32 bpc float precision if the hardware supports
% simultaneous use of 32 bpc float and alpha-blending. Otherwise it
% will use a 16 bpc floating point framebuffer for drawing and
% alpha-blending, but a 32 bpc buffer for gamma correction and final
% display. The effective stimulus precision is reduced from 23 bits to
% about 11 bits when a 16 bpc float buffer must be used instead of a 32
% bpc float buffer:
PsychImaging('AddTask', 'General', 'FloatingPoint32BitIfPossible');
PsychImaging('AddTask', 'General', 'EnablePseudoGrayOutput');
PsychImaging('AddTask', 'FinalFormatting', 'DisplayColorCorrection', 'SimpleGamma');
doTheGamma =1;
%PsychImaging('AddTask', 'General', 'InterleavedLineStereo', 0);
% Finally open a window according to the specs given with above
% PsychImaging calls, clear it to a background color of 0.5 aka 50%
% luminance:
[w, wRect]=PsychImaging('OpenWindow', screenNumber, 0.5, lrect);
gamma = 1 / 2.0;
PsychColorCorrection('SetEncodingGamma', w, gamma);
% From here on, all color values should be specified in the range 0.0
% to 1.0 for displayable luminance values. Values outside that range
% are allowed as intermediate results, but the final stimulus image
% should be in range 0-1, otherwise result will be undefined.
[width, height]=Screen('WindowSize', w);
% Enable alpha blending. We switch it into additive mode which takes
% source alpha into account:
Screen('BlendFunction', w, GL_SRC_ALPHA, GL_ONE);
inc=0.25;
s=200;
[x,y]=meshgrid(-s:s-1, -s:s-1);
angle=0*pi/180; % 30 deg orientation.
f=2*pi/16; % cycles/pixel
a=cos(angle)*f;
b=sin(angle)*f;
% Build grating texture:
m=sin(a*x+b*y);
tex=Screen('MakeTexture', w, m,[],[], 2);
% Show the gray background:
Screen('Flip', w);
i=0;
rotate = 0;
yd =0;
show2nd = 1;
Screen('TextSize', w, 18);
% Center mouse on stimulus display, then make mouse cursor invisible:
[cx, cy] = RectCenter(wRect);
SetMouse(cx, cy, w);
HideCursor(screenNumber);
framecount = 0;
tstart = GetSecs;
% Animation loop:
while 1
Screen('DrawTexture', w, tex, [], [], [], [], 0.25);
i=i+rotate;
[x,y,buttons]=GetMouse(w);
[x,y] = RemapMouse(w, 'AllViews', x, y);
if any(buttons)
if buttons(1)
i=i+0.1;
end
if buttons(2)
i=i-0.1;
end
end
if show2nd
x = cx;
y = cy;
dstRect=CenterRectOnPoint(Screen('Rect', tex), x, y+yd);
Screen('DrawTexture', w, tex, [], dstRect, i, [], inc);
end
[d1, d2, keycode]=KbCheck; %#ok<*ASGLU>
if d1
if keycode(UpArrow)
yd=yd-0.1;
end
if keycode(DownArrow)
yd=yd+0.1;
end
if keycode(LeftArrow) && inc >= 0.001
inc=inc-0.001;
end
if keycode(RightArrow) && inc <= 0.999
inc=inc+0.001;
end
% Change of encoding gamma?
if keycode(GammaIncrease) && doTheGamma
gamma = min(gamma+0.001, 1.0);
PsychColorCorrection('SetEncodingGamma', w, gamma);
end
if keycode(GammaDecrease) && doTheGamma
gamma = max(gamma-0.001, 0.0);
PsychColorCorrection('SetEncodingGamma', w, gamma);
end
if keycode(space)
show2nd = 1-show2nd;
KbReleaseWait;
if show2nd
HideCursor(screenNumber);
else
ShowCursor(screenNumber);
end
end
if keycode(esc)
break;
end
end
txt0= 'At startup:\ngrating = sin(f*cos(angle)*x + f*sin(angle)*y); % Compute luminance grating matrix in Matlab.\n';
txt1= 'tex = Screen(''MakeTexture'', win, grating, [], [], 2); % Convert it into a 32bpc floating point texture.\n';
txt2= 'Screen(''BlendFunction'', win, GL_SRC_ALPHA, GL_ONE); % Enable additive alpha-blending.\n\nIn Display loop:\n\n';
txt3= 'Screen(''DrawTexture'', win, tex, [], [], [], [], 0.25); % Draw static grating at center of screen.\n';
txt4 = sprintf('Screen(''DrawTexture'', win, tex, [], [%i %i %i %i], %f, [], %f);\n', dstRect(1), dstRect(2), dstRect(3), dstRect(4), i, inc);
txt5 = sprintf('\nEncoding Gamma is %f --> Correction for a %f gamma display.', gamma, 1/gamma);
DrawFormattedText(w, [txt0 txt1 txt2 txt3 txt4 txt5], 0, 20, 1.0);
framecount = framecount + 1;
% For the fun of it: Set a specific scanline to send a trigger
% signal for the VideoSwitcher. This does nothing if the driver for
% VideoSwitcher is not selected. We send out a trigger for 1 redraw
% cycle every 30 redraw cycles. The triggerline is placed at
% scanline 10 (for no special reason):
if mod(framecount, 30) == 0
PsychVideoSwitcher('SetTrigger', w, 10, 1);
end
if plotstim == 1
drawnimg = Screen('GetImage', w, dstRect, 'drawBuffer', 1, 1);
sampleLine = drawnimg(size(drawnimg, 1) / 2, :);
plot(sampleLine);
drawnow;
end
% Show stimulus at next display retrace:
Screen('Flip', w);
if plotstim == 2
outimg = Screen('GetImage', w, dstRect, 'frontBuffer', 0, 3);
sampleLine = squeeze(outimg(size(outimg, 1) / 2, :, :));
bl = 1:length(sampleLine);
plot(bl, sampleLine(:,1), 'r', bl, sampleLine(:,2), 'g', bl, sampleLine(:,3), 'b');
drawnow;
end
end
% Done.
avgfps = framecount / (GetSecs - tstart);
fprintf('Average redraw rate in demo was %f Hz.\n', avgfps);
% Again, just to test conversion speed: A fast benchmark with sync of
% buffer swaps to retrace disabled -- Go as fast as you can!
nmaxbench = 300;
% tstart = Screen('Flip', w);
% for i=1:nmaxbench
% Screen('Flip', w, 0, 2, 2);
% end
% tend = Screen('Flip', w);
% fprintf('Average update rate in pipeline was %f Hz.\n', nmaxbench / (tend - tstart));
Screen('Preference','TextAntiAliasing', 1);
% We're done: Close all windows and textures:
sca;
catch %#ok<*CTCH>
%this "catch" section executes in case of an error in the "try" section
%above. Importantly, it closes the onscreen window if its open.
ShowCursor(screenNumber);
sca;
Screen('Preference','TextAntiAliasing', 1);
psychrethrow(psychlasterror);
end %try..catch..
% Restore gfx gammatables if needed:
RestoreCluts;
return;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment