11function [cfg , thisEvent ] = apertureTexture(action , cfg , thisEvent )
2-
3- transparent = [0 0 0 0 ];
2+ % [cfg, thisEvent] = apertureTexture(action, cfg, thisEvent)
3+ %
4+ %
45
56 switch action
6-
7+
78 case ' init'
8-
9- switch cfg .aperture .type
10-
11- case ' circle'
12- % we take the screen height as maximum aperture width if not
13- % specified.
14- if ~isfield(cfg .aperture , ' width' ) || isempty(cfg .aperture .width )
15- cfg.aperture.width = cfg .screen .winRect(4 ) / cfg .screen .ppd ;
16- end
17- cfg.aperture = degToPix(' width' , cfg .aperture , cfg );
18-
19- case ' ring'
20-
21- % Set parameters for rings
22- if strcmp(cfg .aperture .type , ' ring' )
23- % scale of outer ring (exceeding screen until
24- % inner ring reaches window boarder)
25- cfg.ring.maxEcc = ...
26- cfg .screen .FOV / 2 + ...
27- cfg .aperture .width + ...
28- log(cfg .screen .FOV / 2 + 1 ) ;
29- % ring.CsFuncFact is used to expand with log increasing speed so
30- % that ring is at ring.maxEcc at end of cycle
31- cfg.ring.csFuncFact = ...
32- 1 / ...
33- ((cfg .ring .maxEcc + exp(1 )) * ...
34- log(cfg .ring .maxEcc + exp(1 )) - ...
35- (cfg .ring .maxEcc + exp(1 ))) ;
36- end
37- end
38-
9+
10+ cfg = apertureInit(cfg );
11+
3912 cfg.aperture.texture = Screen(' MakeTexture' , cfg .screen .win , ...
4013 cfg .color .background(1 ) * ones(cfg .screen .winRect([4 3 ])));
41-
14+
4215 case ' make'
43-
16+
17+ transparent = [0 , 0 , 0 , 0 ];
18+
4419 xCenter = cfg .screen .center(1 );
4520 yCenter = cfg .screen .center(2 );
46-
21+
4722 switch cfg .aperture .type
48-
23+
4924 case ' none'
50-
25+
5126 Screen(' Fillrect' , cfg .aperture .texture , transparent );
52-
27+
5328 case ' circle'
54-
29+
5530 diameter = cfg .aperture .widthPix ;
56-
31+
5732 if isfield(cfg .aperture , ' xPosPix' )
5833 xCenter = cfg .screen .center(1 ) + cfg .aperture .xPosPix ;
5934 end
6035 if isfield(cfg .aperture , ' yPosPix' )
6136 yCenter = cfg .screen .center(2 ) + cfg .aperture .yPosPix ;
6237 end
63-
38+
6439 Screen(' FillOval' , cfg .aperture .texture , transparent , ...
65- CenterRectOnPoint([0 0 repmat(diameter , 1 , 2 )], ...
40+ CenterRectOnPoint([0 , 0 , repmat(diameter , 1 , 2 )], ...
6641 xCenter , yCenter ));
67-
42+
6843 case ' ring'
69-
44+
7045 % expansion speed is log over eccentricity
7146 [cfg ] = eccenLogSpeed(cfg , thisEvent .time );
72-
47+
7348 Screen(' Fillrect' , cfg .aperture .texture , cfg .color .background );
74-
49+
7550 Screen(' FillOval' , cfg .aperture .texture , transparent , ...
7651 CenterRectOnPoint( ...
77- [0 0 repmat(cfg .ring .outerRimPix , 1 , 2 )], ...
52+ [0 , 0 , repmat(cfg .ring .outerRimPix , 1 , 2 )], ...
7853 xCenter , yCenter ));
79-
54+
8055 Screen(' FillOval' , cfg .aperture .texture , [cfg .color .background 255 ], ...
8156 CenterRectOnPoint( ...
82- [0 0 repmat(cfg .ring .innerRimPix , 1 , 2 )], ...
57+ [0 , 0 , repmat(cfg .ring .innerRimPix , 1 , 2 )], ...
8358 xCenter , yCenter ));
84-
59+
8560 case ' wedge'
86-
61+
8762 cycleDuration = cfg .mri .repetitionTime * cfg .volsPerCycle ;
88-
63+
8964 % Update angle for rotation of background and for apperture for wedge
9065 switch cfg .direction
91-
66+
9267 case ' +'
9368 thisEvent.angle = 90 - ...
9469 cfg .aperture .width / 2 + ...
9772 thisEvent.angle = 90 - ...
9873 cfg .aperture .width / 2 - ...
9974 (thisEvent .time / cycleDuration ) * 360 ;
100-
75+
10176 end
102-
77+
10378 Screen(' Fillrect' , cfg .aperture .texture , cfg .color .background );
104-
79+
10580 Screen(' FillArc' , cfg .aperture .texture , transparent , ...
10681 CenterRect( ...
107- [0 0 repmat(cfg .stimRect(4 ), 1 , 2 )], ...
82+ [0 , 0 , repmat(cfg .stimRect(4 ), 1 , 2 )], ...
10883 cfg .screen .winRect ), ...
10984 thisEvent .angle , ... % start angle
11085 cfg .aperture .width ); % arc angle
86+
87+ case ' bar'
88+
89+ % aperture is the color of the background
90+ Screen(' FillRect' , cfg .aperture .texture , cfg .color .background );
91+
92+ % We let the stimulus through
93+ Screen(' FillOval' , cfg .aperture .texture , transparent , ...
94+ CenterRect([0 , 0 , repmat(cfg .stimRect(3 ), 1 , 2 )], cfg .screen .winRect ));
95+
96+ % Then we add the position of the bar aperture
97+ Screen(' FillRect' , cfg .aperture .texture , cfg .color .background , ...
98+ [0 , ...
99+ 0 , ...
100+ thisEvent .barPosPix - cfg .aperture .barWidthPix / 2 , ...
101+ cfg .screen .winRect(4 )]);
102+
103+ Screen(' FillRect' , cfg .aperture .texture , cfg .color .background , ...
104+ [thisEvent .barPosPix + cfg .aperture .barWidthPix / 2 , ...
105+ 0 , ...
106+ cfg .screen .winRect(3 ), ...
107+ cfg .screen .winRect(4 )]);
111108
112109 otherwise
113-
110+
114111 error(' unknown aperture type: %s .' , cfg .aperture .type );
115-
112+
116113 end
117-
114+
118115 case ' draw'
116+
117+ if strcmp(cfg .aperture .type , ' bar' )
118+
119+ % Draw aperture and we rotate to match the required condition
120+ Screen(' DrawTexture' , cfg .screen .win , cfg .aperture .texture , ...
121+ cfg .screen .winRect , ...
122+ cfg .screen .winRect , ...
123+ thisEvent .condition - 90 );
124+ else
125+
126+ Screen(' DrawTexture' , cfg .screen .win , cfg .aperture .texture );
127+
128+ end
119129
120- Screen(' DrawTexture' , cfg .screen .win , cfg .aperture .texture );
121-
122- % Screen('DrawTexture', cfg.screen.win, apertureTexture, ...
123- % cfg.screen.winRect, cfg.screen.winRect, current.apertureAngle - 90);
130+
124131
132+
125133 end
126-
134+
127135end
136+
137+
138+ function cfg = apertureInit(cfg )
139+
140+ switch cfg .aperture .type
141+
142+ case ' circle'
143+ % we take the screen height as maximum aperture width if not
144+ % specified.
145+ if ~isfield(cfg .aperture , ' width' ) || isempty(cfg .aperture .width )
146+ cfg.aperture.width = cfg .screen .winRect(4 ) / cfg .screen .ppd ;
147+ end
148+ cfg.aperture = degToPix(' width' , cfg .aperture , cfg );
149+
150+ case ' ring'
151+
152+ % Set parameters for rings
153+ if strcmp(cfg .aperture .type , ' ring' )
154+ % scale of outer ring (exceeding screen until
155+ % inner ring reaches window boarder)
156+ cfg.ring.maxEcc = ...
157+ cfg .screen .FOV / 2 + ...
158+ cfg .aperture .width + ...
159+ log(cfg .screen .FOV / 2 + 1 ) ;
160+ % ring.CsFuncFact is used to expand with log increasing speed so
161+ % that ring is at ring.maxEcc at end of cycle
162+ cfg.ring.csFuncFact = ...
163+ 1 / ...
164+ ((cfg .ring .maxEcc + exp(1 )) * ...
165+ log(cfg .ring .maxEcc + exp(1 )) - ...
166+ (cfg .ring .maxEcc + exp(1 ))) ;
167+ end
168+
169+ case ' bar'
170+
171+ % Set parameters drifting bars
172+ cfg.aperture.barWidthPix = cfg .stimRect(3 ) / cfg .volsPerCycle ;
173+ cfg.aperture.barPosPix = ...
174+ [ 0 : cfg .aperture .barWidthPix : cfg .stimRect(3 ) - cfg .aperture .barWidthPix ] + ...
175+ (cfg .screen .winRect(3 ) / 2 - cfg .stimRect(3 ) / 2 ) + ...
176+ cfg .aperture .barWidthPix / 2 ; % #ok<NBRAK>
177+
178+ % Width of bar in degrees of VA (needed for saving)
179+ cfg.aperture.width = cfg .aperture .barWidthPix / cfg .screen .ppd ;
180+ cfg.aperture.barPos = ...
181+ (cfg .aperture .barPosPix - cfg .screen .center(1 )) / ...
182+ cfg .screen .ppd ;
183+
184+ end
185+
186+ end
0 commit comments