Repeating Image Stimulus within same routine

I’m trying to get an image to appear every time a condition is met. I’ve tried multiple approaches but I cannot get the stimulus to reappear.

I’m trying to get a thumbs up image to appear for 2 seconds whenever the individual has been “on task” for more than 40% of the current interval time. The if then statement is working fine; I’m just having problems with getting the image to appear each time.

I also have a video running during the routine, so I do not think solutions like


will work because it requires an end routine to have the stimulus reappear.

I’ve been trying to set the image to change size whenever the if-statement is met per another topic’s solution, but that hasn’t been successful so far. I’ve also tried setting the size to update each frame, but since I have a 2 second duration check, I think the check may get ignored if the size I set is being reset to the 0 size using the Builder.

That code snippet is:

//Current interval is based on how long each fixed interval reinforcement period is. This will be determined from baseline data. 
        window.currentInterval = Math.ceil(window.intervalTimer.getTime() / (intervalDur)); 
     
        if (window.ontask + window.offtask >= intervalDur*2 && (window.ontask / (window.ontask + window.offtask)) > baserate) //Reset offtask and ontask every time currentInterval goes up
          { 
           console.log('Good job! Over 40% ontask!' + (window.ontask / (window.ontask + window.offtask))*100 + '%')
            window.flipTime = Date.now();
            window.ThumbsUp.setSize([0.3, 0.3]);
            window.ontask = 0; 
            window.offtask = 0;  
           }
            else
                {
                if (window.ontask + window.offtask >= intervalDur*2)
                  {
                   console.log('less than 40% ontask')
                   window.ontask = 0; 
                   window.offtask = 0;  
                  }
                 }
        
        if (window.flipTime < Date.now() - 2000)
            {
            window.ThumbsUp.setSize([0.0, 0.0]);
            }

For completeness, the rest of the relevant coding is as follows:

