Page unresponsive - pavlovia

jsPsych version: 2021.2.3

url: Pavlovia

hi,

I am trying to build an experiment where participants reproduce a target duration by two space button presses (the interval between the two button presses is what the reproduction stands for in this design). at first, participants are asked to reproduce the target for 90 times. in the further blocks, I will present these reproductions by randomly choosing 30 of them according to some predetermined criteria. in one block, I want to choose 30 of these 90 reproductions that make (e.g.,) distribution with coefficient of variation (i.e., std / mean reproduction) that is 10% above the original (i.e., the distribution with all the 90 reproductions) distribution or 10% below the original or somewhere in between 101% - 99%. In some of the blocks, I create my own random distributions with the same parameters. I am using the loops below for the depicted scenario:

function shuffle(a) {
        var j, x, i;
        for (i = a.length - 1; i > 0; i--) {
          j = Math.floor(Math.random() * (i + 1));
          x = a[i];
          a[i] = a[j];
          a[j] = x;
      }
      return a;
    }
  
function generateGaussian(mean,std, n){
      var a = [];
    for  (let i = 0; i < n; i++) {
      var _2PI = Math.PI * 2;
      var u1 = Math.random();
      var u2 = Math.random();
       var z0 = Math.sqrt(-2.0 * Math.log(u1)) * Math.cos(_2PI * u2);
       var z1 = Math.sqrt(-2.0 * Math.log(u1)) * Math.sin(_2PI * u2);
    
      a.push(z0 * std + mean);
    } 
    return a;
    }


function getRandomSubarray(arr, size) {
    var shuffled = arr.slice(0), i = arr.length, temp, index;
    while (i--) {
        index = Math.floor((i + 1) * Math.random());
        temp = shuffled[index];
        shuffled[index] = shuffled[i];
        shuffled[i] = temp;
    }
    return shuffled.slice(0, size);
}
console.log(all_repro);
shuffle(all_repro);
psychoJS.experiment.addData("all_repro_shuffled", all_repro);
mean_repro = all_repro.reduce((a, b) => a + b) / all_repro.length;
console.log(mean_repro)
stdev_repro = Math.sqrt(all_repro.reduce((s,n) => s + (n - mean_repro) ** 2, 0) / (all_repro.length - 1));
console.log(stdev_repro)
cv_original = (stdev_repro / mean_repro);
console.log(cv_original);
self_rep_high = [];
self_rep_medium = [];
self_rep_low = [];
cv_upper = (cv_original * 1.1);
console.log(cv_upper)
cv_lower = (cv_original * 0.9);
console.log(cv_lower)
cv_upper_same = (cv_original * 1.001);
console.log(cv_upper_same)
cv_lower_same = (cv_original * 0.999);
console.log(cv_lower_same)
psychoJS.experiment.addData("cv_upper", cv_upper);
psychoJS.experiment.addData("cv_lower", cv_lower);
psychoJS.experiment.addData("cv_upper_same", cv_upper_same);
psychoJS.experiment.addData("cv_lower_same", cv_lower_same);
var p;
p = getRandomSubarray(all_repro, 30);
console.log(p)
var t;
var mean_t;
var std_t;
var check_val;
var mean_p;
var std_p;
mean_p = p.reduce((a, b) => a + b) / p.length;
console.log(mean_p)
std_p = Math.sqrt(p.reduce((s,n) => s + (n - mean_p) ** 2, 0) / (p.length - 1));
console.log(std_p)
selfhigh_cv = (std_p / mean_p);
console.log(selfhigh_cv)
while ((selfhigh_cv < cv_upper)) {
    p = getRandomSubarray(all_repro, 30);
    console.log(p)
    mean_p = p.reduce((a, b) => a + b) / p.length;
    console.log(mean_p)
    std_p = Math.sqrt(p.reduce((s,n) => s + (n - mean_p) ** 2, 0) / (p.length - 1));
    console.log(std_p)
    selfhigh_cv = (std_p / mean_p);
    console.log(selfhigh_cv)   //// never ends
}
self_rep_high = p;
console.log(self_rep_high)
psychoJS.experiment.addData("self_rep_high", self_rep_high);
psychoJS.experiment.addData("selfhigh_cv", selfhigh_cv);

