Appendix
Background Code
Below is the code behind the makebox() function described in section 3.7. This function can be called without adding this to your script. We include it for those interested.
var makebox = function(layout,scheme)
{
var box;
layout = layout || "centered";
scheme = scheme || "white";
switch (scheme)
{
case 'white': box = new Box();
break;
case 'black': box = new Box('black','black','white');
break;
case 'light': box = new Box('white','#fafafa','black',100,5,'#f3f3f3',5,"squ\
are");
break;
case 'wide-white': box = new Box(0,0,0,0,0,0,0,"wide");
break;
case 'wide-black': box = new Box('black','black','white',0,0,0,0,"wide");
break;
case 'wide-light': box = new Box('white','#fafafa','black',100,5,'#f3f3f3',5\
,"wide");
break;
default: exec.error("scriptlib","Unknown box scheme: " + scheme);
}
switch (layout)
{
case 'empty': break;
case 'centered':
box.centerblock = box.addblock("center","center",90,90);
break;
case 'threerows':
box.headerblock = box.addblock("center","top",100,25);
box.centerblock = box.addblock("center","center",100,50);
box.footerblock = box.addblock("center","bottom",100,25);
break;
default: exec.error("scriptlib","Unknown blocks layout: " + scheme);
}
return box;
};
Example Scripts
In this section, we will demonstrate how to write scripts for classic experiments and neuropsychological tasks.
Corsi Block Tapping Task
The Corsi Block Tapping Task is often used in neuropsychological assessment to estimate visuo-spatial memory span. It is described more fully in section 3.9.
1 var coords = [[10,10],[20,40],[20,80],[40,30],[45,60], // block coordinates
2 [60,10],[60,75],[70,50],[80,20],[85,45]], // [[left,top], ...]
3 blocks = [], i, b, series, e, block,
4 block_color = "lightgrey",
5 span = 2, errors, attempts = 0, correct = 0, kessels_score;
6
7 instruction("Watch the blocks 'light up' and then click them in the correct order. "
8 + "The test starts with a series of 2 blocks.");
9 clear();
10 await(1500);
11
12 for (i = 0; i < coords.length; i++) // Create block layout, use `i` as id
13 {
14 blocks.push(main.addblock(coords[i][0],coords[i][1],10,10,block_color,"",i));
15 }
16
17 while (true) // Do 'forever', but really only until `break` is called
18 {
19 await(2000);
20 series = shuffle(range(10)); // Randomize series
21 for (i = 0; i < span; i++) // 'Play' series
22 {
23 b = series[i];
24 blocks[b].style("backgroundColor","black");
25 await(500);
26 blocks[b].style("backgroundColor",block_color);
27 await(500);
28 }
29
30 errors = 0;
31 for (i = 0; i < span; i++) // Have subject click series
32 {
33 e = await("click"); // Event `e` also contains target node
34 b = parseInt(e.event.target.id); // parseInt turns a string into a number
35 blocks[b].blink("black",250); // 250 ms blink to black
36 if (series[i] !== b) // Count errors
37 {
38 ++errors;
39 }
40 }
41
42 ++attempts;
43 if (errors === 0)
44 {
45 ++correct;
46 if (attempts === 2) // If twice correct, increase span
47 {
48 ++span;
49 attempts = 0;
50 }
51 }
52 else
53 {
54 if (attempts === 2) // If twice wrong, stop test
55 {
56 --span;
57 kessels_score = span*correct; // Kessels et al. (2000)
58 break; // Break out of while loop
59 }
60 }
61 }
62
63 await(1000);
64 main.addblock("center","center",90,90,"white","Your Corsi blocks span is " + span);
Random Dot Pattern Recognition
Loosely based after Posner and Keele (1968), Kolodny, Squire and Knowlton, etc. This experiment is described more fully in section 3.9.
- Simplest version: show as images, store keystrokes, don’t analyze, no feedback
1 var pattern = new Box(),
2 coords = [[20,20],[30,40],[30,80],[40,30],[45,60],
3 [60,10],[60,75],[70,50],[80,20],[75,45]],
4 no_of_targets = 5, study_time = 2000, series,
5 hits = 0, false_alarms = 0, prototype_alarm = 0;
6
7 function showPattern(coords)
8 {
9 var block, blocks = [], i;
10 for (i = 0; i < coords.length; i++)
11 {
12 block = pattern.addblock(coords[i][0],coords[i][1],10,10);
13 block.text("•",200);
14 blocks.push(block);
15 }
16 return blocks;
17 }
18
19 function distortCoordinates(coordinates,distortion,seed)
20 {
21 var i, c = coordinates;
22 distortion = distortion || 10;
23 Math.seedrandom(seed); // Make distortion repeatable with `seed`
24 for (i = 0; i < c.length; i++) // Distort all coordinates
25 {
26 c[i][0] += randomint(-distortion,distortion);
27 c[i][1] += randomint(-distortion,distortion);
28 }
29 return c;
30 }
31
32 function presentStimuli(indices,distortion)
33 {
34 var c, i, p;
35 for (i = 0; i < indices.length; i++)
36 {
37 p = indices[i];
38 c = distortCoordinates(coords,distortion,p); // Use p as seed
39 showPattern(c);
40 await(study_time);
41 pattern.clearall(); // Remove pattern from screen
42 await(1000);
43 }
44 }
45
46 function getResponses(indices,distortion)
47 {
48 var c, i, p, e;
49 for (i = 0; i < indices.length; i++)
50 {
51 p = indices[i];
52 if (p === -1)
53 {
54 c = coords; // -1 means: show the prototype
55 }
56 else
57 {
58 c = distortCoordinates(coords,distortion,p); // Use p as seed
59 }
60 showPattern(c);
61 e = awaitkey("s,l");
62
63 if (e.key === "s") // Pattern believed to be old
64 {
65 if (-1 < p && p < no_of_targets)
66 {
67 ++hits; // Targets have indices 0,1,2, ..., no_of_targets-1
68 }
69 else
70 {
71 ++false_alarms;
72 }
73
74 if (p === -1) // Prototype has index -1
75 {
76 ++prototype_alarm; // False recognition of prototype
77 }
78 }
79 pattern.clearall(); // Remove pattern from screen
80 await(1000);
81 }
82 }
83
84 instruction("Study the following random dot patterns for later recognition. "
85 + "Patterns appear automatically.");
86 presentStimuli(range(no_of_targets),5);
87 instruction("Try to recognize the following patterns. "
88 + "Type the 's' or 'S' for an old or 'seen' pattern "
89 + "and 'l' or 'L' for a new pattern");
90 series = shuffle(range(-1,2*no_of_targets));
91 getResponses(series);
92 text("You had " + hits + " hits and you recognized the prototype as "
93 + (prototype_alarm ? "old." : "new."));