psychopy.org | Reference | Downloads | Github

Unconvertable code component

URL of experiment: https://gitlab.pavlovia.org/DuderstadtV/leson_onlinepilot_square_debug

Description of the problem:
Dear all,

unfortunately I have an unconvertable code component. It randomly generates a bi-colored pixel square:

def generate_px_image(sizex=128, anteil_l = 0.5, anteil_r = 0.5):
    size = int(sizex **2)
    n_black_l = round(size//2.0 * anteil_l)
    n_black_r = round(size//2.0 * anteil_r)

    n_l = np.ones(size//2) * -1
    n_r = np.ones(size//2) * -1
    n_l[0:int(n_black_l)] = 1
    n_r[0:int(n_black_r)] = 1
    n_l = np.random.permutation(n_l).reshape(int(sizex),int(sizex/2))
    n_r = np.random.permutation(n_r).reshape(int(sizex),int(sizex/2))
    return np.append(n_l,n_r,1)

def generate_px_image_alt(sizex=128, anteil=0.5):
    return generate_px_image(sizex, anteil, anteil)

Does anyone know other solutions or has a suggestion how to convert this? Is numpy the problem?

Best regards,
Vinzenz

@Vinzenz, it looks like the double forward slash used in your Python code is causing the code translation issue, probably because // is used for commenting in JS. However, you are also going to have issues using numpy libraries in JS. You will need to find alternative methods that do not rely on Python libraries.

Thank you for your reply. I try to cenvert it, but am right now wondering, if there is an overview about workarounds for numpy components (in my case: np.ones , np.random.permutation, np.append) or if it would be possible to do the same thing I wish to accomplish with the stimNoise component? Can I change this from a 50/50 background/noise distribution?

I tried to convert to code, but it still is not running. Does anyone have a clue what is wrong? Right now it gives me a syntax error in the eight row.

function generate_px_image(sizex = 128, anteil_l = 0.5, anteil_r = 0.5) {
    var n_black_l, n_black_r, n_l, n_r, size;
    size = Number.parseInt(Math.pow(sizex, 2));
    n_black_l = Math.round(((size / 2.0) * anteil_l));
    n_black_r = Math.round(((size / 2.0) * anteil_r));
    n_l = (Math.ones((size / 2)) * (- 1));
    n_r = (Math.ones((size / 2)) * (- 1));
    n_l.slice(0, Number.parseInt(n_black_l)) = 1;
    n_r.slice(0, Number.parseInt(n_black_r)) = 1;
    n_l = Math.floor((Math.random() * 2)).permutation(n_l).reshape(Number.parseInt(sizex), Number.parseInt((sizex / 2)));
    n_r = Math.floor((Math.random() * 2)).permutation(n_r).reshape(Number.parseInt(sizex), Number.parseInt((sizex / 2)));
    return Math.matrix([[n_l], [n_r]]);
}
function generate_px_image_alt(sizex = 128, anteil = 0.5) {
    return generate_px_image(sizex, anteil, anteil);
}

@Vinzenz, could you share the error? It may be from n_l.slice(0, Number.parseInt(n_black_l)) = 1;, as you cannot assign a variable to a slice like that. It looks like you are trying to convert a range of values in that array to 1, and to do that you could use the map method, using something along the lines of

n_l = n_l.map((val, index) => {if (index < n_black_l) {return 1} else {return val}})

Thank you for your the reply! I will try out your suggestion. Right now I receive the following error:

SyntaxError: invalid assignment left-hand side

You can narrow this down by opening the JS console in your browser when the error occurs (in Chrome, it’s under view -> developer). That will give you an actual line number and tell you which statement it’s having trouble with.

I tried to rework the code based on your suggestions and it looks now like this:

function generate_px_image(sizex = 128, anteil_l = 0.5, anteil_r = 0.5) {
    var n_black_l, n_black_r, n_l, n_r, size;
    size = Number.parseInt(Math.pow(sizex, 2));
    n_black_l = Math.round(((size / 2.0) * anteil_l));
    n_black_r = Math.round(((size / 2.0) * anteil_r));
    n_l = Math.ones(((size / 2)) * (- 1));
    n_r = Math.ones(((size / 2)) * (- 1));
    n_l = n_l.map(x => {if (x = 0) {return 1} else {return -1}})
    n_r = n_r.map(x => {if (x = 0) {return 1} else {return -1}})
    n_l = Math.floor((Math.random() * 2)).permutation(n_l).reshape(Number.parseInt(sizex), Number.parseInt((sizex / 2)));
    n_r = Math.floor((Math.random() * 2)).permutation(n_r).reshape(Number.parseInt(sizex), Number.parseInt((sizex / 2)));
    return Math.matrix([[n_l], [n_r]]);
}
function generate_px_image_alt(sizex = 128, anteil = 0.5) {
    return generate_px_image(sizex, anteil, anteil);
}

But now I receive the following error message: TypeError: Math.ones is not a function
I exchanged the component np.ones with Math.ones and based on my research I assumed it does the same. Was I wrong?

JavaScript’s built in Math library doesn’t seem to have a ones() function. I suspect you’ve come across that function in the 3rd party math.js package:

https://mathjs.org/

I don’t know enough about JavaScript to advise whether or how you could install that library and access its functions from your script, but this thread might be useful:

Thank you htat soves the problem with math.ones. It is just really troublesome that the link to the library gets lost every time I synchronize my experiment.

I tried to use your code component as follows (but was not 100% sure how to define “val” and “index”):

function generate_px_image(sizex = 128, anteil_l = 0.5, anteil_r = 0.5) {
    var n_black_l, n_black_r, n_l, n_r, size;
    size = Number.parseInt(Math.pow(sizex, 2));
    n_black_l = Math.round(((size / 2.0) * anteil_l));
    n_black_r = Math.round(((size / 2.0) * anteil_r));
    n_l = math.ones((size / 2)) * (- 1);
    n_r = math.ones((size / 2)) * (- 1);
    n_l = n_l.map((x) => {if (x < n_black_l) {return 1} else {return x}});
    n_r = n_r.map((x) => {if (x < n_black_l) {return 1} else {return x}});
    n_l = Math.floor((Math.random() * 2)).permutation(n_l).reshape(Number.parseInt(sizex), Number.parseInt((sizex / 2)));
    n_r = Math.floor((Math.random() * 2)).permutation(n_r).reshape(Number.parseInt(sizex), Number.parseInt((sizex / 2)));
    return Math.matrix([[n_l], [n_r]]);
}
function generate_px_image_alt(sizex = 128, anteil = 0.5) {
    return generate_px_image(sizex, anteil, anteil);
}

But now I receive the error: TypeError: n_l.map is not a function . I assumed it would be because math.ones gives no array back, but this should be the case.

Not sure what math.ones is, but it is not part of the Math package. Try using the following instead to populate n_l and n_r with -1 values instead of math.ones

n_l = [...Array(size/2).keys()].fill(-1)

Now you should have an array that has the map method. In the previous answer, val and index are arguments that are passed to the map function, I used names that aimed to explain how those values are used in the method, so val is the actual val for that particular index - see Mozilla map docs . Its similar to the following in Python:

for index, val in enumerate(n_l):
  # do this

I was looking into this, in math.js ones(n) just creates an array of length n filled with the number 1. It indeed does not exist in JS’s native Math library, which is the source of that error. So, the “fill” solution should just solve that problem.

1 Like