p = getRandomSubarray(all_repro, 30);
console.log(p)
mean_p = p.reduce((a, b) => a + b) / p.length;
console.log(mean_p)
std_p = Math.sqrt(p.reduce((s,n) => s + (n - mean_p) ** 2, 0) / (p.length - 1));
console.log(std_p)
selflow_cv = (std_p / mean_p);
console.log(selflow_cv)
while ((selflow_cv > cv_lower)) {
    p = getRandomSubarray(all_repro, 30);
    console.log(p)
    mean_p = p.reduce((a, b) => a + b) / p.length;
    console.log(mean_p)
    std_p = Math.sqrt(p.reduce((s,n) => s + (n - mean_p) ** 2, 0) / (p.length - 1));
    console.log(std_p)
    selflow_cv = (std_p / mean_p);
    console.log(selflow_cv)
}
self_rep_low = p;
console.log(self_rep_low);
psychoJS.experiment.addData("self_rep_low", self_rep_low);
psychoJS.experiment.addData("selflow_cv", selflow_cv);

p = getRandomSubarray(all_repro, 30);
console.log(p)
mean_p = p.reduce((a, b) => a + b) / p.length;
console.log(mean_p)
std_p = Math.sqrt(p.reduce((s,n) => s + (n - mean_p) ** 2, 0) / (p.length - 1));
console.log(std_p)
selfsame_cv = (std_p / mean_p);
console.log(selfsame_cv)
while ((! ((selfsame_cv > cv_lower_same) && (selfsame_cv < cv_upper_same)))) { //burada hata
    p = getRandomSubarray(all_repro, 30);
    console.log(p)
    mean_p = p.reduce((a, b) => a + b) / p.length;
    console.log(mean_p)
    std_p = Math.sqrt(p.reduce((s,n) => s + (n - mean_p) ** 2, 0) / (p.length - 1));
    console.log(std_p)
    selfsame_cv = (std_p / mean_p);  
}
self_rep_medium = p;
console.log(self_rep_medium)
psychoJS.experiment.addData("self_rep_medium", self_rep_medium);
psychoJS.experiment.addData("selfsame_cv", selfsame_cv);


obs_rep = [];
other_rep_high = [];
other_rep_medium = [];
other_rep_low = [];
for (var i, _pj_c = 0, _pj_a = util.range(0, 90), _pj_b = _pj_a.length; (_pj_c < _pj_b); _pj_c += 1) {
    i = _pj_a[_pj_c];
    check_val = generateGaussian(mean_repro, stdev_repro,1);
    console.log(check_val)
    while ((check_val < 0)) {
        check_val = generateGaussian(mean_repro, stdev_repro,1);
        console.log(check_val)
    }
    obs_rep.push(check_val);
    console.log(obs_rep)
}

psychoJS.experiment.addData("obs_rep", obs_rep);
mean_repro_obs = obs_rep.reduce((a, b) => a + b) / obs_rep.length
console.log(mean_repro_obs)
stdev_repro_obs = Math.sqrt(obs_rep.reduce((s,n) => s + (n - mean_repro_obs) ** 2, 0) / (obs_rep.length - 1));
console.log(stdev_repro_obs)
psychoJS.experiment.addData('mean_repro_obs',mean_repro_obs);
psychoJS.experiment.addData('stdev_repro_obs',stdev_repro_obs);


p = getRandomSubarray(all_repro, 30);
console.log(p)
mean_p = p.reduce((a, b) => a + b) / p.length;
console.log(mean_p)
std_p = Math.sqrt(p.reduce((s,n) => s + (n - mean_p) ** 2, 0) / (p.length - 1));
console.log(std_p)
otherhigh_cv = (std_p / mean_p);
console.log(otherhigh_cv)

