Skip to content

Commit 93ab890

Browse files
Merge pull request #4 from cpp-lln-lab/master
update origin
2 parents 46674f1 + 6069a96 commit 93ab890

File tree

6 files changed

+557
-5
lines changed

6 files changed

+557
-5
lines changed

README.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,10 +134,32 @@ and returns a structure with an additional field with Pix suffix holding that ne
134134

135135
Define the parameters of the fixation cross in `cfg` and `expParameters` and this does the rest.
136136

137+
### eyeTracker
138+
139+
This will handle the Eye Tracker (EyeLink set up) and can be called to initialize the connection and start the calibration, start/stop eye(s) movement recordings and save the `*.edf` file (named with BIDS specification from cpp-lln-lab/CPP_BIDS).
140+
137141
### pressSpace4me
138142

139143
Use that to stop your script and only restart when the space bar is pressed.
140144

145+
## Annexes
146+
147+
### Experiment template [ WIP ]
148+
149+
### `devSandobox.m` stand-alone
150+
151+
This script is a stand-alone function that can be useful as a sandbox to develop the PTB audio/visual stimulation of your experiment. No input/output required.
152+
153+
Here, a tutorial from https://peterscarfe.com/contrastgratingdemo.html is provided for illustrative purpose (notice that some variable names are updated to our code style). For your use, you will delete that part.
154+
155+
It is composed of two parts:
156+
- a fixed structure that will initialize and close PTB in 'debug mode'
157+
(`PsychDebugWindowConfiguration`, `SkipSyncTests`)
158+
- the actual sandbox where to set your dynamic variables (the stimulation
159+
parameters) and the 'playground' where to develop the stimulation code
160+
161+
When you are happy with it, ideally you will move the vars in `setParameters.m` and the stimulation code in a separate function in `my-experiment-folder/subfun`. The code style and variable names are the same used in `cpp-lln-lab/CPP_PTB` github repo, therefore it should be easy to move everything in your experiment scripts (see the template that is annexed in `cpp-lln-lab/CPP_PTB`).
162+
141163
## Contributors ✨
142164

143165
Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):

demos/CPP_wait4TriggerDemo.m

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
cd ..
2+
3+
cfg.device = 'Scanner';
4+
5+
cfg.numTriggers = 4;
6+
7+
cfg.triggerKey = 'space';
8+
9+
KbName('UnifyKeyNames');
10+
11+
wait4Trigger(cfg)

devSandbox.m

