Drag&Drop Stimuli Output

Hi,
I’m building an experiment where participants drag and drop 4 image stimuli, in 4 of the 8 possible box polygons in each trial. I will analyze which image is placed on which polygon location for all stimuli in all trials. I’m unfamiliar to coding so I couldn’t figure out what I should to get an output in the data folder that tells me this. I’d appreciate if you could help me.
Below I post the code that I used to drag&drop stimuli and to prevent participants from proceeding to the next trial without completing the task (shoutout to every user who helped me build the experiment this far!).
Thanks in advance!

Begin Experiment

def movePicked(picked, mouse, grabbed):
if grabbed is not None and mouse.isPressedIn(grabbed):
grabbed.pos = mouse.getPos()
return grabbed
else:
for piece in picked:
if mouse.isPressedIn(piece) and grabbed is None:
return piece

stimuli = [“P1”,“P2”,“P3”,“P4”]
positions = [
(-0.33,0.35),
(-0.11,0.35),
(0.11, 0.35),
(0.33, 0.35)]

Begin Routine

pieces = [P1,P2,P3,P4]
picked =
movingPiece = None

P1.pos = positions[0]
P2.pos = positions[1]
P3.pos = positions[2]
P4.pos = positions[3]

allow_continue = False

Each Frame

for piece in pieces:
if mouse.isPressedIn(piece) and movingPiece is None:
picked.append(piece)

movingPiece = movePicked(picked, mouse, movingPiece)

match = # create empty list

for img_position in [P1.pos, P2.pos, P3.pos, P4.pos]: # for each image
for polygon in [S1, S2, S3, S4, S5, S6, S7, S8]: # and each polygon
if polygon.contains(img_position): # check whether this polygon contains this image
match.append(1) # if so, add a 1 to the list

allow_continue = len(match) == 4 # allow respondents to continue if there are 4 1’s in the list

Hi @Betul_O,

try this and let me know if it works:

Each frame

for piece in pieces:
    if mouse.isPressedIn(piece) and movingPiece is None:
        picked.append(piece)

movingPiece = movePicked(picked, mouse, movingPiece)

match = # create empty list

for img in [P1, P2, P3, P4]: # for each image
    for polygon in [S1, S2, S3, S4, S5, S6, S7, S8]: # and each polygon
        if polygon.contains(img.pos): # check whether this polygon contains this image
            match.append(1) # if so, add a 1 to the list
            exec(img.name + '_position = ' + polygon.name)

allow_continue = len(match) == 4 # allow respondents to continue if there are 4 1’s in the list

End routine

for img in [P1, P2, P3, P4]: # for each image
    thisExp.addData(img.name + '_position', eval(img.name + '_position')) # add the position to the output

Hi @ajus thanks for the response. However, the code didn’t work. Psychopy doesn’t give an error or anything, it works alright but the output folder does not contain anything regarding stimuli locations.
I wonder if I need to specify “store params for clicked” in mouse data properties. I tried $positions but didn’t work either. I’m attaching the output excel folder in case you’d like to look.
_FS2_test_exp.xlsx (141.9 KB)

image

Did you include the End routine code?

If so, please change it to

End routine

for img in [P1, P2, P3, P4]: # for each image
    print(img.name)
    print(img.name + '_position')
    print(eval(img.name + '_position'))
    thisExp.addData(img.name + '_position', eval(img.name + '_position')) # add the position to the

and let me know what is printed in the console at the end of the routine.

Also, your xlsx has some weird features: There are a lot of columns without names and the expInfo data is in the bottom left corner. Is this a product of my code? Or is it the same without it?

Still no :frowning:
Is this the console screenshot? I’m not sure


Yes, some of the rows in the excel file are slid to the right. Happens everytime but I don’t know why. The extraInfo data has always been in the bottom left corner so it’s not due to the code.
a1_FS2_test_exp.xlsx (57.9 KB)

The console is the bottom part of the runner window (std_out).

Oh sorry :sweat_smile:
The positions are visible here. I’m pasting it below. The whole thing is too long to post here but it repeats itself so I think it’ll be fine. Is there a way to get them in the output excel folder?