var tracking_trialComponents;
function tracking_trialRoutineBegin(snapshot) {
  return function () {
    //------Prepare to start Routine 'tracking_trial'-------
    t = 0;
    tracking_trialClock.reset(); // clock
    frameN = -1;
    // update component parameters for each repeat
        window.intervalTimer = new util.Clock();
        window.flipTime = 0;
        //start with no ontask or offtask
        window.ontask = 0;
        window.offtask = 0;
        window.ThumbsUp = new visual.ImageStim({
            win : psychoJS.window,
            name : 'image', units : 'norm', 
            image : 'images/Thumbs_up.png', mask : undefined,
            ori : 0, pos : [-0.8, 0.8], size : [0, 0],         //initialize at 0 size
            color : new util.Color([1, 1, 1]), opacity : 1,
            flipHoriz : false, flipVert : false,
            texRes : 128, interpolate : true, depth : -3.0}); 
        
        setInterval(function()
//      Function being evaluated continuously every 500ms
//
//
  
    // keep track of which components have finished
    tracking_trialComponents = [];
    tracking_trialComponents.push(movie);
    tracking_trialComponents.push(tracking_square);
    tracking_trialComponents.push(ThumbsUp);
    
    for (const thisComponent of tracking_trialComponents)
      if ('status' in thisComponent)
        thisComponent.status = PsychoJS.Status.NOT_STARTED;
    // check if the Routine should terminate
    if (!continueRoutine) {  // a component has requested a forced-end of Routine
      return Scheduler.Event.NEXT;
    }
  };
}
var frameRemains;
function tracking_trialRoutineEachFrame(snapshot) {
  return function () {
    //------Loop for each frame of Routine 'tracking_trial'-------
    let continueRoutine = true; // until we're told otherwise
    // get current time
    t = tracking_trialClock.getTime();
    frameN = frameN + 1;// number of completed frames (so 0 is the first frame)
    // update/draw components on each frame
    
    // *movie* updates
    if (t >= 0.0 && movie.status === PsychoJS.Status.NOT_STARTED) {
      // keep track of start time/frame for later
      movie.tStart = t;  // (not accounting for frame time here)
      movie.frameNStart = frameN;  // exact frame index      
      movie.setAutoDraw(true);
      movie.play();
    }
   
    // *tracking_square* updates
    if (t >= 0.0 && tracking_square.status === PsychoJS.Status.NOT_STARTED) {
      // keep track of start time/frame for later
      tracking_square.tStart = t;  // (not accounting for frame time here)
      tracking_square.frameNStart = frameN;  // exact frame index
      
      tracking_square.setAutoDraw(true);
    }

    const intervalDur = 20; //in seconds, how long before boolean check for reinforcement
    const baserate = .4; //% of time ontask during baseline
        
//Current interval is based on how long each fixed interval reinforcement period is. This will be determined from baseline data. 
        window.currentInterval = Math.ceil(window.intervalTimer.getTime() / (intervalDur)); 
     
        if (window.ontask + window.offtask >= intervalDur*2 && (window.ontask / (window.ontask + window.offtask)) > baserate) //Reset offtask and ontask every time currentInterval goes up
          { 
           console.log('Good job! Over 40% ontask!' + (window.ontask / (window.ontask + window.offtask))*100 + '%')
            window.flipTime = Date.now();
            window.ThumbsUp.setSize([0.3, 0.3]);
            window.ontask = 0; 
            window.offtask = 0;  
           }
            else
                {
                if (window.ontask + window.offtask >= intervalDur*2)
                  {
                   console.log('less than 40% ontask')
                   window.ontask = 0; 
                   window.offtask = 0;  
                  }
                 }
        
        if (window.flipTime < Date.now() - 2000)
            {
            window.ThumbsUp.setSize([0.0, 0.0]);
            }
// 
//
//Deleted lots of code here for brevity
//
//
        
    // *ThumbsUp* updates
    if (t >= 0.0 && ThumbsUp.status === PsychoJS.Status.NOT_STARTED) {
      // keep track of start time/frame for later
      ThumbsUp.tStart = t;  // (not accounting for frame time here)
      ThumbsUp.frameNStart = frameN;  // exact frame index  
      ThumbsUp.setAutoDraw(true);
    }
frameRemains = 0.0 + 100000 - psychoJS.window.monitorFramePeriod * 0.75;  // most of one frame period left
   if ((ThumbsUp.status === PsychoJS.Status.STARTED || ThumbsUp.status === PsychoJS.Status.FINISHED) && t >= frameRemains) {
      ThumbsUp.setAutoDraw(false);
    }
    
    if (ThumbsUp.status === PsychoJS.Status.STARTED){ // only update if being drawn
      ThumbsUp.setSize();
    }
    // check for quit (typically the Esc key)
if (psychoJS.experiment.experimentEnded || psychoJS.eventManager.getKeys({keyList:['escape']}).length > 0) {
      return quitPsychoJS('The [Escape] key was pressed. Goodbye!', false);
    }
    
    // check if the Routine should terminate
    if (!continueRoutine) {  // a component has requested a forced-end of Routine
      return Scheduler.Event.NEXT;
    }
continueRoutine = false;  // reverts to True if at least one component still running
    for (const thisComponent of tracking_trialComponents)
      if ('status' in thisComponent && thisComponent.status !== PsychoJS.Status.FINISHED) {
        continueRoutine = true;
        break;
      }  
    // refresh the screen if continuing
    if (continueRoutine) {
      return Scheduler.Event.FLIP_REPEAT;
    } else {
      return Scheduler.Event.NEXT;
    }
  };
}

function tracking_trialRoutineEnd(snapshot) {
  return function () {
    //------Ending Routine 'tracking_trial'-------
    for (const thisComponent of tracking_trialComponents) {
      if (typeof thisComponent.setAutoDraw === 'function') {
        thisComponent.setAutoDraw(false);
      }
    }
    movie.stop();
    // the Routine "tracking_trial" was not non-slip safe, so reset the non-slip timer
    routineTimer.reset();
    
    return Scheduler.Event.NEXT;
  };
}

function endLoopIteration(scheduler, snapshot) {
  // ------Prepare for next entry------
  return function () {
    if (typeof snapshot !== 'undefined') {
      // ------Check if user ended loop early------
      if (snapshot.finished) {
        // Check for and save orphaned data
        if (psychoJS.experiment.isEntryEmpty()) {
          psychoJS.experiment.nextEntry(snapshot);
        }
        scheduler.stop();
      } else {
        const thisTrial = snapshot.getCurrentTrial();
        if (typeof thisTrial === 'undefined' || !('isTrials' in thisTrial) || thisTrial.isTrials) {
          psychoJS.experiment.nextEntry(snapshot);
        }
      }
    return Scheduler.Event.NEXT;
    }
  };
}
function importConditions(currentLoop) {
  return function () {
    psychoJS.importAttributes(currentLoop.getCurrentTrial());
    return Scheduler.Event.NEXT;
    };
}
function quitPsychoJS(message, isCompleted) {
  // Check for and save orphaned data
  if (psychoJS.experiment.isEntryEmpty()) {
    psychoJS.experiment.nextEntry();
  }
  psychoJS.window.close();
  psychoJS.quit({message: message, isCompleted: isCompleted});
  
  return Scheduler.Event.QUIT;

Anyone have any ideas how to get the image to appear multiple times for my purposes?

Thanks!

Experiment | ayjayar/demo_eye_tracker2 (pavlovia.org)

I ended up getting it to work by adding a variable in opacity which refreshed every frame and having that variable change based on the output of each loop.

    window.currentInterval = Math.ceil(window.intervalTimer.getTime() / (intervalDur)); 
    
    if (window.ontask + window.offtask >= intervalDur*2 && (window.ontask / (window.ontask + window.offtask)) > baserate) //Reset offtask and ontask every time currentInterval goes up
      { 
       console.log('Good job! Over 40% ontask!' + (window.ontask / (window.ontask + window.offtask))*100 + '%')
        window.flipTime = Date.now();
        window.currOpac = 1;   //Set image to opaque
        window.ontask = 0; 
        window.offtask = 0;  
       }
        else
            {
            if (window.ontask + window.offtask >= intervalDur*2)
              {
               console.log('less than 40% ontask')
               window.ontask = 0; 
               window.offtask = 0;  
              }
             }
    
    if (window.flipTime < Date.now() - 2000)
        {
        window.currOpac = 0;  //After 2 seconds, set image to transparent
        }