Lines changed: 241 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,241 @@
1+
function devSandbox
2+
3+
% This script is a stand-alone function that can be useful as a sandbox to
4+
% develop the PTB audio/visual stimulation of your experiment. No input/output
5+
% required.
6+
%
7+
% Here, a tutorial from https://peterscarfe.com/contrastgratingdemo.html is
8+
% provided for illustrative purpose (notice that some variable names are updated
9+
% to our code style). For your use, you will delete that part.
10+
%
11+
% It is composed of two parts:
12+
% - a fixed structure that will initialize and close PTB in 'debug mode'
13+
% (`PsychDebugWindowConfiguration`, `SkipSyncTests`)
14+
% - the actual sandbox where to set your dynamic variables (the stimulation
15+
% parameters) and the 'playground' where to develop the stimulation code
16+
%
17+
% When you are happy with it, ideally you will move the vars in `setParameters.m`
18+
% and the stimulation code in a separate function in `my-experiment-folder/subfun`.
19+
% The code style and variable names are the same used in `cpp-lln-lab/CPP_PTB`
20+
% github repo, therefore it should be easy to move everything in your experiment
21+
% scripts (see the template that is annexed in `cpp-lln-lab/CPP_PTB`)
22+
23+
% Init the structure that will contain PTB setup
24+
cfg = struct;
25+
26+
% Set some colors to be choosen as background
27+
cfg.white = [255 255 255];
28+
cfg.black = [ 0 0 0 ];
29+
cfg.grey = mean([cfg.black; cfg.white]);
30+
31+
% Set the PTB window background manually
32+
cfg.backgroundColor = cfg.grey;
33+
34+
% Init PTB, see the Sub-Functions below
35+
cfg = devSandbox_initPTB(cfg);
36+
37+
%%
38+
% -------------------------------------------------------------------------
39+
% -------------------------- SET YOUR VARS HERE ---------------------------
40+
% -------------------------------------------------------------------------
41+
42+
% Define black and white
43+
white = WhiteIndex(cfg.screen);
44+
grey = white / 2;
45+
inc = white - grey;
46+
47+
% Grating size in pixels
48+
gratingSizePix = 600;
49+
50+
% Grating frequency in cycles / pixel
51+
freqCyclesPerPix = 0.01;
52+
53+
% Drift speed cycles per second
54+
cyclesPerSecond = 1;
55+
56+
% Contrast for our contrast modulation mask: 0 = mask has no effect, 1 = mask
57+
% will at its strongest part be completely opaque frameCounter.e. 0 and 100% contrast
58+
% respectively
59+
contrast = 0.8;
60+
61+
% We set PTB to wait one frame before re-drawing
62+
waitframes = 1;
63+
64+
% -------------------------------------------------------------------------
65+
%%
66+
67+
% Catch the error and restore your computer for debugging
68+
try
69+
70+
%%
71+
% -------------------------------------------------------------------------
72+
% ------------------------------ PLAYGROUND -------------------------------
73+
% -------------------------------------------------------------------------
74+
% Define Half-Size of the grating image.
75+
textureSize = gratingSizePix / 2;
76+
77+
% First we compute pixels per cycle rounded to the nearest pixel
78+
pixPerCycle = ceil(1 / freqCyclesPerPix);
79+
80+
% Frequency in Radians
81+
freqRad = freqCyclesPerPix * 2 * pi;
82+
83+
% This is the visible size of the grating
84+
visibleSize = 2 * textureSize + 1;
85+
86+
87+
% Define our grating. Note it is only 1 pixel high. PTB will make it a full
88+
% grating upon drawing
89+
x = meshgrid(-textureSize:textureSize + pixPerCycle, 1);
90+
grating = grey * cos(freqRad*x) + inc;
91+
92+
93+
% Make a two layer mask filled with the background colour
94+
mask = ones(1, numel(x), 2) * grey;
95+
96+
% Place the grating in the 'alpha' channel of the mask
97+
mask(:, :, 2)= grating .* contrast;
98+
99+
% Make our grating mask texture
100+
gratingMaskTex = Screen('MakeTexture', cfg.win, mask);
101+
102+
103+
% Make a black and white noise mask half the size of our grating. This will
104+
% be scaled upon drawing to make a "chunky" noise texture which our grating
105+
% will mask. Note the round function in here. For this demo we are simply
106+
% rounding the size to the nearest pixel, leaving PTB to do some scaling.
107+
noise = rand(round(visibleSize / 2)) .* white;
108+
109+
% Make our noise texture
110+
noiseTexture = Screen('MakeTexture', cfg.win, noise);
111+
112+
113+
% Make a destination rectangle for our textures and center this on the
114+
% screen
115+
dstRect = [0 0 visibleSize visibleSize];
116+
dstRect = CenterRect(dstRect, cfg.winRect);
117+
118+
% Calculate the wait duration
119+
waitDuration = waitframes * cfg.ifi;
120+
121+
% Recompute pixPerCycle, this time without the ceil() operation from above.
122+
% Otherwise we will get wrong drift speed due to rounding errors
123+
pixPerCycle = 1 / freqCyclesPerPix;
124+
125+
% Translate requested speed of the grating (in cycles per second) into
126+
% a shift value in "pixels per frame"
127+
shiftPerFrame = cyclesPerSecond * pixPerCycle * waitDuration;
128+
129+
% Sync us to the vertical retrace
130+
vbl = Screen('Flip', cfg.win);
131+
132+
% Set the frame counter to zero, we need this to 'drift' our grating
133+
frameCounter = 0;
134+
135+
% Loop until a key is pressed
136+
while ~KbCheck
137+
138+
% Calculate the xoffset for our window through which to sample our
139+
% grating
140+
xoffset = mod(frameCounter * shiftPerFrame, pixPerCycle);
141+
142+
% Now increment the frame counter for the next loop
143+
frameCounter = frameCounter + 1;
144+
145+
% Define our source rectangle for grating sampling
146+
srcRect = [xoffset 0 xoffset + visibleSize visibleSize];
147+
148+
% Draw noise texture to the screen
149+
Screen('DrawTexture', cfg.win, noiseTexture, [], dstRect, []);
150+
151+
% Draw grating mask
152+
Screen('DrawTexture', cfg.win, gratingMaskTex, srcRect, dstRect, []);
153+
154+
% Flip to the screen on the next vertical retrace
155+
vbl = Screen('Flip', cfg.win, vbl + (waitframes - 0.5) * cfg.ifi);
156+
157+
end
158+
159+
160+
161+
% -------------------------------------------------------------------------
162+
%%
163+
164+
% Close PTB, see the Sub-Functions below
165+
devSandbox_cleanUp
166+
167+
catch
168+
169+
devSandbox_cleanUp
170+
psychrethrow(psychlasterror);
171+
172+
end
173+
174+
175+
end
176+
177+
%% Sub-Functions
178+
function cfg = devSandbox_initPTB(cfg)
179+
180+
% Shorter version of `initPTB.m`
181+
182+
% Skip the PTB sync test
183+
Screen('Preference', 'SkipSyncTests', 2);
184+
185+
% Open a transparent window
186+
PsychDebugWindowConfiguration
187+
188+
% Here we call some default settings for setting up Psychtoolbox
189+
PsychDefaultSetup(2);
190+
191+
% Get the screen numbers and draw to the external screen if avaliable
192+
cfg.screen = max(Screen('Screens'));
193+
194+
% Open an on screen window
195+
[cfg.win, cfg.winRect] = Screen('OpenWindow', cfg.screen, cfg.backgroundColor);
196+
197+
% Get the size of the on screen window
198+
[cfg.winWidth, cfg.winHeight] = WindowSize(cfg.win);
199+
200+
% Query the frame duration
201+
cfg.ifi = Screen('GetFlipInterval', cfg.win);
202+
203+
% Get the Center of the Screen
204+
cfg.center = [cfg.winRect(3), cfg.winRect(4)]/2;
205+
206+
% Set up alpha-blending for smooth (anti-aliased) lines
207+
Screen('BlendFunction', cfg.win, 'GL_SRC_ALPHA', 'GL_ONE_MINUS_SRC_ALPHA');
208+
209+
end
210+
211+
function devSandbox_cleanUp
212+
213+
% A wrapper function to close all windows, ports, show mouse cursor, close keyboard queues
214+
% and give access back to the keyboards.
215+
216+
WaitSecs(0.5);
217+
218+
Priority(0);
219+
220+
ListenChar(0);
221+
KbQueueRelease();
222+
223+
ShowCursor
224+
225+
% Screen Close All
226+
sca;
227+
228+
% Close Psychportaudio if open
229+
if PsychPortAudio('GetOpenDeviceCount') ~= 0
230+
PsychPortAudio('Close');
231+
end
232+
233+
if ~ismac
234+
% remove PsychDebugWindowConfiguration
235+
clear Screen
236+
end
237+
238+
close all
239+
240+
241+
end

0 commit comments

Comments
 (0)