while ((selfhigh_cv < cv_upper)) {
    p = getRandomSubarray(obs_rep, 30);
    console.log(p)
    mean_p = p.reduce((a, b) => a + b) / p.length;
    console.log(mean_p)
    std_p = Math.sqrt(p.reduce((s,n) => s + (n - mean_p) ** 2, 0) / (p.length - 1));
    console.log(std_p)
    otherhigh_cv = (std_p / mean_p);   
    console.log(otherhigh_cv)
}
other_rep_high = p;
console.log(other_rep_high)
psychoJS.experiment.addData("other_rep_high", other_rep_high);
psychoJS.experiment.addData("otherhigh_cv", otherhigh_cv);

p = getRandomSubarray(all_repro, 30);
console.log(p)
mean_p = p.reduce((a, b) => a + b) / p.length;
console.log(mean_p)
std_p = Math.sqrt(p.reduce((s,n) => s + (n - mean_p) ** 2, 0) / (p.length - 1));
console.log(std_p)
otherlow_cv = (std_p / mean_p);
console.log(otherlow_cv)
while ((selflow_cv > cv_lower)) {
    p = getRandomSubarray(obs_rep, 30);
    console.log(p)
    mean_p = p.reduce((a, b) => a + b) / p.length;
    console.log(mean_p)
    std_p = Math.sqrt(p.reduce((s,n) => s + (n - mean_p) ** 2, 0) / (p.length - 1));
    console.log(std_p)
    otherlow_cv = (std_p / mean_p);
    console.log(otherlow_cv)
}
other_rep_low = p;
console.log(other_rep_low)
psychoJS.experiment.addData("other_rep_low", other_rep_low);
psychoJS.experiment.addData("otherlow_cv", otherlow_cv);


p = getRandomSubarray(all_repro, 30);
console.log(p)
mean_p = p.reduce((a, b) => a + b) / p.length;
console.log(mean_p)
std_p = Math.sqrt(p.reduce((s,n) => s + (n - mean_p) ** 2, 0) / (p.length - 1));
console.log(std_p)
othersame_cv = (std_p / mean_p);
while ((! ((othersame_cv > cv_lower_same) && (othersame_cv < cv_upper_same)))) {
    p = getRandomSubarray(obs_rep, 30);
    console.log(p)
    mean_p = p.reduce((a, b) => a + b) / p.length;
    console.log(mean_p)
    std_p = Math.sqrt(p.reduce((s,n) => s + (n - mean_p) ** 2, 0) / (p.length - 1));
    console.log(std_p)
    othersame_cv = (std_p / mean_p);
    console.log(othersame_cv)
}
other_rep_medium = p;
console.log(other_rep_medium)
psychoJS.experiment.addData("other_rep_medium", other_rep_medium);
psychoJS.experiment.addData("othersame_cv", othersame_cv);

I am nearly sure that the values that are being checked in the while loop are changing. I’ve also checked from the console to make sure. But after a while, the code gives Page Unresponsive warning and thus, the experiment does not continue as it should do.

I have made my experiment open to public view, any idea for the solution?

thanks so much for the effort in advance, t

How does selflow_cv and/or cv_lower change within this while loop?

A similar question for the other loops?

hi @wakecarter,

thank you so much for your reply. cv_lower should not change, but selflow_cv should. I am calculating the value outside the while loop first, then updating it until it satisfies the condition by picking up a new set of 30 from all_repro (the original vector of values), where; p = getRandomSubarray(all_repro, 30);. same should apply to all loops.

My understanding of how while looks work is that you repeat the instructions within the loop until the condition is false.

Therefore a loop like

while ((selflow_cv > cv_lower)) {
    p = getRandomSubarray(all_repro, 30);
    console.log(p)
    mean_p = p.reduce((a, b) => a + b) / p.length;
    console.log(mean_p)
    std_p = Math.sqrt(p.reduce((s,n) => s + (n - mean_p) ** 2, 0) / (p.length - 1));
    console.log(std_p)
    selflow_cv = (std_p / mean_p);
    console.log(selflow_cv)
}

