% demoMonoCSF % Draws a variant of a Campbell-Robson CSF chart using a Bits++. % ----------------------------------------------------------------------------- % This demonstration illustrates the use of the high bit depth drawing modes % available on the Bits++ to display (a variant of) the Campbell-Robson % Contrast Sensitivity Function chart. This particular demo uses the high % bit depth mono drawing mode. (14bitGreyScaleMode). Another similar % demonstration is available that uses the high resolution colour mode % (42bitColourMode). % % View the source code for this file for pointers on how to use the high bit % depth mono drawing mode. % Please be aware that in this source description, some of the CSF chart % parameters have been modified to improve it's appearance on screen. % Please do not rely on this file as a reference for how to produce a CSF % chart. % originally written by wp for Visage % converted to Bits++ and OSX Psychtoolbox by ejw clear; close all % Define screen whichScreen=max(Screen('Screens')); % Find the color values which correspond to white and black. Though on OS % X we currently only support true color and thus, for scalar color % arguments, % black is always 0 and white 255, this rule is not true on other platforms will % not remain true on OS X after we add other color depth modes. white=WhiteIndex(whichScreen); black=BlackIndex(whichScreen); gray=GrayIndex(whichScreen); % Open up the a window on the screen. % This is done by calling the Screen function of the Psychophysics % Toolbox. We need to open the onscreen window first, so that % the offscreen storage allocated subsequently is properly % matched to the onscreen frame buffer. [window,screenRect] = Screen('OpenWindow',whichScreen,128,[],32,2); % THE FOLLOWING STEP IS IMPORTANT. % make sure the graphics card LUT is set to a linear ramp % (else the encoded data will not be recognised by Bits++). % There is a bug with the underlying OpenGL function, hence the scaling 0 to 255/256. % This demo will not work using a default gamma table in the graphics card, % or even if you set the gamma to 1.0, due to this bug. % This is NOT a bug with Psychtoolbox! Screen('LoadNormalizedGammaTable',window,linspace(0,(255/256),256)'*ones(1,3)); % draw a gray background on front and back buffers Screen('FillRect',window, gray); Screen('Flip', window); Screen('FillRect',window, gray); % ================================================================= % CODE NEEDED HERE ! % "linear_lut" should be replaced here with one giving the inverse % characteristic of the monitor. % ================================================================= % restore the Mono++ overlay LUT to a linear ramp linear_lut = repmat(round(linspace(0, 2^16 -1, 256))', 1, 3); BitsPlusSetClut(window,linear_lut); % find out how big the window is [POINTS_ACROSS, POINTS_DOWN]=Screen('WindowSize', window); % =========================== % DEFINE SPATIAL FREQUENCY GP % =========================== SF_LOW = 1.5; SF_HIGH = 300; SF_BASE = (SF_HIGH/SF_LOW) .^ (1/POINTS_ACROSS); % base SF_POW = [1:POINTS_ACROSS]; % power SF_FORM = SF_BASE .^ SF_POW; % functional form SF_MUL = (SF_LOW/SF_BASE); % scaling factor SF_VALU = SF_FORM * SF_MUL; % values % ================== % DEFINE CONTRAST GP % ================== CT_LOW = 1/1024; CT_HIGH = 1; CT_BASE = (CT_HIGH/CT_LOW) .^ (1/POINTS_DOWN); % base CT_POW = [1:POINTS_DOWN]; % power CT_FORM = CT_BASE .^ CT_POW; % functional form CT_MUL = (CT_LOW/CT_BASE); % scaling factor CT_VALU = CT_FORM .* CT_MUL; % values % ============================ % FORM IMAGE FROM PROGRESSIONS % ============================ [XGRID,YGRID] = meshgrid(sin(SF_VALU),CT_VALU); % CT & SF are orthogonal IMAGE = XGRID .* YGRID; % contrast modulates amplitude IMAGE = (IMAGE + 1) / 2; % map values to between 0 and 1. % ================================================================== % CODE NEEDED HERE ! % "IMAGE" should be corrected here for the inverse characteristic of % the monitor. % ================================================================== % encode the image in mono++ format encoded_image = BitsPlusPackMonoImage(IMAGE*((2^16)-1)); % put the csf chart image up on the back buffer Screen('PutImage', window, encoded_image); % make the make buffer current during the next blanking period Screen(window,'Flip'); fprintf('Displaying CSF chart, hold a key to exit \n'); while(~KbCheck) end; % if the system only has one screen, set the LUT in Bits++ to a linear ramp % if the system has two or more screens, then blank the screen. if (whichScreen == 0) % ================================================================= % CODE NEEDED HERE ! % "linear_lut" should be replaced here with one giving the inverse % characteristic of the monitor. % ================================================================= % restore the Mono++ overlay LUT to a linear ramp linear_lut = repmat(round(linspace(0, 2^16 -1, 256))', 1, 3); BitsPlusSetClut(window,linear_lut); % draw a gray background on front and back buffers to clear out any old LUTs Screen('FillRect',window, gray); Screen('Flip', window); Screen('FillRect',window, gray); Screen('Flip', window); % Close the window. Screen('CloseAll'); else % Blank the screen (zero the Mono++ overlay LUT), % - doesn't actually quite blank the screen. BitsPlusSetClut(window,zeros(256,3)); % draw a black background on front and back buffers to clear out any old LUTs Screen('FillRect',window, black); Screen('Flip', window); Screen('FillRect',window, black); Screen('Flip', window); Screen('CloseAll'); end