######################## Running: E:\FS2\FS2_lastrun.py ########################
pygame 1.9.6
Hello from the pygame community. Contribute - pygame wiki
P1
P1_position
Rect(class=<class ‘psychopy.visual.rect.Rect’>, autoDraw=False, autoLog=True, closeShape=True, color=method-wrapper(…), colorSpace=‘rgb’, contrast=None, depth=0.0, fillColor=array([1, 1, 1]), fillColorSpace=‘rgb’, fillRGB=array([1, 1, 1]), interpolate=True, lineColor=array([1., 1., 1.]), lineColorSpace=‘rgb’, lineRGB=array([1, 1, 1]), lineWidth=1.0, name=‘S1’, opacity=1, ori=0.0, pos=array([-0.22, 0.09]), size=array([0.19, 0.19]), units=‘height’, vertices=ndarray(…), win=Window(…))
P2
P2_position
Rect(class=<class ‘psychopy.visual.rect.Rect’>, autoDraw=False, autoLog=True, closeShape=True, color=method-wrapper(…), colorSpace=‘rgb’, contrast=None, depth=-1.0, fillColor=array([1, 1, 1]), fillColorSpace=‘rgb’, fillRGB=array([1, 1, 1]), interpolate=True, lineColor=array([1., 1., 1.]), lineColorSpace=‘rgb’, lineRGB=array([1, 1, 1]), lineWidth=1.0, name=‘S2’, opacity=1, ori=0.0, pos=array([0. , 0.09]), size=array([0.19, 0.19]), units=‘height’, vertices=ndarray(…), win=Window(…))
P3
P3_position
Rect(class=<class ‘psychopy.visual.rect.Rect’>, autoDraw=False, autoLog=True, closeShape=True, color=method-wrapper(…), colorSpace=‘rgb’, contrast=None, depth=-2.0, fillColor=array([1, 1, 1]), fillColorSpace=‘rgb’, fillRGB=array([1, 1, 1]), interpolate=True, lineColor=array([1., 1., 1.]), lineColorSpace=‘rgb’, lineRGB=array([1, 1, 1]), lineWidth=1.0, name=‘S3’, opacity=1, ori=0.0, pos=array([0.22, 0.09]), size=array([0.19, 0.19]), units=‘height’, vertices=ndarray(…), win=Window(…))
P4
P4_position
Rect(class=<class ‘psychopy.visual.rect.Rect’>, autoDraw=False, autoLog=True, closeShape=True, color=method-wrapper(…), colorSpace=‘rgb’, contrast=None, depth=-4.0, fillColor=array([1, 1, 1]), fillColorSpace=‘rgb’, fillRGB=array([1, 1, 1]), interpolate=True, lineColor=array([1., 1., 1.]), lineColorSpace=‘rgb’, lineRGB=array([1, 1, 1]), lineWidth=1.0, name=‘S5’, opacity=1, ori=0.0, pos=array([ 0.22, -0.13]), size=array([0.19, 0.19]), units=‘height’, vertices=ndarray(…), win=Window(…))
P1
P1_position
Rect(class=<class ‘psychopy.visual.rect.Rect’>, autoDraw=False, autoLog=True, closeShape=True, color=method-wrapper(…), colorSpace=‘rgb’, contrast=None, depth=0.0, fillColor=array([1, 1, 1]), fillColorSpace=‘rgb’, fillRGB=array([1, 1, 1]), interpolate=True, lineColor=array([1., 1., 1.]), lineColorSpace=‘rgb’, lineRGB=array([1, 1, 1]), lineWidth=1.0, name=‘S1’, opacity=1, ori=0.0, pos=array([-0.22, 0.09]), size=array([0.19, 0.19]), units=‘height’, vertices=ndarray(…), win=Window(…))
P2
P2_position
Rect(class=<class ‘psychopy.visual.rect.Rect’>, autoDraw=False, autoLog=True, closeShape=True, color=method-wrapper(…), colorSpace=‘rgb’, contrast=None, depth=-1.0, fillColor=array([1, 1, 1]), fillColorSpace=‘rgb’, fillRGB=array([1, 1, 1]), interpolate=True, lineColor=array([1., 1., 1.]), lineColorSpace=‘rgb’, lineRGB=array([1, 1, 1]), lineWidth=1.0, name=‘S2’, opacity=1, ori=0.0, pos=array([0. , 0.09]), size=array([0.19, 0.19]), units=‘height’, vertices=ndarray(…), win=Window(…))
P3
P3_position
Rect(class=<class ‘psychopy.visual.rect.Rect’>, autoDraw=False, autoLog=True, closeShape=True, color=method-wrapper(…), colorSpace=‘rgb’, contrast=None, depth=-2.0, fillColor=array([1, 1, 1]), fillColorSpace=‘rgb’, fillRGB=array([1, 1, 1]), interpolate=True, lineColor=array([1., 1., 1.]), lineColorSpace=‘rgb’, lineRGB=array([1, 1, 1]), lineWidth=1.0, name=‘S3’, opacity=1, ori=0.0, pos=array([0.22, 0.09]), size=array([0.19, 0.19]), units=‘height’, vertices=ndarray(…), win=Window(…))
P4
P4_position
Rect(class=<class ‘psychopy.visual.rect.Rect’>, autoDraw=False, autoLog=True, closeShape=True, color=method-wrapper(…), colorSpace=‘rgb’, contrast=None, depth=-4.0, fillColor=array([1, 1, 1]), fillColorSpace=‘rgb’, fillRGB=array([1, 1, 1]), interpolate=True, lineColor=array([1., 1., 1.]), lineColorSpace=‘rgb’, lineRGB=array([1, 1, 1]), lineWidth=1.0, name=‘S5’, opacity=1, ori=0.0, pos=array([ 0.22, -0.13]), size=array([0.19, 0.19]), units=‘height’, vertices=ndarray(…), win=Window(…))
P1
P1_position
Rect(class=<class ‘psychopy.visual.rect.Rect’>, autoDraw=False, autoLog=True, closeShape=True, color=method-wrapper(…), colorSpace=‘rgb’, contrast=None, depth=0.0, fillColor=array([1, 1, 1]), fillColorSpace=‘rgb’, fillRGB=array([1, 1, 1]), interpolate=True, lineColor=array([1., 1., 1.]), lineColorSpace=‘rgb’, lineRGB=array([1, 1, 1]), lineWidth=1.0, name=‘S1’, opacity=1, ori=0.0, pos=array([-0.22, 0.09]), size=array([0.19, 0.19]), units=‘height’, vertices=ndarray(…), win=Window(…))
P2
P2_position
Rect(class=<class ‘psychopy.visual.rect.Rect’>, autoDraw=False, autoLog=True, closeShape=True, color=method-wrapper(…), colorSpace=‘rgb’, contrast=None, depth=-1.0, fillColor=array([1, 1, 1]), fillColorSpace=‘rgb’, fillRGB=array([1, 1, 1]), interpolate=True, lineColor=array([1., 1., 1.]), lineColorSpace=‘rgb’, lineRGB=array([1, 1, 1]), lineWidth=1.0, name=‘S2’, opacity=1, ori=0.0, pos=array([0. , 0.09]), size=array([0.19, 0.19]), units=‘height’, vertices=ndarray(…), win=Window(…))
P3
P3_position
Rect(class=<class ‘psychopy.visual.rect.Rect’>, autoDraw=False, autoLog=True, closeShape=True, color=method-wrapper(…), colorSpace=‘rgb’, contrast=None, depth=-2.0, fillColor=array([1, 1, 1]), fillColorSpace=‘rgb’, fillRGB=array([1, 1, 1]), interpolate=True, lineColor=array([1., 1., 1.]), lineColorSpace=‘rgb’, lineRGB=array([1, 1, 1]), lineWidth=1.0, name=‘S3’, opacity=1, ori=0.0, pos=array([0.22, 0.09]), size=array([0.19, 0.19]), units=‘height’, vertices=ndarray(…), win=Window(…))
P4
P4_position
Rect(class=<class ‘psychopy.visual.rect.Rect’>, autoDraw=False, autoLog=True, closeShape=True, color=method-wrapper(…), colorSpace=‘rgb’, contrast=None, depth=-4.0, fillColor=array([1, 1, 1]), fillColorSpace=‘rgb’, fillRGB=array([1, 1, 1]), interpolate=True, lineColor=array([1., 1., 1.]), lineColorSpace=‘rgb’, lineRGB=array([1, 1, 1]), lineWidth=1.0, name=‘S5’, opacity=1, ori=0.0, pos=array([ 0.22, -0.13]), size=array([0.19, 0.19]), units=‘height’, vertices=ndarray(…), win=Window(…))

