Math.random() function in PsychoPy for Pavlovia

Hello,

I am attempting to use a random function to determine feedback values, but I am having some trouble.

As I have learnt, it is impossible to use “import” functions in Pavlovia, so I am having to find a way around using “import random”.

However, I have fallen at the first hurdle; if I simply use the Math.random() function in a JS code component, my experiment does not work at all. I simply typed “x = Math.random()” and I put “$x” in a text component (set every frame) in the same routine. The experiment then crashes when I run it.

I am sure I am just making a very simple mistake somewhere - can anyone point me in the right direction?

Thanks!
Marcus

Hi Marcus,

Sounds like you are on the right track, please could you let us know what error message you get when your experiment crashes and, if possible, share a miminaly working version of your file/problem :slight_smile:

As a first check - do you have x specified in both python and JS? if not then it will crash locally because x isn’t defined. Try using a code component where the code type is ‘both’ and on the left you have x =np.random.rand() and on the right x = Math.random()

Thanks,
Becca

Hi Becca,

Thank you for this, it has worked! I should be able to extrapolate this method and use it in my broader experiment now.

Just out of curiosity though, why can x not just be defined in a JS code component? And what exactly is the “np.random.rand()” function doing?

Thanks,
Marcus

Hmm actually sorry I think you might want random.random() on your python side ( I assumed you wanted to randomly sample a number between 0 and 1 since this is what Math.random does https://stackoverflow.com/questions/33359740/random-number-between-0-and-1-in-python) - random.random() and math.random() should be functionally equivalent.

In response you your Q ‘why can x not just be defined in a JS code component?’ - technically it can, but that code will only be run online. Any JS code components will be run online and any Py components will be run locally.

Locally you rexperiment uses PsychoPy, so only interprets python code. Online, you expeirment used PsychoJS so will monly read JS components.

Hope this helps :slight_smile:

If the solution worked please could you also mark the solution for future users!

Thanks,
Becca

1 Like

Great. The random.random() function works just as well, providing I add “import random” too. What is the “random.random()” function doing differently to “np.random.rand()”?

Brilliant, that is incredibly helpful, thank you very much!
Marcus

technically I think they output the same thing but np.random.random() can take additional parameters and has more methods for generating a uniform distribution over a range a useful thread might be this here https://stackoverflow.com/questions/7029993/differences-between-numpy-random-and-random-random-in-python :slight_smile: as well as the official documentation on these libraries


Becca

I tried using this fix on my local Python code components, and it’s not working. I tried substituting random.random() and math.random() for np.random(), neither of which worked. With random.random(), I get AttributeError: 'builtin_function_or_method' object has no attribute 'random'
and with math.random() I get NameError: name 'math' is not defined.

Hi There,

In the newest release this should no longer be needed. You should be able to use random() and that will work both locally and online.

Thanks,
Becca

Is there a version of random.uniform() that works? I tried both that and just random(), but with random() I get the following error:
TypeError: random() takes at most 1 positional argument (2 given)

For context, I’m trying to generate a random integer between two values:
lower_t1_x = random(-785, 445)

locally random.uniform will use the numpy library, which will not work online because it is python but it looks like the JS version of random samples over an approximately uniform distribution, but between 0 and 1. Could you try using linspace instead?

Add a code component, set type to JS, use this in the before experiment tab:

//provide the JS alternative to any functions that exist in python but not JS
function linspace(startValue, stopValue, cardinality) {
  var arr = [];
  var step = (stopValue - startValue) / (cardinality - 1);
  for (var i = 0; i < cardinality; i++) {
    arr.push(startValue + (step * i));
  }
  return arr;
}

then you can call it later using linspace(start, stop, cardinality)

Becca