psychopy.org | Reference | Downloads | Github

Stim dur calculated by median is noisy

URL of experiment: https://gitlab.pavlovia.org/pinartoptas/timingpriors_avg

Description of the problem: I changed how I determine the duration of the next stimulus from calculating the average of the previous trials to taking the median of the previous trials by using the code below.

Here I store the time between 2 presses into a variable called reproduction1, and then save reproduction to a 6-element array called repro1_array later to be sorted.

var repro1_array = new Array (6);
var reproduction1;
var i = 0;
function iteration1RoutineEachFrame(trials) {
  return function () {
    //------Loop for each frame of Routine 'iteration1'-------
    let continueRoutine = true; // until we're told otherwise
    // get current time
    t = iteration1Clock.getTime();
    frameN = frameN + 1;// number of completed frames (so 0 is the first frame)
    // update/draw components on each frame
    if ((_key_resp_allKeys.length === 2)) {
        key_resp.keys = _key_resp_allKeys.slice((- 1))[0].name;
        reproduction1 = (_key_resp_allKeys.slice((- 1))[0].rt - _key_resp_allKeys.slice((- 2))[0].rt);
        repro1_array[i] = reproduction1;
        i = i+1;
        continueRoutine = false;
    }

Here I calculate median and determine the stimulus duration of the next iteration by defining seed2 as the median.

    const arr1Sort = repro1_array.sort((a,b)=>a -b);
    const len = repro1_array.length;
    const mid = Math.ceil(len/2);
    const median1 = 
        len % 2 == 0 ? (arr1Sort[mid] + arr1Sort[mid -1])/2 : arr1Sort[mid -1];
    stimulus1t = (polygon.tStop - polygon.tStart);
    stimulus1f = (polygon.frameNStop*frameDur - polygon.frameNStart*frameDur);
    ite1_loop.addData("stimulus1t", stimulus1t);
    ite1_loop.addData("stimulus1f", stimulus1f);
    ite1_loop.addData("reproduction1", reproduction1);
    ite1_loop.addData("sum_ite1", sum_ite1);
    
    if ((ite1_count === trialNum)) {
        seed2 = (median1); // used when I want median
        // seed2 = (sum_ite1 / ite1_count); // used when I want average
        ite1_count = 0;
        sum_ite1 = 0;
    }

However, I noticed a seemingly systematic error while doing that. When the code calculates the median, there is a significant increase in the difference between the actual stimulus duration presented on the screen (which should be the median) and what I want to present (which is again, the median). More specifically, when the calculated median is below < 500 ms, the stimulus duration that is calculated by frameN*frameDur is much higher (~1000 ms higher). And this definitely does not happen when I’m calculating the average as the next stim dur.

I couldn’t figure out where in the code this problem lies exactly. So here I am sharing the problem briefly.

I would really really appreciate any help.

Thanks in advance!

Hi all, I am waiting for a reply on the issue above. :frowning: I’m pretty much stuck with my experiment at the moment cause I really cannot see where the problem is, and as I collect more data I see that this noisy calculation is the case with almost every participant.

I’d really appreciate any help.

I haven’t commented on this one before because I’m not yet sure I understand the problem and you are presenting JS code which looks like it might have been written in JS rather than using the PsychoPy Builder translation tool.

I was wondering whether the issu was that your code took too long to run for short intervals.

Thanks for your answer @wakecarter
I did write in in JS rather than using Psychopy cause the translation to JS is pretty messy in the features that I’m using. (e.g. conditional stimulus duration in Psychopy does not translate len() to .length)

Anyways, I solved it. The array I defined as an empty variable at the beginning of a routine needed to be cleared each time at the end. That’s what made my median calcultation wrong.