Ok, you have to exchange the line

with

exec(img.name + '_position = ' + '"' + polygon.name + '"')

this makes it work for me.

I changed it but I don’t see it in the output :frowning: I don’t know if I’m doing anything wrong but here’s the screenshot of the new code:

99_FS2_test_exp.xlsx (59.6 KB)

From the prints and my own test, it seems it should be working. But if there’s nothing in the output and the output seems to be messed up somehow I suspect there is something else going wrong. Could you add the line thisExp.addData("test","test") in the “End routine” code? This should add a column “test” to the output.

Also, why is your data in xlsx format? Do you open the csv file in Excel and then save it, or did you activate “save excel file” in the experiment settings? If so, could you set it back to csv and show the output?

Oh it works! Thanks a lot! It’s in the csv file as you said. We used the xlsx file output in my previous experiment so that’s why I was looking at that.
I realised if I rearrange the position of one image, there are multiple positions printed in the output and I don’t understand which position is the final position for which image. Can I solve this issue with changing mouse property to save mouse state to “final” instead of “on click” or does that need a code too?

These are the mouse coordinates. The positions in terms of which polygon contained the image at last (what I thought you wanted to know) should be in columns called “P1_position” and so on.

Oh I see. I can’t thank you enough, you literally saved my thesis! :pray:

