Timeout for categorisation task

444 views
Skip to first unread message

experimenter

unread,
May 17, 2015, 11:23:53 AM5/17/15
to jsp...@googlegroups.com
Hi,
I'm trying to add a timeout for a categorisation task but I'm not sure how to go about it. Essentially if the participant presses the wrong key I would like something to show up on the screen for a set amount of time.

I'm guessing you need an if-loop chunk, so I have something like this to begin - but it's not working.

var timeout = {
type = "text",
text: "Timeout. Please wait."
}
var if_chunk = {
chunk_type: 'if',
timeline: [timeout],
conditional_function: function(){
var previous_trial = jsPsych.data.getLastTrialData();
if (!previous_trial.correct){
return true;
}

return false;

}
}

Could you help?

Many thanks!

Josh de Leeuw

unread,
May 17, 2015, 11:41:23 AM5/17/15
to experimenter, jsp...@googlegroups.com
That looks like the right general approach. What behavior are you seeing (i.e. what's broken)?


--
You received this message because you are subscribed to the Google Groups "jsPsych" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jspsych+u...@googlegroups.com.
To post to this group, send email to jsp...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/jspsych/d0629ac3-b4ee-4857-8e8f-d0bf826f2963%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

somewha...@gmail.com

unread,
May 17, 2015, 11:54:51 AM5/17/15
to jsp...@googlegroups.com, somewha...@gmail.com
The experiment won't run at all, probably because I'm not sure how to go from writing an if chunk to actually inserting the trial/block after each experimental trial. To elaborate I'd like after each trial to show feedback conditional on the response, but it's not working so far.

Josh de Leeuw

unread,
May 18, 2015, 4:47:24 PM5/18/15
to Julie Lee, jsp...@googlegroups.com
Here's a sketch of how you could do this:

var categorization_trial = {
  type: 'categorize',
  // other parameters for categorization trial
}

var delay_trial = {
  type: 'single-stim', //using single-stim instead of text so that the delay can be for a fixed period of time
  stimuli: ["<p>Timeout. Please wait.</p>"],
  timing_response: 2000, // 2 second timeout
  choices: 'none', // no keys are allowed to advance
  is_html: true
}

var if_chunk = {
  chunk_type: 'if',
  timeline: [delay_trial],
  conditional_function: function(){
    var data = jsPsych.data.getLastTrialData();
    return !data.correct;
  }
}

var experiment = [categorization_trial, if_chunk]; 

jsPsych.init({
  experiment_structure: experiment
});

That should display a single trial with the timeout trial only appearing if they get the categorization trial wrong. If you want to create multiple categorization trials then you could create a loop:

var number_of_trials = 10;
for(var i=0; i<number_of_trials; i++){
  
 var categorization_trial = {
   type: 'categorize',
   // other parameters for categorization trial
   // use the loop to fill in parameters of the categorization block
 }

 experiment.push(categorization_trial);
 experiment.push(if_chunk);
}

somewha...@gmail.com

unread,
May 19, 2015, 6:44:39 AM5/19/15
to jsp...@googlegroups.com, somewha...@gmail.com
Excellent, thanks so much! It works perfectly.
Message has been deleted
Message has been deleted

somewha...@gmail.com

unread,
Jun 2, 2015, 7:18:32 AM6/2/15
to jsp...@googlegroups.com, Josh de Leeuw
For some reason the incorrect if chunk is no longer displaying after implementing randomisation to my experiment as per the example on the documentation - http://docs.jspsych.org/plugins/jspsych-categorize/

Do you know why this could be?

Many thanks for your help!

Josh de Leeuw

unread,
Jun 2, 2015, 9:15:58 AM6/2/15
to somewha...@gmail.com, jsp...@googlegroups.com
I haven't yet implemented an "if-else" kind of chunk structure, but something like that will eventually be part of the library. One way you can do something like that is to just nest all the chunks under a "linear" chunk:

var feedback_chunk = {
  chunk_type: 'linear',
  timeline: [incorrect_ifchunk, bigreward_ifchunk, smallreward_ifchunk]
}

On Tue, Jun 2, 2015 at 5:59 AM <somewha...@gmail.com> wrote:
This is what the three if chunks look at the moment
    var incorrect_ifchunk = {

      chunk_type: 'if',
      timeline: [delay_trial],
      conditional_function: function(){
        var data = jsPsych.data.getLastTrialData();
        return !data.correct;
      }
    }

    var bigreward_ifchunk = {
      chunk_type: 'if',
      timeline: [bigreward_trial],

      conditional_function: function(){
        var data = jsPsych.data.getLastTrialData();
        if (data.correct && data.key_press == 90 ) {
          return true;
        } else {
          return false;
        }
      }
    }

    var smallreward_ifchunk = {
      chunk_type: 'if',
      timeline: [smallreward_trial],

      conditional_function: function(){
        var data = jsPsych.data.getLastTrialData();
        if (data.correct && data.key_press == 77 ) {
          return true;
        } else {
          return false;
        }
      }
    }

On Tuesday, 2 June 2015 10:54:22 UTC+1, somewha...@gmail.com  wrote:
> I am trying to show different feedback trials depending on user responses, so far I have made three different if chunks to show three different feedback single-stim trials, which works; however, is it possible to make a single 'feedback' if chunk that shows a different single-stim trial dependent on an if statement? Many thanks!

Josh de Leeuw

unread,
Jun 2, 2015, 9:16:57 AM6/2/15
to somewha...@gmail.com, jsp...@googlegroups.com
I think I would need to see more details about what you've done in order to diagnose the issue. Are there any errors in the JavaScript console?

Julie

unread,
Jun 2, 2015, 9:50:41 AM6/2/15
to Josh de Leeuw, jsp...@googlegroups.com
No I can't see any errors! I'll try to send over the code when I have my computer again. It was working fine so I'm not sure what went wrong; it's still correctly categorizes incorrect trials, but doesn't show the if chunk after!
Message has been deleted

somewha...@gmail.com

unread,
Jun 2, 2015, 1:19:19 PM6/2/15
to jsp...@googlegroups.com
Never mind, I fixed the error! I realised that I was pushing each trial into a block, so the timeout trial wasn't showing up until after the end of the block.

somewha...@gmail.com

unread,
Jun 10, 2015, 1:41:47 PM6/10/15
to jsp...@googlegroups.com, somewha...@gmail.com
On a similar note, I'm hoping to have the trial marked as incorrect if the subject doesn't respond within the time set in the timing_stim parameter. Is there a way of tracking the rt within the current trial to achieve this? I tried playing around with the categorize plugin to end the trial if the timeout ran out, but while that worked it introduced strange bugs of duplicated stimuli so I thought I'd ask...

Josh de Leeuw

unread,
Jun 10, 2015, 1:54:10 PM6/10/15
to somewha...@gmail.com, jsp...@googlegroups.com
A maximum duration parameter would be really useful for the categorize plugin. I can add that to the list of things to implement in the future. It sounds like you were close to getting it, but the issues with the duplicated stimuli were a problem. That kind of issue is likely the result of not shutting off all of the event handlers when ending the trial. Take a look at the bit of code starting around L80: https://github.com/jodeleeuw/jsPsych/blob/master/plugins/jspsych-categorize.js#L80. If you make sure that the loop runs to clear all the timeout handlers, then that will probably fix the duplicate stimuli bug.

Josh de Leeuw

unread,
Jun 10, 2015, 1:55:50 PM6/10/15
to somewha...@gmail.com, jsp...@googlegroups.com
You'll also need to cancel the keyboard listener if you abort the trial early. You can use jsPsych.pluginAPI.cancelAllKeyboardResponses() to do that (http://docs.jspsych.org/core_library/jspsych-pluginAPI/#jspsychpluginapicancelallkeyboardresponses)

Julie Lee

unread,
Jun 10, 2015, 1:58:21 PM6/10/15
to Josh de Leeuw, jsp...@googlegroups.com
Seems to do the trick! Thanks so much. 

Julie Lee

unread,
Jun 11, 2015, 8:37:48 AM6/11/15
to Josh de Leeuw, jsp...@googlegroups.com
I’m trying to append a ‘no response’ alert but since I endTrial, it doesn’t show up before the trial ends. How would I make this work? Here’s what it looks like in the plugin so far:

if (trial.timing_stim > 0) {
setTimeoutHandlers.push(setTimeout(function() {
display_element.append(trial.noresp_text);
$('#jspsych-categorize-stimulus').css('visibility', 'hidden');
var correct = false;
clearTimeout(setTimeoutHandlers[i]);
jsPsych.pluginAPI.cancelAllKeyboardResponses();
endTrial();
}, trial.timing_stim));
}

Many thanks!

Josh de Leeuw

unread,
Jun 11, 2015, 8:42:41 AM6/11/15
to Julie Lee, jsp...@googlegroups.com
You would need to add some kind of delay in order to give it time to actually show the message. Right now the message is being added, but then the trial ends right away so it doesn't have time to display. You could add another setTimeout, with a parameter to control how long to display the message for. You'll probably want to do this after you clear the other timeout handlers and clear the keyboard response. That way you are sure that nothing else can happen during the time that the message is displaying. Something like:

f (trial.timing_stim > 0) {
setTimeoutHandlers.push(setTimeout(function() {
display_element.append(trial.noresp_text);
$('#jspsych-categorize-stimulus').css('visibility', 'hidden');
var correct = false;
clearTimeout(setTimeoutHandlers[i]);
jsPsych.pluginAPI.cancelAllKeyboardResponses();
                setTimeout(function(){
endTrial();
                }, 500); // adjust this parameter as needed, or make it a plugin parameter
}, trial.timing_stim));
}

Julie Lee

unread,
Jun 12, 2015, 10:50:06 AM6/12/15
to Josh de Leeuw, jsp...@googlegroups.com
Hi Josh,

That fixed it but now I’m finding another error, namely if the previous trial was correct, the timeout does not show a timeout single stim trial afterwards. However, it does if the previous trial was incorrect.

To explain, it’s usually [trial1] [timeout if necessary] [trial2] [timeout] etc. but if [trial1] is correctly responded to, a no-response [timeout] after [trial2] doesn’t occur, it just skips to [trial3] and so on. 

I laid out a timeout like so:
    var timeout_ifchunk = {
      chunk_type: 'if',
      timeline: [delay_trial],
      conditional_function: function(){
        var data = jsPsych.data.getLastTrialData();
        return !data.correct || data.timeout;
      }
    }

and in the plugin added an extra data variable of timeout:
if (trial.timing_stim > 0) {
setTimeoutHandlers.push(setTimeout(function() {
timeout = true;
display_element.append(trial.noresp_text);
$('#jspsych-categorize-stimulus').css('visibility', 'hidden');
clearTimeout(setTimeoutHandlers[i]);
jsPsych.pluginAPI.cancelAllKeyboardResponses();
                setTimeout(function(){
     endTrial();
                }, 500); // adjust this parameter as needed, or make it a plugin parameter
}, trial.timing_stim));
}

I thought it was because a previously-correct trial would cause a no-response trial to not meet the conditions of the if chunk, but even removing !data.correct in the if chunk doesn’t fix it. I also changed the if-statement later to:

if (trial.key_answer == info.key && !timeout) {
correct = true;
}

So, I’m not sure where the problem could lie. Do you have any ideas?

Many thanks!

Josh de Leeuw

unread,
Jun 12, 2015, 10:57:39 AM6/12/15
to Julie Lee, jsp...@googlegroups.com
Is jsPsych.data.write() called on trials when there is a timeout? (It sounds like the answer is yes, but I just want to make sure). If it's not, then jsPsych.data.getLastTrialData() would get the data from the last trial where a response was given. The method isn't smart enough to return null data from a trial that didn't write any data. It just grabs the last set of data that was recorded.

Julie Lee

unread,
Jun 12, 2015, 11:01:49 AM6/12/15
to Josh de Leeuw, jsp...@googlegroups.com
Ah, it wasn’t! Silly mistake. Makes sense now, thanks so much!
Reply all
Reply to author
Forward
0 new messages