should be fine because selflow_cv is in the condition and changes in the loop. However, this doesn’t appear to be true in all cases.

yeah doublechecked all the loops, seeing nothing wrong, the loops should be ending. what am I missing?

I’m still stuck… :confused: any ideas?

In most cases you have "while (x > y) and the last statement is x = ".

In at least two cases that I’ve spotted this format is broken and you have “while (x > y) and z =”

I can’t help you any further because I feel that there is a bug in the code I quoted in my first reply “(selflow_cv > cv_lower) otherlow_cv =” which you think is fine.

ah you are right, sorry for overlooking it, now I updated the code as;


`mean_p = p.reduce((a, b) => a + b) / p.length;
console.log(mean_p)
std_p = Math.sqrt(p.reduce((s,n) => s + (n - mean_p) ** 2, 0) / (p.length - 1));
console.log(std_p)
selfhigh_cv = (std_p / mean_p);
console.log(selfhigh_cv)
while ((selfhigh_cv < cv_upper)) {
    p = getRandomSubarray(all_repro, 30);
    console.log(p)
    mean_p = p.reduce((a, b) => a + b) / p.length;
    console.log(mean_p)
    std_p = Math.sqrt(p.reduce((s,n) => s + (n - mean_p) ** 2, 0) / (p.length - 1));
    console.log(std_p)
    selfhigh_cv = (std_p / mean_p);
    console.log(selfhigh_cv)   //// never ends
}
self_rep_high = p;
console.log(self_rep_high)
psychoJS.experiment.addData("self_rep_high", self_rep_high);
psychoJS.experiment.addData("selfhigh_cv", selfhigh_cv);

p = getRandomSubarray(all_repro, 30);
console.log(p)
mean_p = p.reduce((a, b) => a + b) / p.length;
console.log(mean_p)
std_p = Math.sqrt(p.reduce((s,n) => s + (n - mean_p) ** 2, 0) / (p.length - 1));
console.log(std_p)
selflow_cv = (std_p / mean_p);
console.log(selflow_cv)
while ((selflow_cv > cv_lower)) {
    p = getRandomSubarray(all_repro, 30);
    console.log(p)
    mean_p = p.reduce((a, b) => a + b) / p.length;
    console.log(mean_p)
    std_p = Math.sqrt(p.reduce((s,n) => s + (n - mean_p) ** 2, 0) / (p.length - 1));
    console.log(std_p)
    selflow_cv = (std_p / mean_p);
    console.log(selflow_cv)
}
self_rep_low = p;
console.log(self_rep_low);
psychoJS.experiment.addData("self_rep_low", self_rep_low);
psychoJS.experiment.addData("selflow_cv", selflow_cv);

p = getRandomSubarray(all_repro, 30);
console.log(p)
mean_p = p.reduce((a, b) => a + b) / p.length;
console.log(mean_p)
std_p = Math.sqrt(p.reduce((s,n) => s + (n - mean_p) ** 2, 0) / (p.length - 1));
console.log(std_p)
selfsame_cv = (std_p / mean_p);
console.log(selfsame_cv)
while ((! ((selfsame_cv > cv_lower_same) && (selfsame_cv < cv_upper_same)))) { //burada hata
    p = getRandomSubarray(all_repro, 30);
    console.log(p)
    mean_p = p.reduce((a, b) => a + b) / p.length;
    console.log(mean_p)
    std_p = Math.sqrt(p.reduce((s,n) => s + (n - mean_p) ** 2, 0) / (p.length - 1));
    console.log(std_p)
    selfsame_cv = (std_p / mean_p);  
}
self_rep_medium = p;
console.log(self_rep_medium)
psychoJS.experiment.addData("self_rep_medium", self_rep_medium);
psychoJS.experiment.addData("selfsame_cv", selfsame_cv);


obs_rep = [];
other_rep_high = [];
other_rep_medium = [];
other_rep_low = [];
for (var i, _pj_c = 0, _pj_a = util.range(0, 90), _pj_b = _pj_a.length; (_pj_c < _pj_b); _pj_c += 1) {
    i = _pj_a[_pj_c];
    check_val = generateGaussian(mean_repro, stdev_repro,1);
    console.log(check_val)
    while ((check_val < 0)) {
        check_val = generateGaussian(mean_repro, stdev_repro,1);
        console.log(check_val)
    }
    obs_rep.push(check_val);
    console.log(obs_rep)
}

psychoJS.experiment.addData("obs_rep", obs_rep);
mean_repro_obs = obs_rep.reduce((a, b) => a + b) / obs_rep.length
console.log(mean_repro_obs)
stdev_repro_obs = Math.sqrt(obs_rep.reduce((s,n) => s + (n - mean_repro_obs) ** 2, 0) / (obs_rep.length - 1));
console.log(stdev_repro_obs)
psychoJS.experiment.addData('mean_repro_obs',mean_repro_obs);
psychoJS.experiment.addData('stdev_repro_obs',stdev_repro_obs);


p = getRandomSubarray(all_repro, 30);
console.log(p)
mean_p = p.reduce((a, b) => a + b) / p.length;
console.log(mean_p)
std_p = Math.sqrt(p.reduce((s,n) => s + (n - mean_p) ** 2, 0) / (p.length - 1));
console.log(std_p)
otherhigh_cv = (std_p / mean_p);
console.log(otherhigh_cv)

while ((otherhigh_cv < cv_upper)) {
    p = getRandomSubarray(obs_rep, 30);
    console.log(p)
    mean_p = p.reduce((a, b) => a + b) / p.length;
    console.log(mean_p)
    std_p = Math.sqrt(p.reduce((s,n) => s + (n - mean_p) ** 2, 0) / (p.length - 1));
    console.log(std_p)
    otherhigh_cv = (std_p / mean_p);   
    console.log(otherhigh_cv)
}
other_rep_high = p;
console.log(other_rep_high)
psychoJS.experiment.addData("other_rep_high", other_rep_high);
psychoJS.experiment.addData("otherhigh_cv", otherhigh_cv);

p = getRandomSubarray(all_repro, 30);
console.log(p)
mean_p = p.reduce((a, b) => a + b) / p.length;
console.log(mean_p)
std_p = Math.sqrt(p.reduce((s,n) => s + (n - mean_p) ** 2, 0) / (p.length - 1));
console.log(std_p)
otherlow_cv = (std_p / mean_p);
console.log(otherlow_cv)
while ((otherlow_cv > cv_lower)) {
    p = getRandomSubarray(obs_rep, 30);
    console.log(p)
    mean_p = p.reduce((a, b) => a + b) / p.length;
    console.log(mean_p)
    std_p = Math.sqrt(p.reduce((s,n) => s + (n - mean_p) ** 2, 0) / (p.length - 1));
    console.log(std_p)
    otherlow_cv = (std_p / mean_p);
    console.log(otherlow_cv)
}
other_rep_low = p;
console.log(other_rep_low)
psychoJS.experiment.addData("other_rep_low", other_rep_low);
psychoJS.experiment.addData("otherlow_cv", otherlow_cv);


p = getRandomSubarray(all_repro, 30);
console.log(p)
mean_p = p.reduce((a, b) => a + b) / p.length;
console.log(mean_p)
std_p = Math.sqrt(p.reduce((s,n) => s + (n - mean_p) ** 2, 0) / (p.length - 1));
console.log(std_p)
othersame_cv = (std_p / mean_p);
while ((! ((othersame_cv > cv_lower_same) && (othersame_cv < cv_upper_same)))) {
    p = getRandomSubarray(obs_rep, 30);
    console.log(p)
    mean_p = p.reduce((a, b) => a + b) / p.length;
    console.log(mean_p)
    std_p = Math.sqrt(p.reduce((s,n) => s + (n - mean_p) ** 2, 0) / (p.length - 1));
    console.log(std_p)
    othersame_cv = (std_p / mean_p);
    console.log(othersame_cv)
}
other_rep_medium = p;
console.log(other_rep_medium)
psychoJS.experiment.addData("other_rep_medium", other_rep_medium);
psychoJS.experiment.addData("othersame_cv", othersame_cv);


`