1 Like

Glad to help! Please give the code a test run and check if the correct positions are saved before running the experiment with actual participants. There can always be unexpected errors in code, so a test is necessary. If you find any problems, let me know. Otherwise, good luck with your thesis!

1 Like

Hello again!
I finished collecting data for my experiment thanks to your help on coding. Now I’ll start another experiment, which is quite similar to this one except a few changes. I was wondering if there’s a way to adjust the code.
Here’s what’s changed: In first version’s output, image names were the headers and polygon names were saved under each image names’ columns. It worked because each image was a fixed variable type. This time, we wanted to randomize each variable type in each image. So, in the condition file we equally distributed each category under 4 images and now an image is not solely represents one category but instead 4 categories. The problem is that the output file is made to show where each image is put in which polygon. However, since each image consists of every category, I can’t tell which image category is placed into polygons.
Here’s a screenshot of what it was before:
image
And how it’s now (P as in picture):
output_fs3

Only one solution comes to my mind: Instead of printing image names as headers and polygon names under them, can I print polygon names as headers and image names under? So that I can identify them by comparing with the condition file. If so, the ouptut would look something like this:
image

I tried adjusting the original code to do this but failed miserably :sweat_smile: I wonder if there’s a way to achieve this?
I’m attaching the psychopy file and pasting the original code below.

It’s been a longer text than I intended, so thank you if you read this far :innocent:
FS3.psyexp (305.3 KB)

Begin experiment:
def movePicked(picked, mouse, grabbed):
if grabbed is not None and mouse.isPressedIn(grabbed):
grabbed.pos = mouse.getPos()
return grabbed
else:
for piece in picked:
if mouse.isPressedIn(piece) and grabbed is None:
return piece

stimuli = [“P1_PT1”,“P2_PT1”,“P3_PT1”,“P4_PT1”]
positions = [
(-0.5, -0.1),
(-0.5, 0.1),
(0.5, 0.1),
(0.5, -0.1)]

Begin routine:
pieces = [P1_PT1,P2_PT1,P3_PT1,P4_PT1]
picked =
movingPiece = None

P1_PT1.pos = positions[0]
P2_PT1.pos = positions[1]
P3_PT1.pos = positions[2]
P4_PT1.pos = positions[3]

allow_continue = False

Each frame:
for piece in pieces:
if mouse.isPressedIn(piece) and movingPiece is None:
picked.append(piece)

movingPiece = movePicked(picked, mouse, movingPiece)

match = # create empty list

