Browse Source

added stimulation functions to recreate different stimuli

MHK 3 years ago
parent
commit
5df69e735e

+ 267 - 0
Stimulation/Chromatic_Grating_Stimulus.m

@@ -0,0 +1,267 @@
+
+function Chromatic_Grating_Stimulus(varargin)
+
+%===================================================================================
+% Parameter             Default                     Usage
+%===================================================================================
+%
+% selecttextfile        false           Browse prompt to select the parameters text file
+% stimduration          600             Stimulus presentation duration in refresh rate unit (600 = 10 sec).
+% period                60              Duration for one period of the grating in refresh rate unit (60 = 1 sec).
+% gratingwidth          60              Grating widths in pixels
+% squarewave            false           Option to switch between sinusoid and square-wave gratings
+% maxcontrast           0.2             Maximum Weber contrast value (ranges from -1 to 1)
+% mincontrast           -0.2            Minimum Weber contrast value (ranges from -1 to 1)
+% contrastdiff          0.02            Contrast steps from mincontrast to maxcontrast e.g. -20 : 2 : 20
+% seed                  -1000           Starting value for random number generator (should be always negative)
+% redmeanintensity      0               Mean intensity for red gun of the screen
+% greenmeanintensity	0.5             Mean intensity for green gun of the screen
+% bluemeanintensity     0.5             Mean intensity for blue gun of the screen
+% 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
+
+% first make the contrast lists
+offcontrasts    =   fliplr(0:-para.contrastdiff:para.mincontrast);
+oncontrasts     =   0:para.contrastdiff:para.maxcontrast;
+% put the lists together
+greencontrasts  =   [offcontrasts,oncontrasts];
+bluecontrasts   =   [oncontrasts,offcontrasts];
+
+numcontrasts    =   size(greencontrasts,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 Chromatic Grating Stimulus, from Khani and Gollisch (2021)';
+fh.Colormap =   gray;
+ah          =   axes('Units','Normalize','Position',[0 0 1 1]);
+axis(ah,[0, para.screensize(1),0, para.screensize(2)]);
+axis(ah,'off');
+
+framecounter=   0;
+seed        =   para.seed;
+
+while ishandle(fh)
+    
+    
+    frameMod        =   mod(framecounter,para.stimduration);
+    colorindexMod   =   floor(mod(framecounter/para.stimduration,numcontrasts));
+    
+    % resest the color order using Fisher-Yates random permutations
+    if colorindexMod == 0 && frameMod == 0
+        [colorder, seed]    =   fisher_Yates_shuffle_order(seed,1:numcontrasts);
+    end
+    
+    
+    thisphase   =  single(mod(framecounter / para.period + (1:para.screensize(1)) / (para.gratingwidth), 1));
+    
+    grcont = greencontrasts( colorder( colorindexMod+1 ));
+    blucont = bluecontrasts( colorder( colorindexMod+1 ));
+    
+    if para.squarewave
+        % make squarewave gratings
+        g = (thisphase < 0.5) .* grcont;
+        g(thisphase >= 0.5) = g(thisphase >= 0.5) .* (-grcont);
+        
+        b = (thisphase < 0.5) .* blucont;
+        b(thisphase >= 0.5) = b(thisphase >= 0.5) .* (-blucont);
+    else
+        % make sinosoial gratings
+        g   =   sin(2 * pi* thisphase) .* grcont;
+        b   =   sin(2 * pi* thisphase) .* blucont;
+    end
+    % convert to weber contrast
+    g   =   para.greenmeanintensity + (g .* para.greenmeanintensity);
+    b   =   para.bluemeanintensity + (b .* para.bluemeanintensity);
+    
+    % put together and make a 2d image
+    stimframe   =   repmat(cat(3,g.*0,g,b),para.screensize(2),1);
+    
+    
+    if framecounter == 0
+        s                      =   imagesc(stimframe);
+        axis(ah,[0, para.screensize(1),0, para.screensize(2)]);
+    else
+        s.CData                =   stimframe;
+    end
+    
+    % this is to draw the frames relatively accurately.
+    drawnow;
+    java.lang.Thread.sleep(1/para.refreshrate*1e3);
+    %pause(1/para.refreshrate);
+    framecounter    =   framecounter+1;
+end
+
+end
+
+%--------------------------------------------------------------------------------------------------%
+%----------                               sub-functions                                  ----------%
+%--------------------------------------------------------------------------------------------------%
+
+
+function varargout = fisher_Yates_shuffle_order(seed,inputVec,varargin)
+%
+%%% fisher_Yates_shuffle_order %%%
+%
+%
+% This function generate psudorandom permution similar to randperm in MATLAB
+% but works with psudorandom number generator ran1. It also gives back the
+% most recent seed value to continue the permuation in case of repeated trials.
+% note that the direction of permutation is along x-axix or for columns of
+% MATALB not for the rows.
+%
+%
+% ===============================Inputs====================================
+%
+%   seed : seed value for random number generation.
+%   inputVec : input vector used for permutation.
+%
+%================================Output====================================
+%
+%   testOrder : vector of permuted indices for the inputVec.
+%   newSeed : the recent seed that used in the ran1 function.
+%   outputVec : the permuted input vector along x-axis
+%
+% Note that the permution algorithem is based on Fisher-Yates shuffle
+% algorithem identical to what is used in the stimulus program.
+% for more info check :
+% https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
+%
+% written by Mohammad, 01.02.2016
+
+newSeed         =   seed;
+testOrder       =   zeros(1,size(inputVec,2));
+testOrder(1)    =   1;
+
+for i   =   2:length(inputVec)-1
+    
+    [randVal,newSeed] = ran1(newSeed);
+    
+    j               =   ceil(i*randVal);    % based on Fischer-Yates algorithem
+    testOrder(i)    =   testOrder(j);
+    testOrder(j)    =   i;
+    
+end
+
+testOrder           =   [testOrder(end),testOrder(1:end-1)]+1;   % to match MATLAB indexing
+varargout{1}        =   testOrder;
+varargout{2}        =   newSeed;
+for j   =   1:size(inputVec,1)
+    varargout{3}(j,:)   =   inputVec(j,testOrder);
+end
+
+end
+
+%--------------------------------------------------------------------------------------------------%
+
+function paraout = read_stimulus_parameters(varargin)
+
+% first parse the user inputs
+p = inputParser();      % check the user options.
+p.addParameter('selecttextfile', false,  @(x) islogical(x) || (isnumeric(x) && ismember(x,[0,1])));
+p.addParameter('stimduration', 600, @isnumeric);
+p.addParameter('period', 60, @isnumeric);
+p.addParameter('gratingwidth', 60, @isnumeric);
+p.addParameter('squarewave', false, @(x) islogical(x) || (isnumeric(x) && ismember(x,[0,1])));
+p.addParameter('contrastdiff', 0.02, @isnumeric);
+p.addParameter('mincontrast',-0.2, @isnumeric);
+p.addParameter('maxcontrast', 0.2, @isnumeric);
+p.addParameter('seed', -1000, @isnumeric);
+p.addParameter('redmeanintensity', 0, @isnumeric);
+p.addParameter('greenmeanintensity', 0.5, @isnumeric);
+p.addParameter('bluemeanintensity', 0.5, @isnumeric);
+p.addParameter('lmargin',0, @isnumeric);
+p.addParameter('rmargin', 0, @isnumeric);
+p.addParameter('bmargin', 0, @isnumeric);
+p.addParameter('tmargin', 0, @isnumeric);
+p.addParameter('coneisolating', true,  @(x) islogical(x) || (isnumeric(x) && ismember(x,[0,1])));
+p.addParameter('screensize', [864 480], @isnumeric);
+p.addParameter('refreshrate', 60, @isnumeric);
+p.addParameter('fullscreen', false,  @(x) islogical(x) || (isnumeric(x) && ismember(x,[0,1])));
+p.addParameter('help', false,  @(x) islogical(x) || (isnumeric(x) && ismember(x,[0,1])));
+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
+
+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

+ 248 - 0
Stimulation/Chromatic_Integration_Stimulus.m

@@ -0,0 +1,248 @@
+
+
+function Chromatic_Integration_Stimulus(varargin)
+
+%===================================================================================
+% Parameter             Default                     Usage
+%===================================================================================
+
+% selecttextfile        false       Browse prompt to select the parameters text file
+% stimduration          30          Stimulus presentation duration screen refresh rate unit (30 = 0.5 sec)
+% preframes             120         Duration of background light presented in between the stimulus flashes
+% maxcontrast           0.2         Maximum Weber contrast value (ranges from -1 to 1)
+% mincontrast          -0.2         Minimum Weber contrast value (ranges from -1 to 1)
+% contrastdiff          0.02        Contrast steps from mincontrast to maxcontrast e.g. -20 : 2 : 20
+% seed                  -1000   	Starting value for random number generator (should be always negative)
+% redmeanintensity        0     	Mean intensity for red gun of the screen
+% greenmeanintensity	0.5         Mean intensity for green gun of the screen
+% bluemeanintensity     0.5     	Mean intensity for blue gun of the screen
+% 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
+
+offcontrasts    =   fliplr(0:-para.contrastdiff:para.mincontrast);
+oncontrasts     =   0:para.contrastdiff:para.maxcontrast;
+
+greencontrasts  =   [offcontrasts,oncontrasts];
+bluecontrasts   =   [oncontrasts,offcontrasts];
+
+% convert to weber contrast (mean+(contrast*mean))
+greencontrasts  =   para.greenmeanintensity + (greencontrasts * para.greenmeanintensity);
+bluecontrasts   =   para.bluemeanintensity + (bluecontrasts * para.bluemeanintensity);
+
+numcontrasts    =   size(greencontrasts,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 Chromatic Integration Stimulus, from Khani and Gollisch (2021)';
+fh.Colormap =   gray;
+ah          =   axes('Units','Normalize','Position',[0 0 1 1]);
+                axis(ah,[0, para.screensize(1),0, para.screensize(2)]);
+                axis(ah,'off');
+
+stimsize    =   [0+para.bmargin, 0+para.lmargin, para.screensize(1)-para.rmargin,...
+                para.screensize(2)-para.tmargin];
+framecounter=   0;
+seed        =   para.seed;
+
+while ishandle(fh)
+    
+    if framecounter == 0
+        % start with gray screen
+        r= rectangle('pos',stimsize,'facecolor',[0.5 0.5 0.5],'edgecolor','none');
+    end
+    
+    frameMod        =   mod(framecounter,para.stimduration + para.preframes);
+    colorindexMod   =   floor(mod((framecounter)/(para.stimduration+para.preframes),numcontrasts));
+    
+    % resest the color order using Fisher-Yates random permutations
+    if colorindexMod == 0 && frameMod == 0
+        [colorder, seed]    =   fisher_Yates_shuffle_order(seed,1:numcontrasts);
+    end
+    
+    % show gray screen in between stimulus frames
+    if frameMod < (para.preframes)
+        r.FaceColor =   [0.5 0.5 0.5]; % gray screen during preframes
+    else
+        r.FaceColor =   [0, greencontrasts(colorder(colorindexMod+1)), bluecontrasts(colorder(colorindexMod+1))];
+    end
+    
+    % this is to draw the frames relatively accurately.
+    drawnow;
+    java.lang.Thread.sleep(1/para.refreshrate*1e3);
+    %pause(1/para.refreshrate);
+    framecounter    =   framecounter+1;
+end
+
+end
+
+%--------------------------------------------------------------------------------------------------%
+%----------                               sub-functions                                  ----------%
+%--------------------------------------------------------------------------------------------------%
+
+
+function varargout = fisher_Yates_shuffle_order(seed,inputVec,varargin)
+%
+%%% fisher_Yates_shuffle_order %%%
+%
+%
+% This function generate psudorandom permution similar to randperm in MATLAB
+% but works with psudorandom number generator ran1. It also gives back the
+% most recent seed value to continue the permuation in case of repeated trials.
+% note that the direction of permutation is along x-axix or for columns of
+% MATALB not for the rows.
+%
+%
+% ===============================Inputs====================================
+%
+%   seed : seed value for random number generation.
+%   inputVec : input vector used for permutation.
+%
+%================================Output====================================
+%
+%   testOrder : vector of permuted indices for the inputVec.
+%   newSeed : the recent seed that used in the ran1 function.
+%   outputVec : the permuted input vector along x-axis
+%
+% Note that the permution algorithem is based on Fisher-Yates shuffle
+% algorithem identical to what is used in the stimulus program.
+% for more info check :
+% https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
+%
+% written by Mohammad, 01.02.2016
+
+newSeed         =   seed;
+testOrder       =   zeros(1,size(inputVec,2));
+testOrder(1)    =   1;
+
+for i   =   2:length(inputVec)-1
+    
+    [randVal,newSeed] = ran1(newSeed);
+    
+    j               =   ceil(i*randVal);    % based on Fischer-Yates algorithem
+    testOrder(i)    =   testOrder(j);
+    testOrder(j)    =   i;
+    
+end
+
+testOrder           =   [testOrder(end),testOrder(1:end-1)]+1;   % to match MATLAB indexing
+varargout{1}        =   testOrder;
+varargout{2}        =   newSeed;
+for j   =   1:size(inputVec,1)
+    varargout{3}(j,:)   =   inputVec(j,testOrder);
+end
+
+end
+
+%--------------------------------------------------------------------------------------------------%
+
+function paraout = read_stimulus_parameters(varargin)
+
+% first parse the user inputs
+p = inputParser();      % check the user options.
+p.addParameter('selecttextfile', false,  @(x) islogical(x) || (isnumeric(x) && ismember(x,[0,1])));
+p.addParameter('stimduration', 30, @isnumeric);
+p.addParameter('preframes', 120, @isnumeric);
+p.addParameter('contrastdiff', 0.02, @isnumeric);
+p.addParameter('mincontrast',-0.2, @isnumeric);
+p.addParameter('maxcontrast', 0.2, @isnumeric);
+p.addParameter('seed', -1000, @isnumeric);
+p.addParameter('redmeanintensity', 0, @isnumeric);
+p.addParameter('greenmeanintensity', 0.5, @isnumeric);
+p.addParameter('bluemeanintensity', 0.5, @isnumeric);
+p.addParameter('lmargin',0, @isnumeric);
+p.addParameter('rmargin', 0, @isnumeric);
+p.addParameter('bmargin', 0, @isnumeric);
+p.addParameter('tmargin', 0, @isnumeric);
+p.addParameter('coneisolating', true,  @(x) islogical(x) || (isnumeric(x) && ismember(x,[0,1])));
+p.addParameter('screensize', [864 480], @isnumeric);
+p.addParameter('refreshrate', 60, @isnumeric);
+p.addParameter('fullscreen', false,  @(x) islogical(x) || (isnumeric(x) && ismember(x,[0,1])));
+p.addParameter('help', false,  @(x) islogical(x) || (isnumeric(x) && ismember(x,[0,1])));
+
+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
+
+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 

+ 371 - 0
Stimulation/Local_Chromatic_Integration_Stimulus.m

@@ -0,0 +1,371 @@
+
+
+function Local_Chromatic_Integration_Stimulus(varargin)
+%
+%===================================================================================
+% Parameter             Default                     Usage
+%===================================================================================
+%
+% selecttextfile        false           Browse prompt to select the parameters text file
+% stimduration          600             Stimulus presentation duration in refresh rate unit (600 = 10 sec).
+% maxcontrast           0.2             Maximum Weber contrast value (ranges from -1 to 1)
+% mincontrast           -0.2            Minimum Weber contrast value (ranges from -1 to 1)
+% contrastdiff          0.02            Contrast steps from mincontrast to maxcontrast e.g. -20 : 2 : 20
+% stixelwidth           20              Width of each local stimulus in pixels
+% stixelheight          20              Height of each local stimulus in pixels
+% gapwidth              2               Number of locations to be avoided around each locally selected stimulus area
+% gapheight             2               Same as gapwidth but for the y-axis of each selected location
+% seedlocation          -1000           Seed for random number generator for locations’ list (should be negative)
+% seedonoroffpixels     -10000          Seed for random number generator of binary contrasts (not used here)
+% seedcolorcontrast     -2000           Seed for random number generator for color contrast list (should be negative)
+% redmeanintensity      0               Mean intensity for red gun of the screen
+% greenmeanintensity	0.5             Mean intensity for green gun of the screen
+% bluemeanintensity     0.5             Mean intensity for blue gun of the screen
+% screensize            864 x 480       Screen resolution, default value is the resolution of the lightcrafter projector
+% refreshrate           60              Screen refresh rate in Hz
+% drawcircle            true            Option to display stimulus as circle or squares
+% drawannulus           false           Option to display the stimulus as annulus (not available for this stimulus)
+% 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
+
+
+offcontrasts    =   fliplr(0:-para.contrastdiff:para.mincontrast);
+oncontrasts     =   0:para.contrastdiff:para.maxcontrast;
+
+greencontrasts  =   [offcontrasts,oncontrasts];
+bluecontrasts   =   [oncontrasts,offcontrasts];
+
+% convert to weber contrast (mean+(contrast*mean))
+greencontrasts  =   para.greenmeanintensity + (greencontrasts * para.greenmeanintensity);
+bluecontrasts   =   para.bluemeanintensity + (bluecontrasts * para.bluemeanintensity);
+
+% first get the corrdinates of all the locations
+[f, v]          =   draw_locations(para);
+
+% 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 Local Chromatic Integration Stimulus, from Khani and Gollisch (2021)';
+fh.Colormap =   gray;
+ah          =   axes('Units','Normalize','Position',[0 0 1 1]);
+                axis(ah,[0, para.screensize(1),0, para.screensize(2)]);
+                axis(ah,'off');
+
+% inital variables
+framecounter=   0;
+seedlocation    =   para.seedlocation;      % to randomize locations
+seedcolor       =   para.seedcolorcontrast; % to randomize contrast order
+stimdur         =   ceil((para.stimduration ./ para.refreshrate)/ 0.5); % start by an estimate of one cycle
+
+while ishandle(fh)
+    
+    if framecounter == 2,   tic;    end     % start the timer on the second frame
+    frameMod        =   mod(framecounter,stimdur);
+    
+    if frameMod     ==  0
+        [contrastlist, seedlocation, seedcolor] = select_sparse_locations(seedlocation, seedcolor, greencontrasts, bluecontrasts, para);
+    end
+    if framecounter ==  0
+        p   =     patch('Faces',f,'Vertices',v,'FaceVertexcData',contrastlist,'Facecolor','Flat','edgecolor','none');
+    else
+        p.FaceVertexCData            =          contrastlist;
+    end
+     
+    % this is to draw the frames relatively accurately.
+    drawnow;
+    java.lang.Thread.sleep(1/para.refreshrate*1e3);
+    %pause(1/para.refreshrate);
+    if framecounter == 2
+       t            =  toc; % take the time of one trial and adjust the time based on that.
+       stimdur      =  ceil((para.stimduration ./ para.refreshrate)/ t); 
+    end
+    
+    framecounter    =   framecounter+1;
+end
+
+end
+
+%--------------------------------------------------------------------------------------------------%
+%----------                               sub-functions                                  ----------%
+%--------------------------------------------------------------------------------------------------%
+
+function varargout = fisher_Yates_shuffle_order(seed,inputVec,varargin)
+%
+%%% fisher_Yates_shuffle_order %%%
+%
+%
+% This function generate psudorandom permution similar to randperm in MATLAB
+% but works with psudorandom number generator ran1. It also gives back the
+% most recent seed value to continue the permuation in case of repeated trials.
+% note that the direction of permutation is along x-axix or for columns of
+% MATALB not for the rows.
+%
+%
+% ===============================Inputs====================================
+%
+%   seed : seed value for random number generation.
+%   inputVec : input vector used for permutation.
+%
+%================================Output====================================
+%
+%   testOrder : vector of permuted indices for the inputVec.
+%   newSeed : the recent seed that used in the ran1 function.
+%   outputVec : the permuted input vector along x-axis
+%
+% Note that the permution algorithem is based on Fisher-Yates shuffle
+% algorithem identical to what is used in the stimulus program.
+% for more info check :
+% https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
+%
+% written by Mohammad, 01.02.2016
+
+newSeed         =   seed;
+testOrder       =   zeros(1,size(inputVec,2));
+testOrder(1)    =   1;
+
+for i   =   2:length(inputVec)-1
+    
+    [randVal,newSeed] = ran1(newSeed);
+    
+    j               =   ceil(i*randVal);    % based on Fischer-Yates algorithem
+    testOrder(i)    =   testOrder(j);
+    testOrder(j)    =   i;
+    
+end
+
+testOrder           =   [testOrder(end),testOrder(1:end-1)]+1;   % to match MATLAB indexing
+varargout{1}        =   testOrder;
+varargout{2}        =   newSeed;
+for j   =   1:size(inputVec,1)
+    varargout{3}(j,:)   =   inputVec(j,testOrder);
+end
+
+end
+
+%--------------------------------------------------------------------------------------------------%
+
+
+function [f, v] = draw_locations(para)
+
+Nx      =   ceil(para.screensize(1)/para.stixelwidth);
+Ny      =   ceil(para.screensize(2)/para.stixelheight);
+
+if para.drawcircle,     numpoints = 100;        else,    numpoints = 5;     end
+
+locs    =   nan(Nx*Ny,numpoints,2);
+iter    =   1;
+for ii  =   1 : para.stixelheight : para.screensize(2)
+    for jj  =   1 : para.stixelwidth : para.screensize(1)
+        if para.drawcircle
+            locs(iter,1:numpoints,1)    =   jj + ((para.stixelwidth/2).*cos(linspace(0, 2*pi,numpoints))) - para.stixelwidth/2;
+            locs(iter,1:numpoints,2)    =   ii + ((para.stixelheight/2).*sin(linspace(0, 2*pi,numpoints))) - para.stixelheight/2;
+        else % little hack to draw squares
+            locs(iter,1:numpoints,1)    =   [jj, jj+para.stixelwidth, jj+para.stixelwidth, jj, jj]-para.stixelwidth;
+            locs(iter,1:numpoints,2)    =   [ii, ii, ii+para.stixelheight, ii+para.stixelheight,ii]-para.stixelheight;
+        end
+        iter                            =   iter+1;
+    end
+end
+x       =   squeeze(locs(:,:,1))';
+y       =   squeeze(locs(:,:,2))';
+
+f       =   reshape(1:Nx*Ny*numpoints,numpoints,Nx*Ny)';    % faces for patch fuction
+v       =   [x(:),y(:)];                                    % vertices for patch function
+%c      =   repmat(0.5*[1 1 1],Nx*Ny,1);                    % colors for patch function
+end
+
+%--------------------------------------------------------------------------------------------------%
+
+function [stimMat, seedlocationout, seedcolorout] = select_sparse_locations(seedlocation, seedcolor, greencontrasts, bluecontrasts, para)
+
+numcontrasts    =   size(greencontrasts,2);
+Nx              =   ceil(para.screensize(1)/para.stixelwidth);
+Ny              =   ceil(para.screensize(2)/para.stixelheight);
+
+stimMat         =   zeros(Ny*Nx,3)+0.5;         % set all locations to gray
+locationlist    =   (0:Nx*Ny-1)';
+neighbourlist   =   get_neighbourlist(Nx, Ny, para.gapwidth, para.gapheight);
+
+% make an estimate of all possible locations
+possibleXYlocs  =   zeros(floor(numel(locationlist)/min(cellfun(@numel,neighbourlist))),1);
+
+%outside loop is faster
+[randvals, seedlocationout]   =   ran1(seedlocation, numel(possibleXYlocs));
+randIdx         =   1;
+
+availablelist   =   locationlist;
+currXYlocs      =   possibleXYlocs;
+idx             =   1;
+
+while numel(availablelist)>0
+    
+    randval     =   randvals(randIdx);
+    randIdx     =   randIdx + 1;
+    stixelInd   =   floor(randval * size(availablelist,1)) + 1;
+    toadd       =   availablelist(stixelInd);
+    toremove    =   neighbourlist{Ny * mod(toadd,Nx) + floor(toadd/Nx)+1};
+    %using the mex function for speed
+    % availablelist(builtin('_ismemberoneoutput',availablelist,sort(toremove)))=[];
+    % this is for older matlab, for new matlab use the line below
+    availablelist(ismembc(availablelist,sort(toremove)))    =   [];
+    
+    currXYlocs(idx)     =   toadd+1;
+    idx         =   idx + 1;
+end
+
+contlist        =   cell(1,ceil((idx-1)/length(1:numcontrasts)));
+for jj  =    1:ceil((idx-1) / length(1 : numcontrasts))
+    [contlist{jj}, seedcolor] = fisher_Yates_shuffle_order(seedcolor, 1:numcontrasts);
+end
+seedcolorout    =   seedcolor;
+contindices     =   cell2mat(contlist)';
+%contperframe = contindices(1:idx-1);
+stimMat(currXYlocs(1:idx-1),1)      =   0;
+stimMat(currXYlocs(1:idx-1),2)      =   greencontrasts (contindices(1:idx-1));
+stimMat(currXYlocs(1:idx-1),3)      =   bluecontrasts (contindices(1:idx-1));
+
+end
+
+%--------------------------------------------------------------------------------------------------%
+
+function neighbourlist = get_neighbourlist(nx, ny, gapx, gapy)
+
+neighbourlist       =       cell(nx*ny,1);
+idx                 =       1;
+for x   =   0: nx-1
+    for y   =   0: ny-1
+        localneigbour       =       [];
+        for currX           = x-gapx : x+gapx
+            for currY       = y-gapy : y+gapy
+                if (currX  >= 0 && currY >= 0 )
+                    localneigbour   =   [localneigbour, nx * currY + currX];    %#ok
+                end
+            end
+        end
+        neighbourlist{idx}      =    localneigbour;
+        idx                     =    idx+1;
+    end
+end
+
+end
+
+%--------------------------------------------------------------------------------------------------%
+
+function paraout = read_stimulus_parameters(varargin)
+
+% first parse the user inputs
+p = inputParser();      % check the user options.
+p.addParameter('selecttextfile', false,  @(x) islogical(x) || (isnumeric(x) && ismember(x,[0,1])));
+p.addParameter('stimduration', 30, @isnumeric);
+p.addParameter('contrastdiff', 0.02, @isnumeric);
+p.addParameter('mincontrast',-0.2, @isnumeric);
+p.addParameter('maxcontrast', 0.2, @isnumeric);
+
+p.addParameter('stixelwidth', 20, @isnumeric);
+p.addParameter('stixelheight', 20, @isnumeric);
+p.addParameter('gapwidth', 2, @isnumeric);
+p.addParameter('gapheight', 2, @isnumeric);
+
+p.addParameter('seedlocation', -1000, @isnumeric);
+p.addParameter('seedonoroffpixels', -10000, @isnumeric);
+p.addParameter('seedcolorcontrast', -2000, @isnumeric);
+
+p.addParameter('redmeanintensity', 0, @isnumeric);
+p.addParameter('greenmeanintensity', 0.5, @isnumeric);
+p.addParameter('bluemeanintensity', 0.5, @isnumeric);
+p.addParameter('lmargin',0, @isnumeric);
+p.addParameter('rmargin', 0, @isnumeric);
+p.addParameter('bmargin', 0, @isnumeric);
+p.addParameter('tmargin', 0, @isnumeric);
+p.addParameter('coneisolating', true,  @(x) islogical(x) || (isnumeric(x) && ismember(x,[0,1])));
+p.addParameter('drawcircle', true, @(x) islogical(x) || (isnumeric(x) && ismember(x,[0,1])));
+p.addParameter('drawannulus', false, @(x) islogical(x) || (isnumeric(x) && ismember(x,[0,1])));
+p.addParameter('screensize', [864 480], @isnumeric);
+p.addParameter('refreshrate', 60, @isnumeric);
+p.addParameter('fullscreen', false,  @(x) islogical(x) || (isnumeric(x) && ismember(x,[0,1])));
+p.addParameter('help', false,  @(x) islogical(x) || (isnumeric(x) && ismember(x,[0,1])));
+
+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
+
+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 

+ 245 - 0
Stimulation/SpatioTemporal_Binary_White_Noise_Stimulus.m

@@ -0,0 +1,245 @@
+
+
+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

BIN
Stimulation/ran1.mexw64