doublechecked if I had anything else that needs to be changed, noticed none so far. yet the problem persists :confused:

Do your console logs tell you at what point it hangs?

the code is stuck in this part, it seems:

while ((! ((othersame_cv > cv_lower_same) && (othersame_cv < cv_upper_same)))) {
        p = getRandomSubarray(obs_rep, 30);
        console.log(p)
        mean_p = p.reduce((a, b) => a + b) / p.length;
        console.log(mean_p)
        std_p = Math.sqrt(p.reduce((s,n) => s + (n - mean_p) ** 2, 0) / (p.length - 1));
        console.log(std_p)
        othersame_cv = (std_p / mean_p);
        console.log(othersame_cv)
    }

although I am doing similar computations in the upper parts, mean_p and std_p returns NAN here

What value of p do you get in that while clause?

oh lol, I know that this is getting annoying, but… now I managed to get rid of the NaNs by modifying here:

for (var i, _pj_c = 0, _pj_a = util.range(0, 90), _pj_b = _pj_a.length; (_pj_c < _pj_b); _pj_c += 1) {
    i = _pj_a[_pj_c];
    check_val = generateGaussian(mean_repro, stdev_repro,1);
    console.log(check_val)
    while ((check_val < 0)) {
        check_val = generateGaussian(mean_repro, stdev_repro,1);
        console.log(check_val)
    }
    obs_rep.push(check_val);
    console.log(obs_rep)
}

