psychopy.org | Reference | Downloads | Github

Performance criterion translated to Java Script

Task URL https://pavlovia.org/run/Topor/probabilistic-learning-task/html/
Description of the problem: The task is still quite rough around the edges. I am focusing at the moment on translating the code from Python to PsychoPy.

The task has three phases. The first one is a practice phase and it works fine. The second one is a learning phase and this is where a lot of code has been added. I made a threshold that each participant has to reach before they can progress to the last phase of the experiment. I have already translated parts of the code so the task is working to a certain point. As soon as I started translating the code for the performance criterion, the task stopped working. When I run it, a message shows up “loading the experiment”. I saw on other threads that this means the code is not translated correctly.

This is what I did to establish the criterion

first set of stimuli
sum of correct responses in the last 60 trials in conditions 1 > 12, in conditions 2 > 11 and in condition 3 > 9, there must be at least 60 trials in the training phase

if myCount == 1 and (sum(resplist1[-60:]) > 12 and sum(resplist2[-60:]) > 11 and sum(resplist3[-60:]) > 9 and myCount1 > 59):
    practice.finished = True

I understand that Java Script does not have options to easily operate on arrays.
I have created array slices to identify the last 60 trials, and I made a function to sum the array contents. It looks like this:

practiceA = resplist1.slice(-60,)
practiceB = resplist2.slice(-60,)
practiceC = resplist3.slice(-60,)

arrSum = function(arr){
  return arr.reduce(function(a,b){
    return a + b
  }, 0);
}

Corr1 = arrSum(practiceA)
Corr2 = arrSum(practiceB)
Corr3 = arrSum(practiceC)

if (myCount == 1 and Corr1 > 12 and Corr2  > 11 and Corr3 > 9 and myCount1 > 59)){``
   practice.finished = true;
}

The empty arrays are stated in the Begin routine tab.
However, only in the End Routine tab I included a code that commands how the resplist arrays (used in the Begin routine tab) should be appended. This was not an issue in PsychoPy, but potentially an issue for JS?:

if(resp.keys == letterA) {
  resp1 = 1;
} else {
  resp1 = 0;
}

if(resp.keys == letterC) {
  resp2 = 1;
} else {
  resp2 = 0;
}

if(resp.keys == letterE) {
  resp3 = 1;
} else {
  resp3 = 0;
}

resplist1.appendChild(resp1)
resplist2.appendChild(resp2)
resplist3.appendChild(resp3)

I will appreciate it if someone can look through the code to see if there is anything obvious that could be wrong. The task overall has more code so it is possible that the pieces are in the wrong place as well.

I will appreciate all help!

@MartaT, the first thing I can see is the use of and in your conditional if statements. In JS, you should use && instead. Regarding resplist1 to 3, which look like arrays, I would use the push method to add to those arrays, although this will give nested lists if your push an array to the array, rather than pushing an int/float/string. Alternatively, you can use the concat method, which flattens out the array if you try to concatenate an array to an array. Try those fixes first, and then we see if any other errors are raised.

1 Like

Hi @dvbridges I have made the suggested changes. So my performance criterion code now looks like this:

if (myCount == 1 && Corr1 > 12 && Corr2 > 11 && Corr3 > 9 && myCount1 > 59)){
    practice.finished = true;
}

And the resplists1-3:

resplist1.push(resp1)
resplist2.push(resp2)
resplist3.push(resp3)

However, resplists1-3 are composed of integers (I would have thought), every trial there is one new integer added - either 1 or 0.
Then I take a slice of the last 60 numbers and create a sum in the new variable Corr1-3.

The issue does not seem to be fixed. The message “loading experiment” comes up. However, if I remove the code for performance criterion, the task loads ok.

Ok looks like the same syntax error, but the reason is because there is extra closing brackets on the following conditionals (line 1263)

