-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathVS_driftingGrating.m
159 lines (130 loc) · 6.82 KB
/
VS_driftingGrating.m
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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
classdef VS_driftingGrating < VStim
properties
%all these properties are modifiable by user and will appear in visual stim GUI
%Place all other variables in hidden properties
angles=12;
minFreq=.1;
maxFreq=2;
freqStep=.3;
minSpatialFreq=.01;
maxSpatialFreq=.5;
spatialFreqStep=0.05;
contrast = .5;
end
properties (Hidden,Constant)
defaultStimDuration=5; %stim duration in [sec] of each grating
defaultVisualFieldBackgroundLuminance=0;
defaultTrialsPerCategory=50; %number of gratings to present
screenSizeCm=[52 32];
stimRadiousTxt='radious of stimulus';
contrastTxt='% of dynamic range to use';
anglesTxt='Number of tilt angles of the grating';
minFreqTxt='min temp freq (Hz)';
maxFreqTxt='max temp freq (Hz)';
freqStepTxt='step stize for temp freq';
minSpatialFreqTxt='min spatial freq (cycles/cm) screen size in cm is a paramter below';
maxSpatialFreqTxt='max spatial freq (cycles/cm) screen size in cm is a paramter below';
spatialFreqStepTxt='step stize for spatial freq';
remarks={''};
end
properties (Hidden, SetAccess=protected)
tempFreq
spatialFreq
angleOrder
stimOnset
flipOffsetTimeStamp
flipMiss
flipOnsetTimeStamp
centerXs
centerYs
end
methods
function obj=run(obj)
screenProps=Screen('Resolution',obj.PTB_win(1));
ifi = Screen('GetFlipInterval', obj.PTB_win(1));
pixPerCm=screenProps.width/obj.screenSizeCm(1)
% Initial stimulus parameters for the grating patch:
rotateMode = kPsychUseTextureMatrixForRotation;
% res is the total size of the patch in x- and y- direction, i.e., the
% width and height of the mathematical support.
res = [screenProps.width screenProps.height];
amplitude=0.5*obj.contrast; %halve it to make it compatible with demo
% Retrieve video redraw interval for later control of our animation timing:
ifi = Screen('GetFlipInterval', obj.PTB_win(1));
% Phase is the phase shift in degrees (0-360 etc.)applied to the sine grating:
phase = 0;
% Build a procedural sine grating texture for a grating with a support of
% res(1) x res(2) pixels and a RGB color offset of 0.5 -- a 50%
% gray. Change it's center to the user defined location
%do it blue for the cephs to avoid weird rainbow striping from the monitor
for j=1:obj.nPTBScreens
[gratingtex(j)] = CreateProceduralSineGrating(obj.PTB_win(j), res(1), res(2), [0 0 0.5 1.0],[],0.5);
end
obj.spatialFreq=[];
%load up the range of parameters that are going to be presented
anglesToPresent=[0:round(360/obj.angles):360]; %nice to have it divisible by 360
cyclespersecond=obj.minFreq:obj.freqStep:obj.maxFreq;
spatialFreq=(obj.minSpatialFreq:obj.spatialFreqStep:obj.maxSpatialFreq)/ pixPerCm;
obj.tempFreq=cyclespersecond(ceil(rand(obj.trialsPerCategory,1)*length(cyclespersecond)));
obj.angleOrder=anglesToPresent(ceil(rand(obj.trialsPerCategory,1)*length(anglesToPresent)));
spatialFreq=spatialFreq(ceil(rand(obj.trialsPerCategory,1)*length(spatialFreq)));
obj.spatialFreq=spatialFreq*pixPerCm;
% Compute increment of phase shift per redraw:
phaseincrement = (obj.tempFreq * 360) * ifi;
vbl = Screen('Flip', obj.PTB_win(1));
%make sure there are an even number of frames for led syncing
numFrames=round(1/ifi*obj.stimDuration);
if mod(numFrames,2) == 1
numFrames=numFrames-1;
end
%Pre allocate memory for variables
% obj.stim_onset=nan(obj.trialsPerCategory,obj.numberOfFrames+1);
obj.flipOnsetTimeStamp=nan(obj.trialsPerCategory,numFrames); %when the flip happened
obj.stimOnset=nan(obj.trialsPerCategory,numFrames); %estimate of stim onset
obj.flipOffsetTimeStamp=nan(obj.trialsPerCategory,numFrames); %flip done
obj.flipMiss=nan(obj.trialsPerCategory,numFrames);
WaitSecs(obj.preSessionDelay);
% Animation loop
for i=1:obj.trialsPerCategory
disp(['Trial ' num2str(i) '/' num2str(obj.trialsPerCategory)]);
obj.sendTTL(1,true);
% Screen('FillOval',obj.PTB_win(1),obj.visualFieldBackgroundLuminance);
for frame= 1: numFrames
phase = phase + phaseincrement(i);
for j=1:obj.nPTBScreens
Screen('DrawTexture', obj.PTB_win(j), gratingtex(j), [], [], obj.angleOrder(i), [], [], [], [], rotateMode, [phase, spatialFreq(i), amplitude, 0]);
end
obj.applyBackgound;
obj.sendTTL(2,true);
for j=1:obj.nPTBScreens
[obj.flipOnsetTimeStamp(i,frame),obj.stimOnset(i,frame),obj.flipOffsetTimeStamp(i,frame),obj.flipMiss(i,frame)]=Screen('Flip',obj.PTB_win(j), vbl + 0.5 * ifi);
end
obj.sendTTL(2,false);
Screen('DrawingFinished', obj.PTB_win(1)); % Tell PTB that no further drawing commands will follow before Screen('Flip')
end
for j=1:obj.nPTBScreens
Screen('FillRect',obj.PTB_win(j),[0,0,obj.visualFieldBackgroundLuminance]);
end
obj.applyBackgound;
for j=1:obj.nPTBScreens
Screen('Flip',obj.PTB_win(j));
end
% WaitSecs(obj.interTrialDelay);
obj.sendTTL(1,false);
WaitSecs(obj.interTrialDelay);
disp('Trial ended');
end
WaitSecs(obj.postSessionDelay);
disp('Session ended');
end
%class constractor
function obj=VS_driftingGrating(w,h)
%get the visual stimulation methods
obj = obj@VStim(w); %calling superclass constructor
obj.stimDuration=obj.defaultStimDuration;
obj.visualFieldBackgroundLuminance=obj.defaultVisualFieldBackgroundLuminance;
obj.trialsPerCategory=obj.defaultTrialsPerCategory;
%obj.hInteractiveGUI=h;
end
end
end %EOF