as:

for (var i, _pj_c = 0, _pj_a = util.range(0, 90), _pj_b = _pj_a.length; (_pj_c < _pj_b); _pj_c += 1) {
    i = _pj_a[_pj_c];
    check_val = generateGaussian(mean_repro, stdev_repro,1);
    console.log(check_val)
    while ((check_val < 0)) {
        check_val = generateGaussian(mean_repro, stdev_repro,1);
        console.log(check_val)
    }
    obs_rep.push(check_val[0]); // <---- [0] added
    console.log(obs_rep)
}

now I can get meaningful mean and sd values but the code still goes unresponsive.

@wakecarter , did not solve it, but at least I understood what the problem is and it is purely mathematical instead of something code/algorithm related:

okay, so I have a distribution of 90 values (say dist A) with a mean and a standard deviations. What I want my code to do is to draw a subset of 30 values (say dist B) that is composed of values with (e.g.) 110% of the original mean value (mean of dist A). Not much of a problem to do it for a dist A with a fairly high standard deviation because this means that there are some handful values that are deviated from the mean in either direction (lower or upper). this increases the probability of retrieving the fairly extreme numbers at a cost of a few shots and thus, lower execution times. However… as the standard deviation of the dist A decreases, its values come closer to the mean itself, thus makes it harder to find 30 values that brings a mean value (e.g., mean of dist B) larger than the original mean value (e.g., mean of dist A), because such instances are already quite limited. Hence, my algorithm keeps trying… and failing to find such a subset of dist B that satisfies my “110% of the original mean” condition. so, it is not that the algorithm is not working properly, and it is also not that what I ask it to do is just impossible; its doable, but its just a little too low in probability that can take a really, really long times. needless to say; this works the same for both ways (either upper or lower mean than the mean of dist A).

in a scenario where the parameters of dist A cannot be arbitrarily manipulated (e.g., we cant instruct a participant to make estimations with high standard deviation…), a way to overcome this would be to narrow the upper and lower boundaries and thereby let the new mean parameter (dist B) closer to the original mean (dist A) (not sure if I can find the effect I am after that way though - but we will see…). or maybe to withdraw much fewer values for the new distribution.

sorry for interrupting with a problem that is not in fact has anything to do with PsychoPy/Pavlovia.