if (myCount == 1 && Corr1 > 12 && Corr2 > 11 && Corr3 > 9 && myCount1 > 59)){
      practice.finished = true;
  }
  
  if (myCount == 2 && Corr1 > 12 && Corr2 > 11 && practiceCSum > 9 && Corr3 > 59)){
      practice.finished = true;
  } 
  
  if (myCount == 3 && Corr1 > 12 && Corr2 > 11 && Corr3 > 9 && myCount3 > 59)){
      practice.finished = true;
  }

Remove the extra closing bracket and resync.

Marta, to format code in your post you need 3 backticks, but just at the start and end of the code like this;

here is a line
here is another

You can also specify the language (although I think it tries to detect that automatically too) and that alters teh keywords that get highlighted:

this is Python
this is JavaScript;

Click on edit to see how these were written. I’ve edited your first post to show you.

thanks

Thank you! Just noticed the changes, good stuff!

Regarding problems with your actual code, the lines practiceA = resplist1.slice(-60,) look like they need semi colons to me.

In general, your browser should have a way to “inspect” the code when it fails so you can see where potential errors are. It will probably highlight a syntax error on or just after the line that was broken.

@dvbridges Thanks! I removed the bracket and it removed the problem!

@jon Thank you, I read some forums about this and decided to get rid of the comma and put nothing else and it worked.

The performance criterion is working well now. I have tested it under different conditions and it seems to be working just like the original task with the python code.

I tried to see if I can finish the task without any further errors though, and I had something unexpected pop-up.

The task runs the main loop three times with different stimuli used every time. Each run includes a new learning phase with the performance criterion used and then a testing phase, which is more straightforward. No criterion and no feedback.
The only code I left in the testing phase is the jitter specification. When trialing the task, in the very final run (run 3) just before the testing phase was supposed to start (after I pressed the space bar on the instruction screen) this happened:

image

There is no ‘#’ in the js code, I know that comments are made with //. I checked the stimuli files that are used and there are no odd #s creeping around. The component fields also look clear from #s. Not sure where else to look or where the source of this could be.

@MartaT, I have seen this error before where the user had empty columns in their conditions file (see below). The fix was to delete the empty columns. Does this help?

1 Like

Brilliant! I found the bug in one of the stimuli files (and it was an empty column indeed) and it is all sorted now! I also had to clean out the cached files in the browser before it was running ok.

One final thing (I hope) I wanted to check is whether the main loop is terminated as instructed, so after three runs of the learning and testing phases subsequently.
Unfortunately, this is not the case. I am not sure why the code for the loop to be finished is not being executed. I thought it was in the wrong place so eventually I tried it everywhere throughout the loop and it made no difference.
The myCount variable is used by other commands for the task and that seems to be working fine so it looks like the object is updated properly. Just the loop does not terminate after 3 runs. The code looks like this:

if(myCount > 3) {
  letterMaster.finished = true;
} 

@dvbridges
I see that this issue is being worked on as per the github thread.

If there are no updates on this I will just set up the task as a pilot with the number of possible stimuli equal to the number of loops. I will keep an eye on the thread for when this is changed to update the task.

Just to note though, the performance criterion itself has a condition to terminate the practice loop and this works.

Hi @MartaT, this fix was made and released in 3.1.0, so if you are using version >= 3.1.0 the loop finishing statement should work (I have tested this in 3.1.2 standalone and it does work). What this will not do is finish your routines that are in the loop. All routines will complete before the loop finishes. In that case, if I only wanted 3 iterations, and my counter starts from zero, but I am incrementing my counter before checking whether the loop should end (which I think is what you are doing), I would check for equality instead:

myCount = myCount + 1
if (myCount === 1) {
    currentLoop.finished = true;  // finish at end of this loop
}

Hi @dvbridges thanks a lot for explaining this. I have tried to go with equality before but it didn’t work although I only used 2 equal signs. I trialled the task again today a few times with triple equals and still the loop does not terminate.

I was worried that the task maybe does not update properly between each sync so I made sure to export the html manually and I also tested the task on a different computer today. I have no idea what might be the issue.