1 //Two types of plaid motion
\r
2 //E. H. Adelson and J. A. Movshon (1982).
\r
3 //Phenomenal coherence of moving visual patterns. Nature 300, 523-525
\r
6 //// Include Psychlops Package
\r
9 namespace PsychlopsSilverlightApp
\r
12 public class PsychlopsMain
\r
17 // Struct for component paremeters
\r
20 public double contrast;
\r
21 public double orientation;
\r
22 public double lambda;
\r
27 ///+ Stimulus drawing function
\r
28 //// A function for stimulus drawing (main body)
\r
29 void drawgratingmovie(Image[] img, component c1, component c2, double contrast, int start, int maxframe, double bg_lum, double alpha)
\r
31 double _xp, _xp2, col1, col2;
\r
32 double contrast1, contrast2;
\r
33 double imageheight, imagewidth;
\r
35 contrast1 = contrast*c1.contrast/(c1.contrast+c2.contrast);
\r
36 contrast2 = contrast*c2.contrast/(c1.contrast+c2.contrast);
\r
38 imageheight = img[0].getHeight();
\r
39 imagewidth = img[0].getWidth();
\r
41 for(int frame=start; frame<start+maxframe+1; frame++){
\r
42 //Display.progressbar(frame, maxframe+1);
\r
43 //img[frame].convert(Image::RGBA);
\r
44 for(int i=0; i<imagewidth; i++){
\r
45 for(int j=0; j<imageheight; j++){
\r
46 _xp = Math.sin(c1.orientation)*(i-imagewidth*0.5) + Math.cos(c1.orientation) * (j-imageheight *0.5);
\r
47 _xp2 = Math.sin(c2.orientation)*(i-imagewidth*0.5) + Math.cos(c2.orientation) * (j-imageheight *0.5);
\r
48 col1 = bg_lum*contrast1*Math.sin(2*Math.PI*_xp/c1.lambda + 2*Math.PI*c1.tf*frame/(double)refresh);
\r
49 col2 = bg_lum*contrast2*Math.sin(2*Math.PI*_xp2/c2.lambda + 2*Math.PI*c2.tf*frame/(double)refresh);
\r
50 img[frame].pix(i,j,new Color(col1+col2+bg_lum));
\r
51 img[frame].alpha(i,j,alpha);
\r
54 //img[frame].cache();
\r
58 ///+ Stimulus drawing function
\r
59 //// A function for stimulus drawing (main body)
\r
61 Canvas display = new Canvas(Canvas.window);
\r
63 //// Declare and initialize local variables
\r
64 int rect_size = 150;
\r
65 double rect_lum = 0.5;
\r
66 double bg_lum = 0.2;
\r
67 double duration = 400;
\r
69 double[] lambda = new double[2], contrast = new double[2], tf = new double[2];
\r
70 double center_orientation = 0.0;
\r
71 Image[,] movie = StaticFunctions.NewArray<Image>(2, 120);
\r
72 Image[,] component_movie = StaticFunctions.NewArray<Image>(4, 120);
\r
73 Image envelope = new Image(), envelope_small = new Image();
\r
75 for(int i=0; i<120; i++)
\r
77 movie[0, i].set(rect_size, rect_size);
\r
78 movie[1, i].set(rect_size, rect_size);
\r
79 component_movie[0, i].set(rect_size/2, rect_size/2);
\r
80 component_movie[1, i].set(rect_size/2, rect_size/2);
\r
81 component_movie[2, i].set(rect_size/2, rect_size/2);
\r
82 component_movie[3, i].set(rect_size/2, rect_size/2);
\r
84 envelope.set(rect_size, rect_size);
\r
85 envelope_small.set(rect_size/2, rect_size/2);
\r
87 Letters let1 = new Letters(), let2 = new Letters(), let3 = new Letters();
\r
88 let1.str = "Component1";
\r
89 let2.str = "Component2";
\r
90 let3.str = "Superposition";
\r
91 let1.centering().shift(-rect_size*1.25, -rect_size);
\r
93 let2.centering().shift(rect_size*1.25, -rect_size);
\r
95 let3.centering().shift(0.0, rect_size*0.75);
\r
98 component c1, c2, c0;
\r
99 c0 = new component{ 0.0,0.0,1.0,1.0 }; //dummy for component movie
\r
101 // Prepare Type-I plaid movie
\r
102 center_orientation = 0.0;
\r
103 orientation_offset = Math.PI/6;
\r
104 contrast[0] = 1.0, contrast[1] = 1.0;
\r
105 lambda[0] = 30.0, lambda[1] = 30.0;
\r
106 tf[0] = 1.0; tf[1] = 1.0;
\r
108 c1 = {contrast[0], center_orientation-orientation_offset, lambda[0], tf[0]};
\r
109 c2 = {contrast[1], center_orientation+orientation_offset, lambda[1], tf[1]};
\r
111 drawgratingmovie(movie[0],c1, c2, 0.5, 0, refresh_int, bg_lum, 1.0);
\r
112 drawgratingmovie(component_movie[0],c0, c2, 0.5, 0, refresh_int, bg_lum, 1.0);
\r
113 drawgratingmovie(component_movie[1],c1, c0, 0.5, 0, refresh_int, bg_lum, 1.0);
\r
117 // Prepare Type-II plaid movie
\r
118 center_orientation = -0.0, orientation_offset = Math.PI/12;
\r
119 contrast[0] = 1.0, contrast[1] = 1.0;
\r
120 lambda[0] = 30.0, lambda[1] = 30.0;
\r
121 tf[0] = 1.0; tf[1] = 4.0;
\r
123 c1 = {contrast[0], center_orientation-orientation_offset, lambda[0], tf[0]};
\r
124 c2 = {contrast[1], center_orientation+orientation_offset, lambda[1], tf[1]};
\r
126 drawgratingmovie(movie[1],c1, c2, 0.5, 0, refresh_int, bg_lum, 1.0);
\r
127 drawgratingmovie(component_movie[2],c0, c2, 0.5, 0, refresh_int, bg_lum, 1.0);
\r
128 drawgratingmovie(component_movie[3],c1, c0, 0.5, 0, refresh_int, bg_lum, 1.0);
\r
132 //draw Gaussian envelopes
\r
133 envelope.clear(new Color(bg_lum)); //clear offscreen image
\r
135 for(int i=0; i<rect_size; i++){
\r
136 _x=i-0.5*rect_size;
\r
137 for(int j=0; j<rect_size; j++){
\r
138 _y=j-0.5*rect_size;
\r
139 envelope.alpha(i,j,1.0-Math.exp(-((_x*_x+_y*_y)/ (2.0*pow(rect_size/6.0, 2.0) ))));
\r
143 envelope_small.clear(new Color(bg_lum)); //clear offscreen image
\r
144 for(int i=0; i<rect_size*0.5; i++){
\r
145 _x=i-0.25*rect_size;
\r
146 for(int j=0; j<rect_size*0.5; j++){
\r
147 _y=j-0.25*rect_size;
\r
148 envelope_small.alpha(i,j,1.0-Math.exp(-((_x*_x+_y*_y)/ (2.0*pow(rect_size/12.0, 2.0) ))));
\r
151 envelope.cache(); //send offscreen image from main memory to GPU
\r
152 envelope_small.cache(); //send offscreen image from main memory to GPU
\r
155 ///+ user interface
\r
156 // Draw user interface
\r
157 Widgets::SelectBox stimulus_type;
\r
158 stimulus_type.area.set(120, 20);
\r
159 stimulus_type.append(L"TypeI");
\r
160 stimulus_type.append(L"TypeII");
\r
161 stimulus_type.centering().shift(-120.0,250.0);
\r
163 Psychlops::Widgets::SelectBox stimulus_type2;
\r
164 stimulus_type2.area.set(120, 20);
\r
165 stimulus_type2.append(L"Continuous");
\r
166 stimulus_type2.append(L"Periodic");
\r
167 stimulus_type2.centering().shift(120.0,250.0);
\r
169 Psychlops::Widgets::Slider duration_slider;
\r
170 duration_slider.area.set(100,20);
\r
171 duration_slider.centering().shift(120,280.0);
\r
172 Interval rng = new Interval();
\r
173 duration_slider.link(duration, 50<=rng<=950, 50.0, 50.0);
\r
174 ///- user interface
\r
179 int period = refresh_int;
\r
181 while(!Keyboard.esc.pushed()) {
\r
182 Display.clear(new Color(bg_lum));
\r
183 movienum = stimulus_type.getSelected(); //if "Type-I" is selected, 0, else frame refresh per sec
\r
186 else period = refresh_int;
\r
189 movie[movienum, frame].centering().draw();
\r
190 envelope.centering().draw();
\r
191 component_movie[movienum*2, frame].centering().shift(-rect_size*0.5, -rect_size).draw();
\r
192 envelope_small.centering().shift(-rect_size*0.5, -rect_size).draw();
\r
193 component_movie[movienum*2+1, frame].centering().shift(rect_size*0.5, -rect_size).draw();
\r
194 envelope_small.centering().shift(rect_size*0.5, -rect_size).draw();
\r
197 ///+ draw user interface
\r
201 stimulus_type.draw();
\r
202 stimulus_type2.draw();
\r
203 if(stimulus_type2.getSelected())duration_slider.draw();
\r
204 ///- draw user interface
\r
206 if(frame++ >= period) frame -= refresh_int;
\r
211 ///- Stimulus drawing function
\r
213 ///+ Main function for demo circumstances
\r
214 public void psychlops_main() {
\r
215 ///+ Demo circumstances
\r
216 //// Spells for run demonstration circumstances
\r
217 Procedure p = new Procedure();
\r
218 //p.setDesign(Procedure::DEMO); //Designate that this is a demo.
\r
219 p.setProcedure(drawplaid); //The argument name is a name of drawing function.
\r
221 ///- Demo circumstances
\r
231 //Position Bias Program
\r
232 namespace PsychlopsSilverlightApp
\r
235 public class PsychlopsMain
\r
238 Image img, img2, img3;
\r
241 Psychlops.Widgets.Slider tfreq;
\r
242 Psychlops.Widgets.Slider contrast;
\r
243 Psychlops.Widgets.Slider lambda;
\r
245 public void psychlops_main()
\r
247 cnvs = new Canvas(300, 600);
\r
248 Interval rng = new Interval();
\r
249 tfreq = new Psychlops.Widgets.Slider("Temporal Frequency(Hz)", -5 <= rng <= 5, 3.0);
\r
250 contrast = new Psychlops.Widgets.Slider("Contrast", 0.0 <= rng <= 1.0, 0.25);
\r
251 lambda = new Psychlops.Widgets.Slider("Wave Length", 10.0 <= rng <= 120.0, 30);
\r
253 img = new Image(isize * 2, isize * 2);
\r
254 img2 = new Image(isize * 2, isize * 2);
\r
255 img3 = new Image(isize * 2, isize * 2);
\r
260 cnvs.clear(new Color(0.5));
\r
262 Figures.drawGabor(ref img, isize / 6, 1/lambda, contrast, 0.5 * Math.PI, (double)frames * 2.0 * Math.PI * tfreq / 60);
\r
263 Figures.drawGabor(ref img2, isize / 6, 1 / lambda, contrast, 0.5 * Math.PI, (double)frames * 2.0 * Math.PI * -tfreq / 60);
\r
264 Figures.drawGabor(ref img3, isize / 6, 1 / lambda, contrast, 0.5 * Math.PI, (double)frames * 2.0 * Math.PI * tfreq / 60);
\r
266 img.centering().shift(0, -isize * 1.5).draw();
\r
267 img2.centering().draw();
\r
268 img3.centering().shift(0, isize * 1.5).draw();
\r
270 if (!Mouse.left.pressed()) frames++;
\r