function SpatioTemporal_Binary_White_Noise_Stimulus(varargin) % % %=================================================================================== % Parameter Default Usage %=================================================================================== % % selecttextfile false To call browse prompt to select the parameters text file % stixelwidth 6 Width of each pixel of the checkerboard defined in monitor pixels unit % stixelheight 6 Height of each pixel of the checkerboard defined in monitor pixels unit % blackwhite true Option to switch between Binary and Gaussian white-noise (Not available) % contrast 1 Contrast of black & white stimulus. 1 is 100 contrast. % meanintensity 0.5 Mean intensity value used to define contrast % seed -1000 Starting value for random number generator (should be always negative) % secondseed -10000 Same as seed but for green color (only used if color is true). % thirdseed -2000 Same as seed but for blue color (only used if color is true). % nblinks 2 Number of frames to hold the stimulus on screen (2 is 30 Hz stimulus) % color false Option to switch between black & white and chromatic white-noise % redmeanintensity 0 Mean intensity for red gun of the screen (only used if color is true). % greenmeanintensity 0.5 Mean intensity for green gun of the screen (only used if color is true). % bluemeanintensity 0.5 Mean intensity for blue gun of the screen (only used if color is true). % redcontrast 0 Contrast of red stimulus (only used if color is true). % greencontrast 0.75 Contrast of green stimulus (only used if color is true). % bluecontrast 0.75 Contrast of blue stimulus (only used if color is true). % screensize 864 x 480 Screen resolution, default value is the resolution of the lightcrafter projector % refreshrate 60 Screen refresh rate in Hz % fullscreen false Option to display the stimulus in full-screen mode % help false Option to check the list of available parameters % lmargin 0 Margins from left side of the screen (not available for this stimulus) % rmagin 0 Margins from right side of the screen (not available for this stimulus) % tmargin 0 Margins from top of the screen (not available for this stimulus) % bmargin 0 Margins from bottom of the screen (not available for this stimulus) % coneisolating false Option to activate opsin-isolation (excluded for simplicity) % %==================================================================================== % % para = read_stimulus_parameters(varargin{:}); if para.help, return; end % xax = (para.lmargin+1):para.stixelwidth:(para.screensize(1)-(para.rmargin)); % yax = (para.bmargin+1):para.stixelheight:(para.screensize(2)-(para.tmargin)); xax = linspace(para.lmargin,para.screensize(1)-(para.rmargin),para.Nx)+para.stixelwidth/2; yax = linspace(para.tmargin,para.screensize(2)-(para.bmargin),para.Ny)+para.stixelheight/2; % The darwing of the screen goes here monitorsize = get(0,'ScreenSize'); scpos = [monitorsize(3)/2-(para.screensize(1)/2), ... monitorsize(4)/2-(para.screensize(2)/2), para.screensize]; % make an screen like figure fh = figure('Menu','none','ToolBar','none','Position',scpos,'Color',0.5*[1 1 1]); fh.Name = 'Example of Spatio-temporal White Noise Stimulus, from Khani and Gollisch (2021)'; fh.Colormap = gray; ah = axes('Units','Normalize','Position',[0 0 1 1],'Color',0.5*[1 1 1]); axis(ah,[0, para.screensize(1),0, para.screensize(2)]); axis(ah,'off'); framecounter = 0; if para.color seed1 = para.seed; seed2 = para.secondseed; seed3 = para.thirdseed; redWeberContrastHigh = para.redmeanintensity + (para.redContrast * para.redmeanintensity); redWeberContrastLow = para.redmeanintensity - (para.redContrast * para.redmeanintensity); greenWeberContrastHigh = para.greenmeanintensity + (para.greenContrast * para.greenmeanintensity); greenWeberContrastLow = para.greenmeanintensity - (para.greenContrast * para.greenmeanintensity); blueWeberContrastHigh = para.bluemeanintensity + (para.blueContrast * para.bluemeanintensity); blueWeberContrastLow = para.bluemeanintensity - (para.blueContrast * para.bluemeanintensity); else seed = para.seed; whiteWeberContrastHigh = para.meanintensity + (para.contrast * para.meanintensity); whiteWeberContrastLow = para.meanintensity - (para.contrast * para.meanintensity); end while ishandle(fh) if para.color % red [checkerred, seed1] = ran1(seed1,para.Nx*para.Ny); checkerred = single((checkerred > para.redmeanintensity) .* redWeberContrastHigh); checkerred(checkerred == 0) = redWeberContrastLow; checkerred = reshape(checkerred,para.Ny,para.Nx); % green [checkergreen, seed2] = ran1(seed2,para.Nx*para.Ny); checkergreen = single((checkergreen > para.greenmeanintensity) .* greenWeberContrastHigh); checkergreen(checkergreen == 0) = greenWeberContrastLow; checkergreen = reshape(checkergreen,para.Ny,para.Nx); % blue [checkerblue, seed3] = ran1(seed3,para.Nx*para.Ny); checkerblue = single((checkerblue > para.bluemeanintensity) .* blueWeberContrastHigh); checkerblue(checkerblue == 0) = blueWeberContrastLow; checkerblue = reshape(checkerblue,para.Ny,para.Nx); % put all colors together checker = cat(3,checkerred,checkergreen,checkerblue); else % black & white checker [checker, seed] = ran1(seed,para.Nx*para.Ny); checker = single((checker > para.meanintensity) .* whiteWeberContrastHigh); checker(checker == 0) = whiteWeberContrastLow; checker = reshape(checker,para.Ny,para.Nx); checker = repmat(checker,1,1,3); end if framecounter == 0 rf = imagesc(xax,yax, checker); axis(ah,[0, para.screensize(1),0, para.screensize(2)]); set(ah,'Color',0.5*[1 1 1]); % this is to have gray background with margins else rf.CData = checker; end % this is to draw the frames relatively accurately. drawnow; java.lang.Thread.sleep(para.nblinks/para.refreshrate*1e3); %pause(1/para.refreshrate); framecounter = framecounter+1; end end %--------------------------------------------------------------------------------------------------% %---------- sub-functions ----------% %--------------------------------------------------------------------------------------------------% function paraout = read_stimulus_parameters(varargin) % first parse the user inputs p = inputParser(); % check the user options. validtruefalse = @(x) islogical(x) || (isnumeric(x) && ismember(x,[0,1])); p.addParameter('selecttextfile', false, validtruefalse); p.addParameter('stixelwidth', 6, @isnumeric); p.addParameter('stixelheight', 6, @isnumeric); p.addParameter('blackwhite', true, validtruefalse); p.addParameter('contrast',1, @isnumeric); p.addParameter('meanintensity', 0.5, @isnumeric); p.addParameter('seed', -1000, @isnumeric); p.addParameter('secondseed', -10000, @isnumeric); p.addParameter('thirdseed', -2000, @isnumeric); p.addParameter('nblinks', 2, @isnumeric); p.addParameter('lmargin',0, @isnumeric); p.addParameter('rmargin', 0, @isnumeric); p.addParameter('bmargin', 0, @isnumeric); p.addParameter('tmargin', 0, @isnumeric); p.addParameter('color', false, validtruefalse); p.addParameter('coneisolating', true, validtruefalse); p.addParameter('redmeanintensity', 0, @isnumeric); p.addParameter('greenmeanintensity', 0.5, @isnumeric); p.addParameter('bluemeanintensity', 0.5, @isnumeric); p.addParameter('redContrast', 0, @isnumeric); p.addParameter('greenContrast', 0.75, @isnumeric); p.addParameter('blueContrast', 0.75, @isnumeric); p.addParameter('screensize', [864 480], @isnumeric); p.addParameter('refreshrate', 60, @isnumeric); p.addParameter('fullscreen', false, validtruefalse); p.addParameter('help', false, validtruefalse); p.parse(varargin{:}); % defualt parameters defpara = p.Results; if defpara.help help_info_for_parameters(defpara); paraout = defpara; return; end if defpara.selecttextfile % now read the text files [stimfile, stimpath] = uigetfile('*.txt','Select a chromatic integration stimulus parameter file','chromatic_integration.txt'); fid = fopen([stimpath,filesep,stimfile]); tline = fgetl(fid); while ischar(tline) tline = fgetl(fid); if tline == -1, break; end fn = extractBefore(tline,' = '); if isempty(fn), continue; end val = extractAfter(tline,' = '); % to convert to double if ~isnan(str2double(val)) val = str2double(val); end % to convert to logical if strcmp(val,'true'), val = true; end if strcmp(val,'false'), val = false; end % store the values in a structure stimpara.(fn) = val; end fclose(fid); % compare the text file to the defualt values and fill the missing parameters fn = fieldnames(defpara); for ii = 1:numel(fn) if isfield(stimpara,fn{ii}) paraout.(fn{ii}) = stimpara.(fn{ii}); else paraout.(fn{ii}) = defpara.(fn{ii}); end end else paraout = defpara; end % stimsize = [0+para.bmargin, 0+para.lmargin, para.screensize(1)-para.rmargin,... % para.screensize(2)-para.tmargin]; xpixels = paraout.screensize(1) - (paraout.lmargin + paraout.rmargin); ypixels = paraout.screensize(2) - (paraout.tmargin + paraout.bmargin); paraout.Nx = ceil(xpixels / paraout.stixelwidth); paraout.Ny = ceil(ypixels / paraout.stixelheight); if paraout.stixelwidth > xpixels, paraout.stixelwidth = xpixels-1; end if paraout.stixelheight > ypixels, paraout.stixelheight = ypixels-1; end if paraout.fullscreen monitorsize = get(0,'ScreenSize'); paraout.screensize = monitorsize(3:4) ; end end %--------------------------------------------------------------------------------------------------% function help_info_for_parameters(defpara) fn = fieldnames(defpara); fprintf(['\n\n',repmat('==',1,50),'\r\n']); fprintf([repmat(' ',1,35),'List of Stimulus Parameters\r\n']); fprintf([repmat('==',1,50),'\r\n']); maxtxtlen = max(cellfun(@numel,fn))+10; for ii = 1:numel(fn) g = repmat(' ',1,maxtxtlen - numel(fn{ii})); fprintf(['\t-- \t%s',g,':',repmat(' ',1,10),'%s\n'],fn{ii},num2str(defpara.(fn{ii}))); end fprintf(['\n',repmat('==',1,50),'\r\n']); end