Example Scripts

In this chapter, we will demonstrate how to write scripts for a number of 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.

 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 after Posner and Keele (1968), Kolodny, Squire and Knowlton, etc.

  • 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."));