<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>research &#8211; Dr. Jian Chen</title>
	<atom:link href="http://localhost/jianchen/category/research/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.jianchen.info</link>
	<description>陈建博士</description>
	<lastBuildDate>Mon, 25 Jul 2022 06:05:48 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.1.1</generator>

<image>
	<url>https://www.jianchen.info/wp-content/uploads/2022/06/cropped-Frued_Cartoon-32x32.png</url>
	<title>research &#8211; Dr. Jian Chen</title>
	<link>https://www.jianchen.info</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Corsi Blocks Task with jsPsych</title>
		<link>https://www.jianchen.info/2022/07/25/corsi-blocks-task-with-jspsych/</link>
		
		<dc:creator><![CDATA[saturn]]></dc:creator>
		<pubDate>Mon, 25 Jul 2022 06:03:56 +0000</pubDate>
				<category><![CDATA[research]]></category>
		<guid isPermaLink="false">https://www.jianchen.info/?p=211</guid>

					<description><![CDATA[This piece of code is revised by Dr Jian Chen based on the published code from R. Gibeau (2021) The Corsi Blocks Task: Variations and coding with jsPsych. The Quantitative Methods for Psychology. 10.20982/tqmp.17.3.p299 In this version, I follow the classical Corsi task in which 9 sequences are presented in a fixed order. Blocks are ... <a title="Corsi Blocks Task with jsPsych" class="read-more" href="https://www.jianchen.info/2022/07/25/corsi-blocks-task-with-jspsych/" aria-label="More on Corsi Blocks Task with jsPsych">Read more</a>]]></description>
										<content:encoded><![CDATA[<div class="wp-block-image">
<figure class="aligncenter size-large"><img decoding="async" width="1024" height="792" src="https://www.jianchen.info/wp-content/uploads/2022/07/blockArrangement-1024x792.png" alt="" class="wp-image-212" srcset="https://www.jianchen.info/wp-content/uploads/2022/07/blockArrangement-1024x792.png 1024w, https://www.jianchen.info/wp-content/uploads/2022/07/blockArrangement-300x232.png 300w, https://www.jianchen.info/wp-content/uploads/2022/07/blockArrangement-768x594.png 768w, https://www.jianchen.info/wp-content/uploads/2022/07/blockArrangement-1536x1188.png 1536w, https://www.jianchen.info/wp-content/uploads/2022/07/blockArrangement.png 1652w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure></div>


<p>This piece of code is revised by Dr Jian Chen based on the published code from <a href="https://www.tqmp.org/RegularArticles/vol17-3/p299/p299.pdf" data-type="URL" data-id="https://www.tqmp.org/RegularArticles/vol17-3/p299/p299.pdf">R. Gibeau (2021) The Corsi Blocks Task: Variations and coding with jsPsych. The Quantitative Methods for Psychology. 10.20982/tqmp.17.3.p299</a></p>



<p>In this version, I follow the classical Corsi task in which 9 sequences are presented in a fixed order. Blocks are presented in fixed positions. For each sequence has two trials. Participants need to pass at least one trial to get to the next sequence.</p>



<p>Please notice, given this piece code is based on a exisiting task, so some code look dumb here and there. There are better ways to achieve this but for the moment this is the most time efficient way for me. I will look into the possibility to recode it into a more neat way using the newest version of jsPsych.</p>



<p>This task runs in jsPsych v6.1.0. It does not work in other versions.</p>



<p>Updates:</p>



<ul><li>25.7.2022 add termination if two continuous errors in one sequence.</li></ul>



<p></p>



<p>Here is the main code (also available on my GitHub page (https://github.com/jianch/Corsi-Block-Task). You will also need a specific plugin to run this task:<a href="https://github.com/jianch/Corsi-Block-Task/blob/main/jspsych-html-keyboard-response-noerase.js" data-type="URL" data-id="https://github.com/jianch/Corsi-Block-Task/blob/main/jspsych-html-keyboard-response-noerase.js"> jspsych-html-keyboard-response-noerase.js</a>. </p>



<p>Have fun. </p>



<pre class="wp-block-code"><code>/* url parameters*/
var id = jsPsych.data.getURLVariable("subjectid");
var debrifurl = "https://jianchen.info/?subjectid=".concat(id) // simple reaction task

// ****************************** 
// *   Defining general stuff   * 
// ****************************** 
console.log('Begining of the parameter definitions')

// Experiment parameters 
var nItems              = 9       // total number of squares on the display. Fixed in this experiment
// the sequence lengths to test the participant with, with the variable "OneSequenceLength"
var sequenceLengths_prac = &#91;{OneSequenceLength: 2}];
var sequenceLengths     = &#91;{OneSequenceLength: 2},{OneSequenceLength: 3},{OneSequenceLength: 4},{OneSequenceLength: 5},
                            {OneSequenceLength: 6},{OneSequenceLength: 7},{OneSequenceLength: 8},{OneSequenceLength: 9}];
var sequenceRandomOrder = false   // true for "random" or false for "sequential"
var sequenceRepetition  = 2       // how many times each length is tested

// Trial parameters 
var InterTrialDuration   = 100  // e.g., REF
var FixationDuration     = 400  // e.g., REF
var MouseToBeHidden      = false 
var PreBlinkDuration     = 500  // e.g., REF
var BlinkDuration        = 400  // e.g., REF
var PostBlinkDuration    = 500  // e.g., REF
var InterBlinkDuration   = 400  // e.g., REF
var RecallSignal         = 'https://raw.githubusercontent.com/RMG2424/Dr.-Mid-Nite/master/CorsiBlockjsPsych/500hz-400ms.wav'
var RecallSignalDuration = 400
var AcknowledgeDuration  = 200  // e.g., REF

// Item parameters; assembled using makeItem
var BackgroundColor   = "white"        // accept the HTML-defined colors
var TextColor         = "black"        					// 
var OneItemShape      = "rect"             // one of the svg primitive
var OneItemShownColor = "rgb(0,0,0)"       // black
var OneItemBlinkColor = "rgb(128,128,128)" // gray
var OneItemClickColor = "rgb(0,0,255)"     // blue
var OneItemSize       = 1/10               // proportion of the item relative to minscreen 
var OneItemMargin     = 1/50               // margin to leave empty around the item, relative to minscreen 

console.log('End of the parameter definitions')

var preload = {
  type: 'preload',
  auto_preload: true} 

// set the background color
document.body.style.backgroundColor = BackgroundColor; 
document.body.style.color = TextColor; 

// these two lines convert the relative sizes into pixel sizes LEAVE UNCHANGED
var OneItemSizePX     = Math.floor(OneItemSize * Math.min(screen.width, screen.height))
var OneItemMarginPX   = Math.floor(OneItemMargin * Math.min(screen.width, screen.height))
console.log(`Item dimensions in pixels are: (size) ${OneItemSizePX}, (margins) ${OneItemMarginPX}`);

// Function that builts an HTML svg (scalable vector graphic) image
// may need to be adapted if a different shape is chosen
var makeItem = function(color) {
    return(`&lt;svg width="${OneItemSizePX}" height="${OneItemSizePX}"&gt;&lt;${OneItemShape} width="${OneItemSizePX}" height="${OneItemSizePX}" style="fill:${color};stroke-width:0;"&gt;&lt;/svg&gt;`);
}

// Empty lists of items; are to be populated by PositionFunction 
var ListOfItems         = new Array(nItems); // the array is full length bcse jsPsych updates it too slow 
var ListOfBlinkingItems = new Array(nItems); // idem                                                      
var ListOfButtons       = new Array(0);
var nBlinkingItems      = null;
var nBlinkingItems      = null;
var acc_accumulation    = null;

// create items positions
// relative X position of items
ListOfItems&#91;0] = &#91;]; ListOfItems&#91;1] = &#91;]; ListOfItems&#91;2] = &#91;]; ListOfItems&#91;3] = &#91;];
ListOfItems&#91;4] = &#91;]; ListOfItems&#91;5] = &#91;]; ListOfItems&#91;6] = &#91;]; ListOfItems&#91;7] = &#91;]; ListOfItems&#91;8] = &#91;];

ListOfItems&#91;0].x = 0.5 * screen.width;  
ListOfItems&#91;1].x = 0.27 * screen.width; 
ListOfItems&#91;2].x = 0.64 * screen.width; 
ListOfItems&#91;3].x = 0.31 * screen.width; 
ListOfItems&#91;4].x = 0.55 * screen.width; 
ListOfItems&#91;5].x = 0.70 * screen.width; 
ListOfItems&#91;6].x = 0.23 * screen.width; 
ListOfItems&#91;7].x = 0.38 * screen.width; 
ListOfItems&#91;8].x = 0.52 * screen.width; 

ListOfItemsXPositions = &#91;ListOfItems&#91;0].x, ListOfItems&#91;1].x, ListOfItems&#91;2].x, ListOfItems&#91;3].x, ListOfItems&#91;4].x,
                        ListOfItems&#91;5].x,ListOfItems&#91;6].x,ListOfItems&#91;7].x, ListOfItems&#91;8].x]


// relative Y position of items
ListOfItems&#91;0].y = 0.25 * screen.height;  
ListOfItems&#91;1].y = 0.14 * screen.height;  
ListOfItems&#91;2].y = 0.29 * screen.height;  
ListOfItems&#91;3].y = 0.35 * screen.height;  
ListOfItems&#91;4].y = 0.42 * screen.height;  
ListOfItems&#91;5].y = 0.51 * screen.height;  
ListOfItems&#91;6].y = 0.52 * screen.height;  
ListOfItems&#91;7].y = 0.63 * screen.height;  
ListOfItems&#91;8].y = 0.58 * screen.height;  


ListOfItems&#91;0].ItemHTML  = `&lt;p style = "position:absolute; margin-top: 0em; left: ${ListOfItems&#91;0].x}px; top: ${ListOfItems&#91;0].y}px"&gt;`+ `${makeItem(OneItemShownColor)} &lt;/p&gt;`;
ListOfItems&#91;0].ItemBLANK = `&lt;p style = "position:absolute; margin-top: 0em; left: ${ListOfItems&#91;0].x}px; top: ${ListOfItems&#91;0].y}px"&gt;`+ `${makeItem(OneItemBlinkColor)}&lt;/p&gt;`;
ListOfItems&#91;0].ItemACKNW = `&lt;p style = "position:absolute; margin-top: 0em; left: ${ListOfItems&#91;0].x}px; top: ${ListOfItems&#91;0].y}px"&gt;`+ `${makeItem(OneItemClickColor)}&lt;/p&gt;`;

ListOfItems&#91;1].ItemHTML  = `&lt;p style = "position:absolute; margin-top: 0em; left: ${ListOfItems&#91;1].x}px; top: ${ListOfItems&#91;1].y}px"&gt;`+ `${makeItem(OneItemShownColor)} &lt;/p&gt;`;
ListOfItems&#91;1].ItemBLANK = `&lt;p style = "position:absolute; margin-top: 0em; left: ${ListOfItems&#91;1].x}px; top: ${ListOfItems&#91;1].y}px"&gt;`+ `${makeItem(OneItemBlinkColor)}&lt;/p&gt;`;
ListOfItems&#91;1].ItemACKNW = `&lt;p style = "position:absolute; margin-top: 0em; left: ${ListOfItems&#91;1].x}px; top: ${ListOfItems&#91;1].y}px"&gt;`+ `${makeItem(OneItemClickColor)}&lt;/p&gt;`;

ListOfItems&#91;2].ItemHTML  = `&lt;p style = "position:absolute; margin-top: 0em; left: ${ListOfItems&#91;2].x}px; top: ${ListOfItems&#91;2].y}px"&gt;`+ `${makeItem(OneItemShownColor)} &lt;/p&gt;`;
ListOfItems&#91;2].ItemBLANK = `&lt;p style = "position:absolute; margin-top: 0em; left: ${ListOfItems&#91;2].x}px; top: ${ListOfItems&#91;2].y}px"&gt;`+ `${makeItem(OneItemBlinkColor)}&lt;/p&gt;`;
ListOfItems&#91;2].ItemACKNW = `&lt;p style = "position:absolute; margin-top: 0em; left: ${ListOfItems&#91;2].x}px; top: ${ListOfItems&#91;2].y}px"&gt;`+ `${makeItem(OneItemClickColor)}&lt;/p&gt;`;

ListOfItems&#91;3].ItemHTML  = `&lt;p style = "position:absolute; margin-top: 0em; left: ${ListOfItems&#91;3].x}px; top: ${ListOfItems&#91;3].y}px"&gt;`+ `${makeItem(OneItemShownColor)} &lt;/p&gt;`;
ListOfItems&#91;3].ItemBLANK = `&lt;p style = "position:absolute; margin-top: 0em; left: ${ListOfItems&#91;3].x}px; top: ${ListOfItems&#91;3].y}px"&gt;`+ `${makeItem(OneItemBlinkColor)}&lt;/p&gt;`;
ListOfItems&#91;3].ItemACKNW = `&lt;p style = "position:absolute; margin-top: 0em; left: ${ListOfItems&#91;3].x}px; top: ${ListOfItems&#91;3].y}px"&gt;`+ `${makeItem(OneItemClickColor)}&lt;/p&gt;`;

ListOfItems&#91;4].ItemHTML  = `&lt;p style = "position:absolute; margin-top: 0em; left: ${ListOfItems&#91;4].x}px; top: ${ListOfItems&#91;4].y}px"&gt;`+ `${makeItem(OneItemShownColor)} &lt;/p&gt;`;
ListOfItems&#91;4].ItemBLANK = `&lt;p style = "position:absolute; margin-top: 0em; left: ${ListOfItems&#91;4].x}px; top: ${ListOfItems&#91;4].y}px"&gt;`+ `${makeItem(OneItemBlinkColor)}&lt;/p&gt;`;
ListOfItems&#91;4].ItemACKNW = `&lt;p style = "position:absolute; margin-top: 0em; left: ${ListOfItems&#91;4].x}px; top: ${ListOfItems&#91;4].y}px"&gt;`+ `${makeItem(OneItemClickColor)}&lt;/p&gt;`;

ListOfItems&#91;5].ItemHTML  = `&lt;p style = "position:absolute; margin-top: 0em; left: ${ListOfItems&#91;5].x}px; top: ${ListOfItems&#91;5].y}px"&gt;`+ `${makeItem(OneItemShownColor)} &lt;/p&gt;`;
ListOfItems&#91;5].ItemBLANK = `&lt;p style = "position:absolute; margin-top: 0em; left: ${ListOfItems&#91;5].x}px; top: ${ListOfItems&#91;5].y}px"&gt;`+ `${makeItem(OneItemBlinkColor)}&lt;/p&gt;`;
ListOfItems&#91;5].ItemACKNW = `&lt;p style = "position:absolute; margin-top: 0em; left: ${ListOfItems&#91;5].x}px; top: ${ListOfItems&#91;5].y}px"&gt;`+ `${makeItem(OneItemClickColor)}&lt;/p&gt;`;


ListOfItems&#91;6].ItemHTML  = `&lt;p style = "position:absolute; margin-top: 0em; left: ${ListOfItems&#91;6].x}px; top: ${ListOfItems&#91;6].y}px"&gt;`+ `${makeItem(OneItemShownColor)} &lt;/p&gt;`;
ListOfItems&#91;6].ItemBLANK = `&lt;p style = "position:absolute; margin-top: 0em; left: ${ListOfItems&#91;6].x}px; top: ${ListOfItems&#91;6].y}px"&gt;`+ `${makeItem(OneItemBlinkColor)}&lt;/p&gt;`;
ListOfItems&#91;6].ItemACKNW = `&lt;p style = "position:absolute; margin-top: 0em; left: ${ListOfItems&#91;6].x}px; top: ${ListOfItems&#91;6].y}px"&gt;`+ `${makeItem(OneItemClickColor)}&lt;/p&gt;`;

                                        
ListOfItems&#91;7].ItemHTML  = `&lt;p style = "position:absolute; margin-top: 0em; left: ${ListOfItems&#91;7].x}px; top: ${ListOfItems&#91;7].y}px"&gt;`+ `${makeItem(OneItemShownColor)} &lt;/p&gt;`;
ListOfItems&#91;7].ItemBLANK = `&lt;p style = "position:absolute; margin-top: 0em; left: ${ListOfItems&#91;7].x}px; top: ${ListOfItems&#91;7].y}px"&gt;`+ `${makeItem(OneItemBlinkColor)}&lt;/p&gt;`;
ListOfItems&#91;7].ItemACKNW = `&lt;p style = "position:absolute; margin-top: 0em; left: ${ListOfItems&#91;7].x}px; top: ${ListOfItems&#91;7].y}px"&gt;`+ `${makeItem(OneItemClickColor)}&lt;/p&gt;`;

ListOfItems&#91;8].ItemHTML  = `&lt;p style = "position:absolute; margin-top: 0em; left: ${ListOfItems&#91;8].x}px; top: ${ListOfItems&#91;8].y}px"&gt;`+ `${makeItem(OneItemShownColor)} &lt;/p&gt;`;
ListOfItems&#91;8].ItemBLANK = `&lt;p style = "position:absolute; margin-top: 0em; left: ${ListOfItems&#91;8].x}px; top: ${ListOfItems&#91;8].y}px"&gt;`+ `${makeItem(OneItemBlinkColor)}&lt;/p&gt;`;
ListOfItems&#91;8].ItemACKNW = `&lt;p style = "position:absolute; margin-top: 0em; left: ${ListOfItems&#91;8].x}px; top: ${ListOfItems&#91;8].y}px"&gt;`+ `${makeItem(OneItemClickColor)}&lt;/p&gt;`;

console.log('List of items done.')
console.log(ListOfItems)
console.log(ListOfItems&#91;1].x)


// list of blinking items
ListOfBlinkingItems&#91;0] = &#91;];
ListOfBlinkingItems&#91;0].x = ListOfItems&#91;0].x;
ListOfBlinkingItems&#91;0].y = ListOfItems&#91;0].y;
ListOfBlinkingItems&#91;0].ItemHTML  = `&lt;p style = "position:absolute; margin-top: 0em; left: ${ListOfBlinkingItems&#91;0].x}px; top: ${ListOfBlinkingItems&#91;0].y}px"&gt;${makeItem(OneItemShownColor)}&lt;/p&gt;`;
ListOfBlinkingItems&#91;0].ItemBLANK = `&lt;p style = "position:absolute; margin-top: 0em; left: ${ListOfBlinkingItems&#91;0].x}px; top: ${ListOfBlinkingItems&#91;0].y}px"&gt;${makeItem(OneItemBlinkColor)}&lt;/p&gt;`;                                       

ListOfBlinkingItems&#91;1] = &#91;];
ListOfBlinkingItems&#91;1].x = ListOfItems&#91;1].x;
ListOfBlinkingItems&#91;1].y = ListOfItems&#91;1].y;
ListOfBlinkingItems&#91;1].ItemHTML  = `&lt;p style = "position:absolute; margin-top: 0em; left: ${ListOfBlinkingItems&#91;1].x}px; top: ${ListOfBlinkingItems&#91;1].y}px"&gt;${makeItem(OneItemShownColor)}&lt;/p&gt;`;
ListOfBlinkingItems&#91;1].ItemBLANK = `&lt;p style = "position:absolute; margin-top: 0em; left: ${ListOfBlinkingItems&#91;1].x}px; top: ${ListOfBlinkingItems&#91;1].y}px"&gt;${makeItem(OneItemBlinkColor)}&lt;/p&gt;`;   

ListOfBlinkingItems&#91;2] = &#91;];
ListOfBlinkingItems&#91;2].x = ListOfItems&#91;2].x;
ListOfBlinkingItems&#91;2].y = ListOfItems&#91;2].y;
ListOfBlinkingItems&#91;2].ItemHTML  = `&lt;p style = "position:absolute; margin-top: 0em; left: ${ListOfBlinkingItems&#91;2].x}px; top: ${ListOfBlinkingItems&#91;2].y}px"&gt;${makeItem(OneItemShownColor)}&lt;/p&gt;`;
ListOfBlinkingItems&#91;2].ItemBLANK = `&lt;p style = "position:absolute; margin-top: 0em; left: ${ListOfBlinkingItems&#91;2].x}px; top: ${ListOfBlinkingItems&#91;2].y}px"&gt;${makeItem(OneItemBlinkColor)}&lt;/p&gt;`;   

ListOfBlinkingItems&#91;3] = &#91;];
ListOfBlinkingItems&#91;3].x = ListOfItems&#91;3].x;
ListOfBlinkingItems&#91;3].y = ListOfItems&#91;3].y;
ListOfBlinkingItems&#91;3].ItemHTML  = `&lt;p style = "position:absolute; margin-top: 0em; left: ${ListOfBlinkingItems&#91;3].x}px; top: ${ListOfBlinkingItems&#91;3].y}px"&gt;${makeItem(OneItemShownColor)}&lt;/p&gt;`;
ListOfBlinkingItems&#91;3].ItemBLANK = `&lt;p style = "position:absolute; margin-top: 0em; left: ${ListOfBlinkingItems&#91;3].x}px; top: ${ListOfBlinkingItems&#91;3].y}px"&gt;${makeItem(OneItemBlinkColor)}&lt;/p&gt;`;   

ListOfBlinkingItems&#91;4] = &#91;];
ListOfBlinkingItems&#91;4].x = ListOfItems&#91;4].x;
ListOfBlinkingItems&#91;4].y = ListOfItems&#91;4].y;
ListOfBlinkingItems&#91;4].ItemHTML  = `&lt;p style = "position:absolute; margin-top: 0em; left: ${ListOfBlinkingItems&#91;4].x}px; top: ${ListOfBlinkingItems&#91;4].y}px"&gt;${makeItem(OneItemShownColor)}&lt;/p&gt;`;
ListOfBlinkingItems&#91;4].ItemBLANK = `&lt;p style = "position:absolute; margin-top: 0em; left: ${ListOfBlinkingItems&#91;4].x}px; top: ${ListOfBlinkingItems&#91;4].y}px"&gt;${makeItem(OneItemBlinkColor)}&lt;/p&gt;`;   

ListOfBlinkingItems&#91;5] = &#91;];
ListOfBlinkingItems&#91;5].x = ListOfItems&#91;5].x;
ListOfBlinkingItems&#91;5].y = ListOfItems&#91;5].y;
ListOfBlinkingItems&#91;5].ItemHTML  = `&lt;p style = "position:absolute; margin-top: 0em; left: ${ListOfBlinkingItems&#91;5].x}px; top: ${ListOfBlinkingItems&#91;5].y}px"&gt;${makeItem(OneItemShownColor)}&lt;/p&gt;`;
ListOfBlinkingItems&#91;5].ItemBLANK = `&lt;p style = "position:absolute; margin-top: 0em; left: ${ListOfBlinkingItems&#91;5].x}px; top: ${ListOfBlinkingItems&#91;5].y}px"&gt;${makeItem(OneItemBlinkColor)}&lt;/p&gt;`;   

ListOfBlinkingItems&#91;6] = &#91;];
ListOfBlinkingItems&#91;6].x = ListOfItems&#91;6].x;
ListOfBlinkingItems&#91;6].y = ListOfItems&#91;6].y;
ListOfBlinkingItems&#91;6].ItemHTML  = `&lt;p style = "position:absolute; margin-top: 0em; left: ${ListOfBlinkingItems&#91;6].x}px; top: ${ListOfBlinkingItems&#91;6].y}px"&gt;${makeItem(OneItemShownColor)}&lt;/p&gt;`;
ListOfBlinkingItems&#91;6].ItemBLANK = `&lt;p style = "position:absolute; margin-top: 0em; left: ${ListOfBlinkingItems&#91;6].x}px; top: ${ListOfBlinkingItems&#91;6].y}px"&gt;${makeItem(OneItemBlinkColor)}&lt;/p&gt;`;   

ListOfBlinkingItems&#91;7] = &#91;];
ListOfBlinkingItems&#91;7].x = ListOfItems&#91;7].x;
ListOfBlinkingItems&#91;7].y = ListOfItems&#91;7].y;
ListOfBlinkingItems&#91;7].ItemHTML  = `&lt;p style = "position:absolute; margin-top: 0em; left: ${ListOfBlinkingItems&#91;7].x}px; top: ${ListOfBlinkingItems&#91;7].y}px"&gt;${makeItem(OneItemShownColor)}&lt;/p&gt;`;
ListOfBlinkingItems&#91;7].ItemBLANK = `&lt;p style = "position:absolute; margin-top: 0em; left: ${ListOfBlinkingItems&#91;7].x}px; top: ${ListOfBlinkingItems&#91;7].y}px"&gt;${makeItem(OneItemBlinkColor)}&lt;/p&gt;`;   

ListOfBlinkingItems&#91;8] = &#91;];
ListOfBlinkingItems&#91;8].x = ListOfItems&#91;8].x;
ListOfBlinkingItems&#91;8].y = ListOfItems&#91;8].y;
ListOfBlinkingItems&#91;8].ItemHTML  = `&lt;p style = "position:absolute; margin-top: 0em; left: ${ListOfBlinkingItems&#91;8].x}px; top: ${ListOfBlinkingItems&#91;8].y}px"&gt;${makeItem(OneItemShownColor)}&lt;/p&gt;`;
ListOfBlinkingItems&#91;8].ItemBLANK = `&lt;p style = "position:absolute; margin-top: 0em; left: ${ListOfBlinkingItems&#91;8].x}px; top: ${ListOfBlinkingItems&#91;8].y}px"&gt;${makeItem(OneItemBlinkColor)}&lt;/p&gt;`;   

console.log('List of bliking items done.')
console.log('End of the items definitions')
console.log(ListOfBlinkingItems)



// they are also concatenated in a list of buttons 
ListOfButtons.push(`&lt;button type=button style = "position:absolute; `+ `margin-top: 0px; padding: 0px; background: none; `+ 
`border: none; left: ${ListOfItems&#91;0].x}px; top: ${ListOfItems&#91;0].y}px"&gt;`+ `${makeItem(OneItemShownColor)}&lt;/button&gt;` )

ListOfButtons.push(`&lt;button type=button style = "position:absolute; `+ `margin-top: 0px; padding: 0px; background: none; `+ 
`border: none; left: ${ListOfItems&#91;1].x}px; top: ${ListOfItems&#91;1].y}px"&gt;`+ `${makeItem(OneItemShownColor)}&lt;/button&gt;` )

ListOfButtons.push(`&lt;button type=button style = "position:absolute; `+ `margin-top: 0px; padding: 0px; background: none; `+ 
`border: none; left: ${ListOfItems&#91;2].x}px; top: ${ListOfItems&#91;2].y}px"&gt;`+ `${makeItem(OneItemShownColor)}&lt;/button&gt;` )

ListOfButtons.push(`&lt;button type=button style = "position:absolute; `+ `margin-top: 0px; padding: 0px; background: none; `+ 
`border: none; left: ${ListOfItems&#91;3].x}px; top: ${ListOfItems&#91;3].y}px"&gt;`+ `${makeItem(OneItemShownColor)}&lt;/button&gt;` )

ListOfButtons.push(`&lt;button type=button style = "position:absolute; `+ `margin-top: 0px; padding: 0px; background: none; `+ 
`border: none; left: ${ListOfItems&#91;4].x}px; top: ${ListOfItems&#91;4].y}px"&gt;`+ `${makeItem(OneItemShownColor)}&lt;/button&gt;` )

ListOfButtons.push(`&lt;button type=button style = "position:absolute; `+ `margin-top: 0px; padding: 0px; background: none; `+ 
`border: none; left: ${ListOfItems&#91;5].x}px; top: ${ListOfItems&#91;5].y}px"&gt;`+ `${makeItem(OneItemShownColor)}&lt;/button&gt;` )

ListOfButtons.push(`&lt;button type=button style = "position:absolute; `+ `margin-top: 0px; padding: 0px; background: none; `+ 
`border: none; left: ${ListOfItems&#91;6].x}px; top: ${ListOfItems&#91;6].y}px"&gt;`+ `${makeItem(OneItemShownColor)}&lt;/button&gt;` )

ListOfButtons.push(`&lt;button type=button style = "position:absolute; `+ `margin-top: 0px; padding: 0px; background: none; `+ 
`border: none; left: ${ListOfItems&#91;7].x}px; top: ${ListOfItems&#91;7].y}px"&gt;`+ `${makeItem(OneItemShownColor)}&lt;/button&gt;` )

ListOfButtons.push(`&lt;button type=button style = "position:absolute; `+ `margin-top: 0px; padding: 0px; background: none; `+ 
`border: none; left: ${ListOfItems&#91;8].x}px; top: ${ListOfItems&#91;8].y}px"&gt;`+ `${makeItem(OneItemShownColor)}&lt;/button&gt;` )

console.log('List of buttons done.')
console.log(ListOfButtons)





// mouse pointer functions 
var HideMouse = function() { if (MouseToBeHidden) {
        document.querySelector('head').insertAdjacentHTML('beforeend', '&lt;style id="cursor-toggle"&gt; html { cursor: none; } &lt;/style&gt;');
    }
}
var ShowMouse = function() { if (MouseToBeHidden) {
        document.querySelector('#cursor-toggle').remove();
    }
}

console.log('hide mouse ')

// *************************************** 
// *   Defining experiment-level events  * 
// *************************************** 

// // Toggle full screen on or off 
// var FullScreenOn = {
//     type: 'fullscreen',
//     message: "&lt;p&gt;The experiment will be in full screen mode once you click on the button.&lt;/p&gt;",
//     button_label: 'Full Screen Mode',
//     fullscreen_mode: true
// }
// var FullScreenOff = {
//     type: 'fullscreen',
//     fullscreen_mode: false
// }
// the Welcome and Bye object descriptions 
var SayWelcome = {
    type: 'html-button-response',
    stimulus: 'Welcome to the Corsi Task. &lt;/p&gt; In this task, we would like to know how well you can reproduce the order of blocks highlighted on the screen. &lt;/p&gt; '+
    'First, you will be shown the order of blocks highlighted one by one on the screen and you should try to remember the order of the blocks highlighted as accurately as possible.&lt;/p&gt;' +
    'You will then immediately reproduce the same order of blocks highlighted by clicking on the blocks in exactly the same order as shown before.&lt;/p&gt;' +
    'Click on the Next button to begin the practice trials.',
    choices: &#91;'Next'],
}

var SayFormal = {
    type: 'html-button-response',
    stimulus: 'This is the end of the practice trials. You will now begin the experiment trials. &lt;/p&gt;Click on the Next button to begin.',
    choices: &#91;'Next'],
}

var SayBye = {
    type: 'html-button-response',
    stimulus: 'Thank you for your participation.&lt;/p&gt; Click on Next button to start next task.',
    choices: &#91;'Next'],
}


// *************************************** 
// *     Defining trial-level events     * 
// *************************************** 

var SetnBlinkingItems = {
    type: 'call-function',
    func: function() {
            nBlinkingItems =  jsPsych.timelineVariable("OneSequenceLength", true); 
            console.log("&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;&lt;number of blinking items:", nBlinkingItems);
            console.log(nBlinkingItems);
            currentBlinkingItem = 0;  // counter that will count the number of blinks    
            currentResponse = 0;      // counter that will count the number of responses  
        },
}


var WaitInterTrialDuration = {
    type: 'html-keyboard-response-noerase',
    stimulus: '',
    choices: "NO_KEYS",
    trial_duration: InterTrialDuration
}


var WaitPreBlinkDuration = {
    type: 'html-keyboard-response-noerase',
    stimulus: '',
    choices: "NO_KEYS",
    trial_duration: PreBlinkDuration
}


var WaitBlinkDuration = {
    type: 'html-keyboard-response-noerase',
    stimulus: '',
    choices: "NO_KEYS",
    trial_duration: BlinkDuration
}


var WaitInterBlinkDuration = {
    type: 'html-keyboard-response-noerase',
    stimulus: '',
    choices: "NO_KEYS",
    trial_duration: InterBlinkDuration
}


var WaitPostBlinkDuration = {
    type: 'html-keyboard-response-noerase',
    stimulus: '',
    choices: "NO_KEYS",
    trial_duration: PostBlinkDuration,
}


var ShowFixation = {
    type: 'html-keyboard-response',
    stimulus: '+',
    choices: "NO_KEYS",
    trial_duration: FixationDuration,
    on_start: HideMouse
}


var ShowOneItem = {
    type: 'html-keyboard-response-noerase',
    stimulus: jsPsych.timelineVariable('ItemHTML'),
    choices: "NO_KEYS",
    trial_duration: 0
}


var ShowAllItems = {
    timeline: &#91; ShowOneItem ],
    timeline_variables: ListOfItems
}


var BlinkOneItem = {
    type: 'html-keyboard-response-noerase',
    stimulus: jsPsych.timelineVariable('ItemBLANK'),
    choices: jsPsych.NO_KEYS,
    trial_duration: 0,
    data: {phase: 'BlinkedItemsPhase'},
}


var BlinkAllItems = {
    timeline: &#91; BlinkOneItem, WaitBlinkDuration, ShowOneItem, WaitInterBlinkDuration ],
    timeline_variables: ListOfBlinkingItems,
    sample: {type: 'without-replacement'},
    conditional_function: function() {if(currentBlinkingItem++ &lt; nBlinkingItems) {return true;} else {return false;}}
}



var StartResponding = {
    type: 'audio-keyboard-response',
    stimulus: RecallSignal,
    choices: jsPsych.NO_KEYS,
    trial_duration: RecallSignalDuration,
    on_start: ShowMouse
}


var BlinkThatResponse = {
    type: 'html-button-response',
    stimulus: '',
    button_html: function() {
                    var choice = jsPsych.data.get().last(1).values()&#91;0].button_pressed; 
                    if (choice !== null) {return ListOfButtons.concat(ListOfItems&#91;choice].ItemACKNW);} 
                    else {return "";}
                },
    trial_duration: AcknowledgeDuration,
    choices: function() {return &#91;...Array(ListOfButtons.length+1).keys()]}
}



var ReadOneResponse = {
    type: 'html-button-response',
    stimulus: '',
    button_html: ListOfButtons,
    choices: function() {return &#91;...Array(ListOfButtons.length).keys()] },
    trial_duration: 5000
}



var ReadAllResponses = {
    timeline: &#91; ReadOneResponse, BlinkThatResponse ], 
    timeline_variables: ListOfBlinkingItems,
    conditional_function: function() {if(currentResponse++ &lt; nBlinkingItems) {return true;} else {return false;}}
}

let j = 1;
let terminate = false;
var GatherResponses = {
    // jsPsych.data collects everything, so needs to filter
    // the odd button presses on the last 2*nBlinkingItems events
    type: 'call-function',
    func: function() {
        
        // Find the blink positions. 
        var blinkedItems = jsPsych.data.get().filter({phase: 'BlinkedItemsPhase'}).last(nBlinkingItems).select('stimulus').values;
        let xPositions = "";
        let xPositions_index = "";
        for (let i = 0; i &lt; blinkedItems.length; i++) {
            xPositions = blinkedItems&#91;i].match(/(-\d+|\d+)(,\d+)*(\.\d+)*/g)&#91;1] // extract X position numbers;
            xPositions_index = xPositions_index + &#91;ListOfItemsXPositions.findIndex(element =&gt; element == xPositions)]
        }


        var stem = jsPsych.data.get().filter({trial_type: 'html-button-response'}).last(2*nBlinkingItems);
        var responses = stem.select('button_pressed').values.filter((a,i)=&gt;i%2===0);
        responses = responses.map(Number);
        jsPsych.data.addProperties({resp: responses});
        console.log("click order: ", responses )

        var correct   =  Array.from(String(xPositions_index), Number);
        jsPsych.data.addProperties({stimuli: correct});
        console.log("Correct: ", correct)
        
        var acc       = responses.every(function(value, index) { return value === correct&#91;index]});
        jsPsych.data.addProperties({accuracy: acc});
        
        var rts = stem.select('rt').values.filter((a,i)=&gt;i%2===0);
        jsPsych.data.addProperties({RT: rts});
        
        console.log("Responses: ", responses, " accuracty: ", acc, " RT: ", rts);

        // calculate acc for two trials in one sequence
        if (j%2===0 &amp;&amp; j!=0) {
            acc_accumulation = acc_accumulation+acc;
            // console.log("acc_accumulation 1: ",acc_accumulation)
            if (acc_accumulation==0){terminate = true;} else {terminate = false}
            // console.log("termination status 1:", terminate)
            acc_accumulation = 0;
            j = 1;
        } else {
            acc_accumulation = acc_accumulation+acc;
            j++;                    
        }

        // console.log("acc_accumulation: ",acc_accumulation, "j ",j, "termination status:", terminate)
    }
}



var break_trial = {
    type: 'html-button-response',
    stimulus:  " ",
    choices: " ",
    trial_duration: 1000,
  };
  
  var break_conditional = {
      timeline: &#91;break_trial],
      // terminate experiment if two errors in a row. 
      conditional_function: function() {
          if (terminate==true) {
            return jsPsych.endExperiment('This task has been terminated.');;
          } else {
            return null;
          }
    }
  };



  var RunOneTrial_prac = {
    timeline: &#91; SetnBlinkingItems,
                WaitInterTrialDuration,
                ShowFixation, 
                ShowAllItems, 
                WaitPreBlinkDuration, 
                BlinkAllItems, 
                WaitPostBlinkDuration,
                StartResponding,
                ReadAllResponses,
                //GatherResponses,
            ],
    randomize_order:    false,
    repetitions:        sequenceRepetition
}



var RunOneTrial = {
    timeline: &#91; SetnBlinkingItems,
                WaitInterTrialDuration,
                ShowFixation, 
                ShowAllItems, 
                WaitPreBlinkDuration, 
                BlinkAllItems, 
                WaitPostBlinkDuration,
                StartResponding,
                ReadAllResponses,
                GatherResponses,
                break_conditional // break if fails both trials in one sequence. 
            ],
    randomize_order:    false,
    repetitions:        sequenceRepetition
}


var RunPractice = {
    timeline:           &#91; RunOneTrial_prac ],
    timeline_variables: sequenceLengths_prac,
    randomize_order:    sequenceRandomOrder
}

var RunAllTrials = {
    timeline:           &#91; RunOneTrial ],
    timeline_variables: sequenceLengths,
    randomize_order:    sequenceRandomOrder
}


jsPsych.init({
    use_webaudio: false,
    timeline: &#91;SayWelcome, RunPractice, SayFormal, RunAllTrials, SayBye],
    on_finish: function(){
      window.location.href = debrifurl},
    })</code></pre>



<p></p>



<p></p>



<p></p>
]]></content:encoded>
					
		
		<enclosure url="https://raw.githubusercontent.com/RMG2424/Dr.-Mid-Nite/master/CorsiBlockjsPsych/500hz-400ms.wav" length="6444" type="audio/wav" />

			</item>
		<item>
		<title>Dot Enumeration Task with jsPsych</title>
		<link>https://www.jianchen.info/2022/06/29/dot-enumeration-task-with-jspsych/</link>
		
		<dc:creator><![CDATA[saturn]]></dc:creator>
		<pubDate>Wed, 29 Jun 2022 01:36:40 +0000</pubDate>
				<category><![CDATA[research]]></category>
		<category><![CDATA[dotEnumeration]]></category>
		<category><![CDATA[github]]></category>
		<category><![CDATA[jsPsych]]></category>
		<guid isPermaLink="false">https://www.jianchen.info/?p=163</guid>

					<description><![CDATA[This task was coded with jsPsych v7.2. The source code and materials are available in my GitHub https://github.com/jianch/dotEnumerationTask Here is the key javascript.]]></description>
										<content:encoded><![CDATA[
<p></p>



<blockquote class="wp-block-quote"><p>This task was coded with jsPsych v7.2. The source code and materials are available in my GitHub </p></blockquote>



<p><a href="https://github.com/jianch/dotEnumerationTask">https://github.com/jianch/dotEnumerationTask</a></p>



<p></p>



<p>Here is the key javascript. </p>



<pre class="wp-block-code"><code>var jsPsych = initJsPsych({
  on_finish: function(){
    window.location.href = debrifurl},
});

/* url parameters*/
var id = jsPsych.data.getURLVariable("subjectid");
var debrifurl = "https://www.jianchen.info/?subjectid=".concat(id)  // go to another task

 /* create timeline */
var timeline = &#91;]; 

/* preload images */
var preload = {
  type: jsPsychPreload,
  images: &#91;'n1r1.png', 'n1r2.png', 'n1r3.png', 'n1r4.png','n1r5.png','n1r6.png', 'n1r7.png', 'n1r8.png',
           'n2r1.png', 'n2r2.png', 'n2r3.png', 'n2r4.png','n2r5.png','n2r6.png', 'n2r7.png', 'n2r8.png',
           'n3r1.png', 'n3r2.png', 'n3r3.png', 'n3r4.png','n3r5.png','n3r6.png', 'n3r7.png', 'n3r8.png',
           'n4r1.png', 'n4r2.png', 'n4r3.png', 'n4r4.png','n4r5.png','n4r6.png', 'n4r7.png', 'n4r8.png',
           'n5r1.png', 'n5r2.png', 'n5r3.png', 'n5r4.png','n5r5.png','n5r6.png', 'n5r7.png', 'n5r8.png',
           'n6r1.png', 'n6r2.png', 'n6r3.png', 'n6r4.png','n6r5.png','n6r6.png', 'n6r7.png', 'n6r8.png',
           'n7r1.png', 'n7r2.png', 'n7r3.png', 'n7r4.png','n7r5.png','n7r6.png', 'n7r7.png', 'n7r8.png',
           'n8r1.png', 'n8r2.png', 'n8r3.png', 'n8r4.png','n8r5.png','n8r6.png', 'n8r7.png', 'n8r8.png',
           'n9r1.png', 'n9r2.png', 'n9r3.png', 'n9r4.png','n9r5.png','n9r6.png', 'n9r7.png', 'n9r8.png',
           'n10r1.png', 'n10r2.png', 'n10r3.png', 'n10r4.png',
           ]};
timeline.push(preload);

// settings 
var pic_duration = 5000;
var fix_duration = &#91;200,500,700,900,1000];
var pic_size = 400;


var FullScreenOn = {
    type: jsPsychFullscreen,
    message: "&lt;p&gt;The experiment will be in full screen mode once you click on the button.&lt;/p&gt;",
    button_label: 'Full Screen Mode',
    fullscreen_mode: true
}
timeline.push(FullScreenOn)

/* instructions */
var welcome = {
  type: jsPsychHtmlKeyboardResponse,
  stimulus: '&lt;p&gt;Welcome to the Dot Enumeration Task.&lt;/p&gt;' +
            '&lt;p&gt;In this task, we would like to know, as fast as you can and without making any mistakes, how many dots you see on the screen.&lt;/p&gt;'+
            '&lt;p&gt;A cross will appear on the screen followed by a display of dots. &lt;/p&gt;'+ 
            'Press the SPACE BAR as soon as you identify how many dots there are on the screen, and then select your answer immediately.&lt;p&gt;'+
            '&lt;p&gt;&lt;b&gt;Please respond as accurately and quickly as possible.&lt;/b&gt;&lt;/p&gt;'+
            'Press SPACEBAR to begin practice trials',
  choices: &#91;' '],
};
timeline.push(welcome);


/* defining practice stimululi*/
var prac_stimuli = &#91;
  {prac_stimulus: 'n1r1.png', correct_response:0},
  {prac_stimulus: 'n2r1.png', correct_response:1},
  {prac_stimulus: 'n3r1.png', correct_response:2},
  {prac_stimulus: 'n4r1.png', correct_response:3},
  {prac_stimulus: 'n5r1.png', correct_response:4},
  {prac_stimulus: 'n6r1.png', correct_response:5},
  {prac_stimulus: 'n7r1.png', correct_response:6},
  {prac_stimulus: 'n8r1.png', correct_response:7},
  {prac_stimulus: 'n9r1.png', correct_response:8},
  ];
  
  
var fixation = {
  type: jsPsychHtmlKeyboardResponse,
  stimulus: '&lt;div style="font-size:48px;"&gt;+&lt;/div&gt;',
  choices: "NO_KEYS",
  trial_duration: jsPsych.randomization.sampleWithReplacement(fix_duration, 1),
  data: {phase: 'fixation',},
};


var prac_stimulus = {
  type: jsPsychImageKeyboardResponse,
  stimulus: jsPsych.timelineVariable('prac_stimulus'),
  stimulus_height: pic_size,  
  maintain_aspect_ratio: true,
  choices: &#91;' '],
  data: {
    phase: 'prac_stimulus',
    prac_stimli:jsPsych.timelineVariable('prac_stimulus'),
  },
};

// response and feedback
var msg;
var prac_response = {
  type: jsPsychHtmlButtonResponse,
  stimulus: '&lt;p&gt;How many dots were on the screen?&lt;/p&gt;',
  choices: &#91;'1','2','3','4','5','6','7','8','9','10'],
  prompt: "&lt;p&gt;Select a number&lt;/p&gt;",
  data:{
    phase: 'practice_resp',
    correct_responses: jsPsych.timelineVariable('correct_response'),
  },
  on_finish: function(data){
    data.correct = data.response==jsPsych.timelineVariable('correct_response');
    if (data.correct){
      msg = "&lt;p style='font-size:22px; color:green;'&gt;Correct!&lt;/p&gt;";
    } else {
      msg = "&lt;p style='font-size:22px; color:red;'&gt;Incorrect!&lt;/p&gt;";
    }
  }
};

var practice_feedback = {
	type: jsPsychHtmlKeyboardResponse,
	trial_duration: 1000,
	choices: "NO_KEYS",
	stimulus: function(){return msg;},
};


var practice_procedure = {
  timeline: &#91;fixation, prac_stimulus, prac_response, practice_feedback],
  timeline_variables: jsPsych.randomization.shuffleNoRepeats(prac_stimuli), // make sure that neighboring elements in the array are different.
  // randomize_order: true,
  repetitions: 1,
};	
timeline.push(practice_procedure);






// Formal Experiment 

var pre_test = {
  type: jsPsychHtmlKeyboardResponse,
  stimulus: '&lt;p&gt;This is the end of the practice trials. You will now begin the experiment trials.  &lt;/p&gt; '+
            'Feedback will NOT be provided&lt;/p&gt; ' + 
            'Press Spacebar to begin.&lt;/p&gt;',
  choices: &#91;' '],
}; 
timeline.push(pre_test);



var test_stimuli = &#91;
  {stimulus: "n1r1.png",  correct_response: 0},
  { stimulus: "n1r2.png",  correct_response: 0},
  { stimulus: "n1r3.png",  correct_response: 0},
  { stimulus: "n1r4.png",  correct_response: 0},
  { stimulus: "n1r5.png",  correct_response: 0},
  { stimulus: "n1r6.png",  correct_response: 0},
  { stimulus: "n1r7.png",  correct_response: 0},
  { stimulus: "n1r8.png",  correct_response: 0},

  {stimulus: "n2r1.png",  correct_response: 1},
  { stimulus: "n2r2.png",  correct_response: 1},
  { stimulus: "n2r3.png",  correct_response: 1},
  { stimulus: "n2r4.png",  correct_response: 1},
  { stimulus: "n2r5.png",  correct_response: 1},
  { stimulus: "n2r6.png",  correct_response: 1},
  { stimulus: "n2r7.png",  correct_response: 1},
  { stimulus: "n2r8.png",  correct_response: 1},

  {stimulus: "n3r1.png",  correct_response: 2},
  { stimulus: "n3r2.png",  correct_response: 2},
  { stimulus: "n3r3.png",  correct_response: 2},
  { stimulus: "n3r4.png",  correct_response: 2},
  { stimulus: "n3r5.png",  correct_response: 2},
  { stimulus: "n3r6.png",  correct_response: 2},
  { stimulus: "n3r7.png",  correct_response: 2},
  { stimulus: "n3r8.png",  correct_response: 2},
  
  {stimulus: "n4r1.png",  correct_response: 3},
  { stimulus: "n4r2.png",  correct_response: 3},
  { stimulus: "n4r3.png",  correct_response: 3},
  { stimulus: "n4r4.png",  correct_response: 3},
  { stimulus: "n4r5.png",  correct_response: 3},
  { stimulus: "n4r6.png",  correct_response: 3},
  { stimulus: "n4r7.png",  correct_response: 3},
  { stimulus: "n4r8.png",  correct_response: 3},

  {stimulus: "n5r1.png",  correct_response: 4},
  { stimulus: "n5r2.png",  correct_response: 4},
  { stimulus: "n5r3.png",  correct_response: 4},
  { stimulus: "n5r4.png",  correct_response: 4},
  { stimulus: "n5r5.png",  correct_response: 4},
  { stimulus: "n5r6.png",  correct_response: 4},
  { stimulus: "n5r7.png",  correct_response: 4},
  { stimulus: "n5r8.png",  correct_response: 4},

  {stimulus: "n6r1.png",  correct_response: 5},
  { stimulus: "n6r2.png",  correct_response: 5},
  { stimulus: "n6r3.png",  correct_response: 5},
  { stimulus: "n6r4.png",  correct_response: 5},
  { stimulus: "n6r5.png",  correct_response: 5},
  { stimulus: "n6r6.png",  correct_response: 5},
  { stimulus: "n6r7.png",  correct_response: 5},
  { stimulus: "n6r8.png",  correct_response: 5},
  
  {stimulus: "n7r1.png",  correct_response: 6},
  { stimulus: "n7r2.png",  correct_response: 6},
  { stimulus: "n7r3.png",  correct_response: 6},
  { stimulus: "n7r4.png",  correct_response: 6},
  { stimulus: "n7r5.png",  correct_response: 6},
  { stimulus: "n7r6.png",  correct_response: 6},
  { stimulus: "n7r7.png",  correct_response: 6},
  { stimulus: "n7r8.png",  correct_response: 6},
  
  {stimulus: "n8r1.png",  correct_response: 7},
  { stimulus: "n8r2.png",  correct_response: 7},
  { stimulus: "n8r3.png",  correct_response: 7},
  { stimulus: "n8r4.png",  correct_response: 7},
  { stimulus: "n8r5.png",  correct_response: 7},
  { stimulus: "n8r6.png",  correct_response: 7},
  { stimulus: "n8r7.png",  correct_response: 7},
  { stimulus: "n8r8.png",  correct_response: 7},
  
  {stimulus: "n9r1.png",  correct_response: 8},
  { stimulus: "n9r2.png",  correct_response: 8},
  { stimulus: "n9r3.png",  correct_response: 8},
  { stimulus: "n9r4.png",  correct_response: 8},
  { stimulus: "n9r5.png",  correct_response: 8},
  { stimulus: "n9r6.png",  correct_response: 8},
  { stimulus: "n9r7.png",  correct_response: 8},
  { stimulus: "n9r8.png",  correct_response: 8},
  
  { stimulus: "n10r1.png",  correct_response: 9},
  { stimulus: "n10r2.png",  correct_response: 9},
  { stimulus: "n10r3.png",  correct_response: 9},
  { stimulus: "n10r4.png",  correct_response: 9},
];


/* define break trial */
var trial_count = 0;

var break_trial = {
  type: jsPsychHtmlKeyboardResponse,
  stimulus:  "&lt;p style='font-size: 18px'&gt;Please take a short break if needed.&lt;/p&gt;" + 
          "&lt;p style='font-size: 18px'&gt;When you are ready, continue by pressing the SPACEBAR.&lt;/p&gt;",
};


var break_conditional = {
  timeline: &#91;break_trial],
  // block rest determination
  conditional_function: function() {
    // increment trial count - in first run through the timeline variables procedure, trial_count will be equal to 1
    trial_count++;
    if (trial_count % 41 == 0 &amp;&amp; trial_count!=0) {
      // if the trial count is divisible by 40, then run the break trial
      return true;
    } else {
      // otherwise skip the break trial
      return false;
    }
  }
};




var test_stimulus = {
  type: jsPsychImageKeyboardResponse,
  stimulus: jsPsych.timelineVariable('stimulus'),
  stimulus_height: pic_size,  
  maintain_aspect_ratio: true,
  choices: &#91;' '],
  data: {
    phase: 'test_stimulus',
    test_stimli:jsPsych.timelineVariable('stimulus'),
  },
};


var test_response = {
  type: jsPsychHtmlButtonResponse,
  stimulus: '&lt;p&gt;How many dots were on the screen?&lt;/p&gt;',
  choices: &#91;'1','2','3','4','5','6','7','8','9','10'],
  prompt: "&lt;p&gt;Select a number&lt;/p&gt;",
  data:{
    phase: 'test_resp',
    correct_responses: jsPsych.timelineVariable('correct_response'),
  },
  on_finish: function(data){
    data.correct = data.response==jsPsych.timelineVariable('correct_response');},
};



var test_procedure = {
  timeline: &#91;fixation, test_stimulus, test_response, break_conditional],
  timeline_variables: jsPsych.randomization.shuffleNoRepeats(test_stimuli),
  // randomize_order: true,
  repetitions: 2,
};	
timeline.push(test_procedure);




var post_test = {
  type: jsPsychHtmlKeyboardResponse,
  stimulus: '&lt;p&gt;You have finished the Dot Enumeration Task.&lt;/p&gt; '+
            'Press Spacebar to start next task.&lt;/p&gt;',
  choices: &#91;' '],
}; 
timeline.push(post_test);





/* start the experiment */
jsPsych.run(timeline);</code></pre>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Install Process in SPSS in MacOS Big Sur</title>
		<link>https://www.jianchen.info/2021/09/09/install-process-in-spss-in-macos-big-sur/</link>
		
		<dc:creator><![CDATA[saturn]]></dc:creator>
		<pubDate>Thu, 09 Sep 2021 00:14:18 +0000</pubDate>
				<category><![CDATA[research]]></category>
		<category><![CDATA[MacOS]]></category>
		<category><![CDATA[SPSS]]></category>
		<guid isPermaLink="false">https://www.jianchen.info/?p=131</guid>

					<description><![CDATA[I don’t like SPSS, but due to the need of teaching, I have to install SPSS in my own computer. When I tried to install Hayes’ Process add-ons in the SPSS, it always said it has no permission to do so. This is quite annoying. So the reason is that SPSS has no full disk ... <a title="Install Process in SPSS in MacOS Big Sur" class="read-more" href="https://www.jianchen.info/2021/09/09/install-process-in-spss-in-macos-big-sur/" aria-label="More on Install Process in SPSS in MacOS Big Sur">Read more</a>]]></description>
										<content:encoded><![CDATA[
<p>I don’t like SPSS, but due to the need of teaching, I have to install SPSS in my own computer.</p>



<p>When I tried to install Hayes’ Process add-ons in the SPSS, it always said it has no permission to do so. This is quite annoying.</p>



<p>So the reason is that SPSS has no full disk access to the targeted folder. Why? I already gave full access to it.</p>



<p>It turns out that there are a few things changed since MacOS Catalina, the direct result is that SPSS lost full disk access to many folders in Mac. You have to give a quite specific permission to SPSS.</p>



<p>The video below is the solution for this issue.</p>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe loading="lazy" title="How to Fix SPSS File Access issue after Mac Catalina update - new apple update" width="1100" height="619" src="https://www.youtube.com/embed/gmBn5SneX2I?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
</div></figure>



<p>After you fix the full disk access issue, then you will be able to install Process.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Digit Span Task in Qualtrics</title>
		<link>https://www.jianchen.info/2021/07/23/digit-span-task-in-qualtrics/</link>
		
		<dc:creator><![CDATA[saturn]]></dc:creator>
		<pubDate>Fri, 23 Jul 2021 00:13:10 +0000</pubDate>
				<category><![CDATA[research]]></category>
		<category><![CDATA[digit span task]]></category>
		<category><![CDATA[Qualtrics]]></category>
		<category><![CDATA[working memory]]></category>
		<guid isPermaLink="false">https://www.jianchen.info/?p=129</guid>

					<description><![CDATA[The pandemic makes online psychological experiments very needed in the past few months. One commonly used tool is Qualtrics. I don’t have too many complains about Qualtrics except for its ability to DIY cognitive tasks. I don’t see why they don’t include this feature as many of us already bought their most expensive plans. Nevertheless, ... <a title="Digit Span Task in Qualtrics" class="read-more" href="https://www.jianchen.info/2021/07/23/digit-span-task-in-qualtrics/" aria-label="More on Digit Span Task in Qualtrics">Read more</a>]]></description>
										<content:encoded><![CDATA[
<p>The pandemic makes online psychological experiments very needed in the past few months. One commonly used tool is Qualtrics.</p>



<p>I don’t have too many complains about Qualtrics except for its ability to DIY cognitive tasks. I don’t see why they don’t include this feature as many of us already bought their most expensive plans.</p>



<p>Nevertheless, there are alternative ways to run cognitive tasks with Qualtrics surveys. One way is to use Inquisit Web. But we all know that participants really don’t like to download and install any software in their personal devices, so we see many participants drop out the study due to this reason. May I say that we are lucky enough if we can have 50% participants complete the Inquisit Web-based cognitive tasks? Other ways to run online cognitive tasks include the PsychoPy and PsyToolkit, but I won’t talk about them in this article.</p>



<p>The ideal way to run cognitive tasks along with Qualtrics survey, of course, is to run cognitive tasks within Qualtrics.</p>



<p>Here is an example of running digit span task within Qualtrics. I need to explicitly state that, the code is not from me. I developed my own working version with the help from Dr Becky Gilbert (@BeckyAGilbert). You can find her at&nbsp;<a href="https://www.mrc-cbu.cam.ac.uk/people/becky.gilbert/">https://www.mrc-cbu.cam.ac.uk/people/becky.gilbert/</a>. And of course, if you do use the task and the code, it would be appreciated either a citation or acknowledgment. You should also cite the QRTE paper:&nbsp;<a rel="noreferrer noopener" href="https://link.springer.com/article/10.3758/s13428-014-0530-7" target="_blank">https://link.springer.com/article/10.3758/s13428-014-0530-7</a>&nbsp;.</p>



<p><strong>You can find&nbsp;Dr Becky Gilbert’s Digit Span Task at this link:&nbsp;<a href="https://uclpsych.eu.qualtrics.com/jfe/form/SV_55fg8t1Q3MGO8U5?Q_JFE=qdg">https://uclpsych.eu.qualtrics.com/jfe/form/SV_55fg8t1Q3MGO8U5?Q_JFE=qdg</a></strong>. The first half of the task works fine but the second half does not work. This is because&nbsp;QRTE JavaScript library is no longer supported.<br><br>Here is the QSF file that exported from Qualtrics.</p>



<p><a href="https://jianch.github.io/wp-content/uploads/2021/07/digit_span_demo.qsf_.zip">digit_span_demo.qsf_</a><a href="https://jianch.github.io/wp-content/uploads/2021/07/digit_span_demo.qsf_.zip">Download</a></p>



<p>To get it to work properly, you may need to go into the survey settings and remove any default styling that your institution applies to&nbsp;Qualtrics&nbsp;surveys. You’ll want to use the plain/basic styling option for this task. You can also look at the QRTE documentation for more information about how it works:&nbsp;<a rel="noreferrer noopener" href="http://www.qrtengine.com/" target="_blank">http://www.qrtengine.com/</a></p>



<p>In my case, I have to put the forward and backward parts separately into two Qualtrics surveys, otherwise it just won’t work. I would recommend you do the same thing.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Embed Youtube video in the Inquisit Web in Windows and Mac</title>
		<link>https://www.jianchen.info/2020/04/06/embed-youtube-video-in-the-inquisit-web-in-windows-and-mac/</link>
		
		<dc:creator><![CDATA[saturn]]></dc:creator>
		<pubDate>Mon, 06 Apr 2020 00:11:19 +0000</pubDate>
				<category><![CDATA[research]]></category>
		<category><![CDATA[Inquisit]]></category>
		<category><![CDATA[Youtube]]></category>
		<guid isPermaLink="false">https://www.jianchen.info/?p=127</guid>

					<description><![CDATA[It is necessary to use online video source when you want to present long video clips in an Inquisit Web script. This is because the Inquisit Web server only provides 60MB space for you, although we all pay them a big amount of money, such a small storage space can only host a few short ... <a title="Embed Youtube video in the Inquisit Web in Windows and Mac" class="read-more" href="https://www.jianchen.info/2020/04/06/embed-youtube-video-in-the-inquisit-web-in-windows-and-mac/" aria-label="More on Embed Youtube video in the Inquisit Web in Windows and Mac">Read more</a>]]></description>
										<content:encoded><![CDATA[
<p>It is necessary to use online video source when you want to present long video clips in an Inquisit Web script. This is because the Inquisit Web server only provides 60MB space for you, although we all pay them a big amount of money, such a small storage space can only host a few short and low resolution videos.</p>



<p>Thankfully, Inquisit is able to handle html page, which is great. Theoretically, you only need to embed an iframe element in the Inquisit script and it should be able to fetch video from Youtube or other sources.&nbsp;</p>



<p>You will need an embeded video link like this, it can be obtained from Youtube Share.</p>



<figure class="wp-block-embed"><div class="wp-block-embed__wrapper">
https://youtube.com/watch?v=LW2oswdWs4Q%3Frel%3D0%26controls%3D0%26showinfo%3D0%26autoplay%3D1
</div></figure>



<p>Then you need to add a html element in the Inquisit, it looks like this:</p>



<pre class="wp-block-code"><code>&lt;html demo&gt;
/ items = videos
/ select = 1
/ size = (100%,100%)
/ showborders = false
/ showscrollbars = false
&lt;/html&gt;</code></pre>



<p>However, this method only works fine in MacOS, it shows blank when you run the Inquisit script in a Windows computer. This is a known issue and there is no official solution yet.&nbsp;</p>



<p>————————————<br><strong>Q:&nbsp;</strong><br>I’ve used html to embed videos in my experiment that I have uploaded on youtube.<br>The embedded links when directly entered into the browser (firefox, internet explorer) work fine. Within inquisit it also works fine on a mac, but I’m encountering problems on windows (on some windows laptops it only shows a black box rather than the video). Also, there seem to be a difference between windows 10 and windows 7, since it did work on someone’s windows 7 laptop.<br>Is there a difference for html on mac vs windows?</p>



<p><strong>A:&nbsp;</strong><br>Yes, there are differences between OSX and Windows in how HTML is handled. Essentially, under Windows, Inquisit embeds Internet Explorer (because it is reliably available on all Windows systems) to render HTML. When run in embedded mode like this, however, Internet Explorer enforces various restrictions that may keep embedded / interactive content such as videos from working. The way a given system is set up and what security settings the user or organization applied to Internet Explorer installations also play a role under some circumstances, i.e. content may work on one system, but not on a different one with different settings / restrictions applied.<br><strong>I’m afraid there isn’t a really good or universal solution here.&nbsp;</strong>Ideally, you’d not embed Youtube videos, but instead you’d use standard \&lt;video&gt; elements in Inquisit to play the videos. For online use, you can set the \&lt;video&gt; elements’ /stream attributes to true, that way the won’t have to be downloaded in full before the experiment launches, they’ll be streamed instead at runtime.<br><em><a href="https://www.millisecond.com/forums/Topic25195.aspx" target="_blank" rel="noreferrer noopener">https://www.millisecond.com/forums/Topic25195.aspx</a></em><br>————————————</p>



<p>A possible workaround is to right click on the black screen and then choose a different encoding, such as “Western European (Windows)”. Then the online video will be loaded and displayed on the Inquisit. There seems to be an encoding issue in running Inquisit script in Windows.</p>



<figure class="wp-block-image"><img decoding="async" src="https://jianch.github.io/wp-content/uploads/2021/02/rightClick-1024x473.png" alt="" class="wp-image-143"/></figure>



<p>So, is there a “<strong>really good or universal solution</strong>” for this problem? The answer is&nbsp;<strong>YES.</strong></p>



<p>My idea here is, if the Inquisit is able to handle html element, can we directly insert a DIY html page rather than let the Inquisit build a html page?&nbsp;</p>



<p>Here, I created a html page with some help from W3Schools and other resources:_(<a rel="noreferrer noopener" href="https://benmarshall.me/responsive-iframes/" target="_blank">https://benmarshall.me/responsive-iframes/</a>;&nbsp;<a rel="noreferrer noopener" href="https://www.w3schools.com/tags/att_body_bgcolor.asp" target="_blank">https://www.w3schools.com/tags/att_body_bgcolor.asp</a>;&nbsp;<a rel="noreferrer noopener" href="https://stackoverflow.com/questions/15844500/shrink-a-youtube-video-to-responsive-width" target="_blank">https://stackoverflow.com/questions/15844500/shrink-a-youtube-video-to-responsive-width</a>)_</p>



<pre class="wp-block-code"><code>&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;style&gt;
.iframe-container {
 overflow: hidden;
 padding-top: 56.25%;
 position: relative;
}
.iframe-container iframe {
  border: 0;
  height: 100%;
  left: 0;
  position: absolute;
  top: 0;
  width: 100%;
}
/* 4x3 Aspect Ratio */
.iframe-container-4x3 {
 padding-top: 75%;
}
&lt;/style&gt;
&lt;/head&gt;

&lt;body bgcolor="black"&gt;

&lt;div class="iframe-container"&gt;
 &lt;iframe src="<a href="https://www.youtube.com/embed/LW2oswdWs4Q?~~start=10&amp;rel=0&amp;controls=0&amp;showinfo=0&amp;autoplay=1">https://www.youtube.com/embed/LW2oswdWs4Q?~~start=10&amp;rel=0&amp;controls=0&amp;showinfo=0&amp;autoplay=1</a>" allowfullscreen=1&gt;&lt;/iframe&gt;
&lt;/div&gt;

&lt;/body&gt;
&lt;/html&gt;</code></pre>



<p>You can create an empty html document and the copy these code into your document, or you can download a html file from&nbsp;<a href="https://jianchen.info/files/inquisitOnlineVideo/demo.html">here</a>.</p>



<p>When you have the DIY html file, let’s see an Inquisit&nbsp;<a href="https://jianchen.info/files/inquisitOnlineVideo/demo.iqx">demo</a>. This demo is extracted and modified from somewhere in the Inquisit forum. Nevertheless, it’s quite easy to make your own one.</p>



<pre class="wp-block-code"><code>&lt;html videoDemo&gt;
/ items = ("demo.html")
/ size = (100%, 100%) 
/ erase = true(255, 255, 255)
/ showborders = false
/ showscrollbars = false
&lt;/html&gt;

&lt;trial videoDemo&gt;
/ stimulustimes = &#91;500=videoDemo]
/ trialduration = 50000
/ ontrialend= &#91;trial.videoDemo.resetstimulusframes();]
&lt;/trial&gt;

&lt;block videoDemo&gt;
/ trials = &#91;1=videoDemo]
&lt;/block&gt;

&lt;expt&gt;
/ blocks = &#91;1=videoDemo]
&lt;/expt&gt;</code></pre>



<p>And boom! It works! Now we can display Youtube video in Inquisit in a damn Windows pc!</p>



<figure class="wp-block-image"><img decoding="async" src="https://jianch.github.io/wp-content/uploads/2021/02/htmlScreenshot-1024x583.png" alt="" class="wp-image-144"/></figure>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Change the space between paragraphs in Qualtrics</title>
		<link>https://www.jianchen.info/2019/11/12/change-the-space-between-paragraphs-in-qualtrics/</link>
		
		<dc:creator><![CDATA[saturn]]></dc:creator>
		<pubDate>Tue, 12 Nov 2019 00:10:12 +0000</pubDate>
				<category><![CDATA[research]]></category>
		<category><![CDATA[Qualtrics]]></category>
		<category><![CDATA[space]]></category>
		<guid isPermaLink="false">https://www.jianchen.info/?p=125</guid>

					<description><![CDATA[The space between paragraphs in the Qualtrics might be too large, how to reduce the space?&#160; One solution is to add JS code in the “Question JavaScript” to change the padding size or margin size before and after one paragraph. Note, Qualtrics appears to set up some kind of minimum space between paragraphs so even ... <a title="Change the space between paragraphs in Qualtrics" class="read-more" href="https://www.jianchen.info/2019/11/12/change-the-space-between-paragraphs-in-qualtrics/" aria-label="More on Change the space between paragraphs in Qualtrics">Read more</a>]]></description>
										<content:encoded><![CDATA[
<p>The space between paragraphs in the Qualtrics might be too large, how to reduce the space?&nbsp;</p>



<p>One solution is to add JS code in the “Question JavaScript” to change the padding size or margin size before and after one paragraph.</p>



<pre class="wp-block-code"><code>jQuery("#"+this.questionId).find('.QuestionText:first').css("padding-bottom", "0px");
jQuery("#"+this.questionId).find('.QuestionText:first').css("padding-top", "0px");</code></pre>



<p>Note, Qualtrics appears to set up some kind of minimum space between paragraphs so even if you change the padding value to 0, the space might still be large.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Plot Heatmap from Eye Tracking Data</title>
		<link>https://www.jianchen.info/2017/09/07/plot-heatmap-from-eye-tracking-data/</link>
		
		<dc:creator><![CDATA[saturn]]></dc:creator>
		<pubDate>Thu, 07 Sep 2017 00:09:14 +0000</pubDate>
				<category><![CDATA[research]]></category>
		<category><![CDATA[eyetracker]]></category>
		<category><![CDATA[heatmap]]></category>
		<guid isPermaLink="false">https://www.jianchen.info/?p=123</guid>

					<description><![CDATA[There are many ways/toolbox to plot a heat map from eye tracking data. but I prefer DIY Here is the source code:]]></description>
										<content:encoded><![CDATA[
<p>There are many ways/toolbox to plot a heat map from eye tracking data. but I prefer DIY</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>Here is the source code:</p>



<pre class="wp-block-code"><code>%% Data Structure Explanation
% Explanation from Eyelink Programers Guide 3.0

%--------------------------------------------------------
% dataEyelink =
%
%       samples: &#91;401341x4 double]()
%     fixations: &#91;3965x6 double]()
%      saccades: &#91;3964x9 double]()
%        blinks: &#91;1720x3 double]()
%      triggers: &#91;1080x3 double]()

%--------------------------------------------------------
% dataEyelink.samples
%       column1         column2         column3     column4
%       timepoint       x               y           pupil size
%--------------------------------------------------------
% dataEyelink.fixations
%       column1         column2         column3     column4 column5 column6
%       tmepoint_start  timepoint_end   duration    x       y       avg pupil size
%--------------------------------------------------------
% dataEyelink.saccades
%       column1         column2         column3     column4 column5 column6
%       tmepoint_start  timepoint_end   duration    x_from  y_from  x_to
%       column7         column8         column9
%       y_to            amplitude       peak velocity
%                       in degrees      degr/sec
%--------------------------------------------------------
% dataEyelink.blinks
%       column1         column2         column3
%       tmepoint_start  timepoint_end   duration
%--------------------------------------------------------
% dataEyelink.triggers
%       column1         column2         column3
%       tmepoint        1=SYNCON        Trial(I also wrote trial number)
%                       0=SYNCOFF
%--------------------------------------------------------



clear;
load xxxxEyelink.mat

%% variables
gaussSigma = 0.05;
posX = round(dataEyelink.fixations(:,4));
posY = round(dataEyelink.fixations(:,5));
gazeDuration = dataEyelink.fixations(:,3) / max(dataEyelink.fixations(:,3)); % rescale to 0-1

%% generating data for heatmap
gazedata = &#91;posX/1024, posY/768](); % rescale to 0-1
gazedata = gazedata((gazedata(:, 1))\&gt;0, :); % remove possible negative value...

%% make gaussians
figure;
&#91;X,Y]() = meshgrid(0:0.001:1, 0:0.001:1);
z = zeros(size(X,1),size(X,2));

for i = 1:length(gazedata)
z = z + gazeDuration(i) * exp(-( ((X - gazedata(i,1)).^2 ./ (2*gaussSigma^2)) + ((Y - gazedata(i,2)).^2 ./ (2*gaussSigma^2)) ) );
end

mesh(X,Y,z); % plot the heatmap
colorbar;
caxis(&#91;0,300]());
view(0,90);


print('heatmap', '-dtiff','-r300');</code></pre>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Corrected Vision May Still Bias the Gabor Patch Detection</title>
		<link>https://www.jianchen.info/2017/07/12/corrected-vision-may-still-bias-the-gabor-patch-detection/</link>
		
		<dc:creator><![CDATA[saturn]]></dc:creator>
		<pubDate>Wed, 12 Jul 2017 00:07:57 +0000</pubDate>
				<category><![CDATA[research]]></category>
		<category><![CDATA[Astigmatism]]></category>
		<category><![CDATA[corrected vision]]></category>
		<category><![CDATA[Gabor patch]]></category>
		<category><![CDATA[vision]]></category>
		<guid isPermaLink="false">https://www.jianchen.info/?p=121</guid>

					<description><![CDATA[As said in the title, participants with corrected vision (wearing glass or contact lens) may still have distorted vision due to whatever reason, especially in Gabor patch detection task. This question comes from my personal experience, I always feel that the vertical Gabor patch is brighter than horizontal ones, and is easier to detect. Below ... <a title="Corrected Vision May Still Bias the Gabor Patch Detection" class="read-more" href="https://www.jianchen.info/2017/07/12/corrected-vision-may-still-bias-the-gabor-patch-detection/" aria-label="More on Corrected Vision May Still Bias the Gabor Patch Detection">Read more</a>]]></description>
										<content:encoded><![CDATA[
<p>As said in the title, participants with corrected vision (wearing glass or contact lens) may still have distorted vision due to whatever reason, especially in Gabor patch detection task.</p>



<p>This question comes from my personal experience, I always feel that the vertical Gabor patch is brighter than horizontal ones, and is easier to detect. Below is my test data from 800 trials of a detection task (error bar represents 1 SE).</p>



<p>I gradually increased the Gabor patch contrast from 0 to 100%, I pressed a button when I saw something on the screen (grey background).</p>



<p><img decoding="async" src="https://jianchen.info/images/gabor/CJ04May17a.png" alt=""><br>Session 1</p>



<p><img decoding="async" src="https://jianchen.info/images/gabor/CJ04May17b.png" alt=""><br>Session 2</p>



<p>I am quite curious about why I feel so differently for these two kinds of Gabor patch, am I special? Do I have something wrong with my eye?</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>So I asked two colleague (they don’t wear glass regularly) to do the same task, and it turns out no difference between vertical and horizontal Gabor patches.</p>



<p><img decoding="async" src="https://jianchen.info/images/gabor/CV04May17a.png" alt=""><br>Colleague 1</p>



<p><img decoding="async" src="https://jianchen.info/images/gabor/JN06May17a.png" alt=""><br>Colleague 2</p>



<p>Then what’s going on underneath?</p>



<p>I doubt that although I have a glass to correct my vision, I may not have astigmatism corrected. So I asked a friend, who also wear a glass, to do the same task. As you can see, he has the same problem.</p>



<p><img decoding="async" src="https://jianchen.info/images/gabor/ZL28Jun17a.png" alt=""><br>Friend 1</p>



<p>Insofar, my guess of the explanation for such results is astigmatism. Me and my friend both have inappropriately corrected vision, which leads to the difference in detection task.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>You may have a quick test to see if you have astigmatism. All the bars in below should have similar brightness.</p>



<p><img decoding="async" src="https://jianchen.info/images/gabor/EYE_astigmatism.gif" alt=""><br>Astigmatism Test</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>What’s the hint from this observation? Well, it may remind us to make sure that participants who claim a correctly corrected vision should be re-checked, especially in those vision tasks relying on Gabor patch detection.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Get real-time gaze positions from the eye tracker</title>
		<link>https://www.jianchen.info/2017/03/30/get-real-time-gaze-positions-from-the-eye-tracker/</link>
		
		<dc:creator><![CDATA[saturn]]></dc:creator>
		<pubDate>Thu, 30 Mar 2017 00:06:55 +0000</pubDate>
				<category><![CDATA[research]]></category>
		<category><![CDATA[eyelink]]></category>
		<category><![CDATA[eyetracker]]></category>
		<category><![CDATA[gaze]]></category>
		<category><![CDATA[matlab]]></category>
		<guid isPermaLink="false">https://www.jianchen.info/?p=119</guid>

					<description><![CDATA[If I want to make sure the participants are fixating on the cross before starting each trial, how should I do? With the help of Eyetracker (Eyelink in this case), we can get the realtime gaze position and therefore we can monitor the gaze position to make sure it falls into a certain area before ... <a title="Get real-time gaze positions from the eye tracker" class="read-more" href="https://www.jianchen.info/2017/03/30/get-real-time-gaze-positions-from-the-eye-tracker/" aria-label="More on Get real-time gaze positions from the eye tracker">Read more</a>]]></description>
										<content:encoded><![CDATA[
<p>If I want to make sure the participants are fixating on the cross before starting each trial, how should I do?</p>



<p>With the help of Eyetracker (Eyelink in this case), we can get the realtime gaze position and therefore we can monitor the gaze position to make sure it falls into a certain area before the participants start the trial.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<pre class="wp-block-code"><code>% make sure participants are fixating on the central
while isEyeLink  % if Eyelink was connected
status = Eyelink('newfloatsampleavailable');  % check to see if everything is fine in Eyelink
if status /=0; % if all is fine
evt = Eyelink('newestfloatsample'); % get the newest float sample from Eyelink
realtime.x = evt.gx(1);  % get the x axis of gaze
realtime.y = evt.gy(1);  % get the y axis of gaze
end;

if abs(realtime.x-512)\&lt;=50&amp;abs(realtime.y-384)\&lt;=50  % if the gaze falls into  a 50\*50 pixel square around the cross
break; % jump out the loop and start the trial
end
end</code></pre>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Keyboard Calibration Using the Damn Laser</title>
		<link>https://www.jianchen.info/2017/03/09/keyboard-calibration-using-the-damn-laser/</link>
		
		<dc:creator><![CDATA[saturn]]></dc:creator>
		<pubDate>Thu, 09 Mar 2017 00:04:34 +0000</pubDate>
				<category><![CDATA[research]]></category>
		<category><![CDATA[calibration]]></category>
		<category><![CDATA[keyboard]]></category>
		<category><![CDATA[laser]]></category>
		<guid isPermaLink="false">https://www.jianchen.info/?p=115</guid>

					<description><![CDATA[Almost no one care about how precise/reliable the keyboard pressing is, here, we built a damn cool equipment to examine this question. Broadly speaking, the time precision is good, mean variance is less than 0.2 ms. Environment: MATLAB with Linux (Ubuntu 14.04) Monitor: SONY Triniton at 120Hz Keyboard: Mechanic number board In short, the delay ... <a title="Keyboard Calibration Using the Damn Laser" class="read-more" href="https://www.jianchen.info/2017/03/09/keyboard-calibration-using-the-damn-laser/" aria-label="More on Keyboard Calibration Using the Damn Laser">Read more</a>]]></description>
										<content:encoded><![CDATA[
<p>Almost no one care about how precise/reliable the keyboard pressing is, here, we built a damn cool equipment to examine this question. Broadly speaking, the time precision is good, mean variance is less than 0.2 ms.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>Environment: MATLAB with Linux (Ubuntu 14.04)</p>



<p>Monitor: SONY Triniton at 120Hz</p>



<p>Keyboard: Mechanic number board</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<figure class="wp-block-image"><img decoding="async" src="https://jianchen.info/images/laser/illustration.png" alt=""/></figure>



<p></p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<figure class="wp-block-image size-large"><img decoding="async" loading="lazy" width="1024" height="481" src="https://www.jianchen.info/wp-content/uploads/2022/06/Figure.2.3_figure-1024x481.jpg" alt="" class="wp-image-116" srcset="https://www.jianchen.info/wp-content/uploads/2022/06/Figure.2.3_figure-1024x481.jpg 1024w, https://www.jianchen.info/wp-content/uploads/2022/06/Figure.2.3_figure-300x141.jpg 300w, https://www.jianchen.info/wp-content/uploads/2022/06/Figure.2.3_figure-768x361.jpg 768w, https://www.jianchen.info/wp-content/uploads/2022/06/Figure.2.3_figure-1536x722.jpg 1536w, https://www.jianchen.info/wp-content/uploads/2022/06/Figure.2.3_figure-2048x962.jpg 2048w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>In short, the delay is about 12 ms and the variation is quite small. </p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