for img in [P1_PT1,P2_PT1,P3_PT1,P4_PT1]: # for each image
for polygon in [top_left_PT1, top_center_PT1, top_right_PT1, left_center_PT1, right_center_PT1, bottom_left_PT1, bottom_center_PT1, bottom_right_PT1]: # and each polygon
if polygon.contains(img.pos): # check whether this polygon contains this image
match.append(1) # if so, add a 1 to the list
exec(img.name + '_pos = ’ + ‘"’ + polygon.name + ‘"’)

allow_continue = len(match) == 4 # allow respondents to continue if there are 4 1’s in the list

End routine:
for img in [P1_PT1,P2_PT1,P3_PT1,P4_PT1]: # for each image
print(img.name)
print(img.name + ‘_pos’)
print(eval(img.name + ‘_pos’))
thisExp.addData(img.name + ‘_pos’, eval(img.name + ‘_pos’)) # add the position to the outputv

Hi @Betul_O, glad to hear that your first experiment went well! Since you only want the data to be saved slightly differently I hope that there are not many adjustments needed.

Do these changes help?

Each frame

for img in [P1_PT1,P2_PT1,P3_PT1,P4_PT1]: # for each image
    for polygon in [top_left_PT1, top_center_PT1, top_right_PT1, left_center_PT1, right_center_PT1, bottom_left_PT1, bottom_center_PT1, bottom_right_PT1]: # and each polygon
        if polygon.contains(img.pos): # check whether this polygon contains this image
            match.append(1) # if so, add a 1 to the list
            exec(polygon.name + '_contains = ' + '"' + img.name + '"')

End routine

for polygon in [top_left_PT1, top_center_PT1, top_right_PT1, left_center_PT1, right_center_PT1, bottom_left_PT1, bottom_center_PT1, bottom_right_PT1]: # for each polygon
    thisExp.addData(polygon.name + '_contains', eval(polygon.name + '_contains')) # add the entailed image to the output

Hi, thanks for the quick answer! So I ran the experiment and it starts but gets corrupt after the first task. Error code is below:
File “D:\TEZ\FS3\FS3 - Copy_lastrun.py”, line 1245, in
thisExp.addData(polygon.name + ‘_contains’, eval(polygon.name + ‘_contains’)) # add the entailed image to the output
File “”, line 1, in
NameError: name ‘top_center_PT1_contains’ is not defined

I tried to solve the problem by adding the print commands (not that I know anything but they were there in previous experiment’s code so I thought it may work). However it still gave the error code that’s below. I couldn’t figure out what causes it :thinking:

for polygon in [top_left_PT1, top_center_PT1, top_right_PT1, left_center_PT1, right_center_PT1, bottom_left_PT1, bottom_center_PT1, bottom_right_PT1]: # for each polygon
print(polygon.name)
print(polygon.name + ‘_contains’)
print(eval(polygon.name + ‘_contains’))
thisExp.addData(polygon.name + ‘_contains’, eval(polygon.name + ‘_contains’)) # add the entailed image to the output

File “D:\TEZ\FS3\FS3 - Copy_lastrun.py”, line 1247, in
print(eval(polygon.name + ‘_contains’))
File “”, line 1, in
NameError: name ‘top_center_PT1_contains’ is not defined

Does this fix it?

End routine

for polygon in [top_left_PT1, top_center_PT1, top_right_PT1, left_center_PT1, right_center_PT1, bottom_left_PT1, bottom_center_PT1, bottom_right_PT1]: # for each polygon
    try: eval(polygon.name + '_contains')
    except NameError:  exec(polygon.name + '_contains = "no image"')
    thisExp.addData(polygon.name + '_contains', eval(polygon.name + '_contains')) # add the entailed image to the output

Yes!!! Exactly what I needed, thank you so so much :hugs:

1 Like

So sorry to bother you again, I have one last question.
In the previous experiment this part of the code below prevented participants to skip the trial unless they put all 4 images into a polygon. With the altered code I realized this no longer works and participants are able to skip trials without any work. I tried using the old exec(img.name + '_pos = ’ + ‘"’ + polygon.name + ‘"’) command but didn’t work and I’m afraid to mess the code up :cold_sweat:

Each Frame for previous experiment

for img in [UhLc_PT1,UhHc_PT1,HeLc_PT1,HeHc_PT1]: # for each image
    for polygon in [top_left, top_center, top_right, left_center, right_center, bottom_left, bottom_center, bottom_right]: # and each polygon
        if polygon.contains(img.pos): # check whether this polygon contains this image
            match.append(1) # if so, add a 1 to the list
            exec(img.name + '_pos = ' + '"' + polygon.name + '"')

allow_continue = len(match) == 4 # allow respondents to continue if there are 4 1’s in the list

Each Frame new one

match = [] # create empty list

for img in [P1_PT1,P2_PT1,P3_PT1,P4_PT1]: # for each image
    for polygon in [top_left_PT1, top_center_PT1, top_right_PT1, left_center_PT1, right_center_PT1, bottom_left_PT1, bottom_center_PT1, bottom_right_PT1]: # and each polygon
        if polygon.contains(img.pos): # check whether this polygon contains this image
            match.append(1) # if so, add a 1 to the list
            exec(polygon.name + '_contains = ' + '"' + img.name + '"')

allow_continue = len(match) == 4 # allow respondents to continue if there are 4 1’s in the list