psychopy.org | Reference | Downloads | Github

Blocks of rating forms

OS (e.g. Win10): macOS Mojave 10.14.6
PsychoPy version (e.g. 1.84.x): v3.2.4
Standard Standalone? (y/n) y
What are you trying to achieve?:
Hi there,
first of all, i’m supernew to PsychoPy, so please keep that in mind.

I want 60 items to be rated on a 7-point scale. I tried the form component for this to have multiple ratings on one screen with a scroll bar. Because they were to many I decided to divide them into 6 different excel-files (each with 10 items). I wanted them to appear randomly after each other, so I thought block of trials would be a good approach after randomizing the 10 items within a file.

My color excel files all look like this:
question text type options layout
orange; rating; not at all, , , , , , absolutely; horiz
blue…
The chooseBlocks looks like this
StimFile
colors1.xlsx
colors2.xlsx…

What should i write for Items in the form component? $StimFile as well? or leave it blank? !



What did you try to make it work?:
I tried to transfer Jons Tutorial: https://www.psychopy.org/builder/blocksCounterbalance.html

I checked if i needed some path added to the files but they’re on my desktop, just as the psyexp file

What specifically went wrong when you tried that?:
The experiment doesn’t even start and i get the following:
Further it says that it can’t find a condition file. see screenshots

if key_resp.keys in ['', [], None]:  # No response was made
    ^
IndentationError: unexpected indent


the lines in the code are: 
\\\       
        # -------Ending Routine "trial"-------
        for thisComponent in trialComponents:
            if hasattr(thisComponent, "setAutoDraw"):
                thisComponent.setAutoDraw(False)
        formData = form.getData()
while formData['questions']:
    for dataTypes in formData.keys():
        thisExp.addData(dataTypes, formData[dataTypes].popleft())
    thisExp.nextEntry()
        # check responses
        if key_resp.keys in ['', [], None]:  # No response was made
            key_resp.keys = None
        trials.addData('key_resp.keys',key_resp.keys)
        if key_resp.keys != None:  # we had a response
            trials.addData('key_resp.rt', key_resp.rt)
        trials.addData('key_resp.started', key_resp.tStartRefresh)
        trials.addData('key_resp.stopped', key_resp.tStopRefresh)
        # the Routine "trial" was not non-slip safe, so reset the non-slip timer
        routineTimer.reset()
        thisExp.nextEntry()

Another question that i have is if the form tool is supported by Pavlovia? I have to run the study online later. So all the effort would be useless if that doesn’t work. For that case: is there any other possibility to have multiple rating scales on one screen? I don’t want participants to have 61 separate screens for the ratings

There are so many issues in your question that it would probably help to take a step back and simplify the experiments, get it running, and then introduce the randomization in a second step. Can you get the form to display one set of your question in a simplified version of your experiment (no loops, just one set of questions)?

There is an issue with your indentation. Do you have a code component in your builder script where the indentation could have gone wrong? The code after # check responses should be on the same level as the line before it.

You could have a file with the paths (your loop) to other files with the questions for your form.
Why do you have two nested loops?

Hi Lukas,

thanks for your friendly answer, i really appreciate it and i am sorry that everything seems so unclear. I guess thats because i just started today.

It works that i can see the 10 questions/ratings from one file, yes :slight_smile: So if i insert colors1.xlsx in the Item field of the form component
And i also just had one loop around, but then was confused. So you suggest to delete the block loop and select the chooseblocks as my conditionsfile in my trial loop, right? Then I’ll get the message “StimFile is not defined”

I’ll correct the line thanks

If you’re working in the Builder interface, you probably can’t change single lines like that. Where did you change it? In the Coder interface?

StimFile is the name of a column of your conditions file? What if you delete every component and add a text component with the text $StimFile. Does it display the path which you want StimFile to contain?

I don’t know how I did it but it seems ok now. Just started my unsaved experiment from before. Maybe I changed something by mistake but luckily this is not a problem any more.

The problem why I can’t just display StimFile is because there is no field for open entries like in the text component where i could simply put $StimFile. Then I’ll get StimFile is not defined.
I added a text component and told it to view $StimFile. Then I’ll get “colors2.xlsx” on the screen

So your experiment is working now? Or do you still have an issue?

Just the indent-thing in the code dissappeared. With the Screenshot that I sent I always get the same 10 items from colors1.xlsx again and again 6 times. I added the text component which changes, so in the background are the Items as a rating scale and in the foreground is the text changing from colors1.xlsx to colors4.xlsx and so on

I see; I’m sorry, I confused you. I think you are right - you cannot update the items of a form object in the middle of your experiment.

One (clumsy) way to solve your problem without a code component would be to have six routines with one form each (with the respective items file). Then you put a loop around all six of those. This loop would have one repetition and the condition file would just specify a variable whichForm with the numbers 0 to 5.
Then, within the global loop, there is a loop around each of the six trials. The first of these nested loops would have $whichForm == 0 for nReps. The second would have $whichForm == 1 for nReps. And so on.
Does this work?

Maybe… Sounds good to me
But again, I get the error of unexpected indent. As you said, I tried to put the line after check responses on the same level as the line above and also put “key_rep.keys = None” one level to the left (for all 6 trials then). But, and I know, you already told me, I can’t change lines in the code if I’m in Builder. Cause next time that I start it’s not saved and I get the same errors.
If I uncheck “Force end of routine” and don’t save any key I’ll get an indentation error with routineTimer.reset() That fixed, I still get the error that library “c” cannot be found

Is there anyone who knows how to deal with these (various) code problems if you’re in builder?

Or has another idea to randomize my forms?

Seems like this form problem is a consistent bug, not just you. I have had a similar indentation issue any time I create a form within a loop that has greater than 1 reps (I’m also on PsychoPy3 in MacOS).

I can manually correct the indentation using coder view and it will work, so maybe that is something you could try. However, after doing so I can’t go back and edit the experiment in builder.

I think the suggestion of using multiple routines might be best for your situation (if a bit hacky), avoiding loops. However, then you would have to use another strategy to randomize your forms-- maybe make a few lines of code using a code object at the beginning of the experiment like:

import random
random.seed() # set randomization seed so you don't get the same shuffle each time
listBlocks = ['colors1.xlsx', 'colors2.xlsx', ...etc.]  # list out your excel files
random.shuffle(listBlocks) # shuffle them up randomly

Then, before each each of your 6 routines, put another routine with a code block in it saying something like:

StimFile = listBlocks[2] # or whatever number block this is

Then you just have to refer to $StimFile when you go to make your form.

@aisa2, nice work around, looks like there are some bugs in the Form that need correcting, but I think there may be an overhaul in future where the Form component has a complete change. Anyway, I have alternative fix that can be done using Builder. This fix is for a task where you have a single loop containing a conditions file, where the conditions file has the paths to multiple files containing questions. First, open your form and give the path to one of the question files, this is so the form can first be created. Next, add the conditions file to the loop. In a code component, add the following code (where “form” is the name of the Form component):

###### Begin Routine
# Reset the form and load a new question file
form.formElements = {'itemIndex': [], 'question': [], 'response': []}
form.items = form.importItems(con)  # con is the variable containing paths
form._doLayout()

###### Each Frame
# If the form is complete, end the routine and save the form data
if form.formComplete():
    continueRoutine = False
    formData = form.getData()
    while formData['questions']:
        for dataTypes in formData.keys():
            thisExp.addData(dataTypes, formData[dataTypes].popleft())
        thisExp.nextEntry()

You will get a duplicate row of data when the form automatically saves at the end of the loop. Here the is example and files, where a.csv and b.csv are question files, and conds.csv is the condition file used in the loop.

a.csv (49 Bytes) b.csv (26 Bytes) conds.csv (19 Bytes) multF.psyexp (6.8 KB)


Just to make sure that I understood right: Does my flow then look like this and I’ve only the code component before each form where I put $StimFile in the Items-Field?

What I get is AttributeError: ‘list’ object has no attribute ‘shuffle’

Just a heads up before you go to all this effort, Forms are not supported online yet, so if you do plan to run this online, you are better off coming up with an alternative solution, for example, using sliderss and text components to present your questions from a loop - this way, you can run your survey online.

Hi bubu,

Oops, you’re right, maybe try

random.shuffle(listBlocks)

I’ll update my other response to reflect that.
Otherwise this looks right to me

Ok thanks. So I try to use sliders. Is there a possibility to present 10 random items with sliders on one screen? Cause that was my original idea for using the form component. I don’t want participants to rate my colors on 60 screens and always have to confirm after one to continue

That’s exactly what I’m working through right now on my experiment. For me, I find that 6 is already hard to fit on the screen, but possible. Not sure about 10.

If you keep the design the same, where you have a loop with a conditions file that contains paths to the actual questions, you can import the questions at the start of each routine using data.importConditions, then convert this to a list of questions, randomise the list of questions, and then present them using a text component with sliders positioned appropriately. This requires minimal coding, but you do need to manually code the JS, as it requires a different approach using trialHandler to get the questions. Here is a smaller working example that only presents 2 of the 10 questions - and the working URL of the online version

a.csv (144 Bytes) b.csv (144 Bytes) conds.csv (19 Bytes) multS.psyexp (17.6 KB)

https://run.pavlovia.org/dvbridges/test_surveys/html/

1 Like

This might be a silly question but how do I manage to get for example six different textStimuli corresponding to the rating scales. I have my 60 colors/textStimuli in a condition file called colors.xlsx now (just one column called Color). Then I added 6 rating scales to my routine and 6 text components. When I put $Color in it, of course I get the same color in all 6 text fields. So how do I get 6 different ones and then one the next routine 6 other ones and so on till all have been presented once?
I guess I need a little bit of coding, right?

If you can code it, that would probably be more robust/modifiable.
However, if you don’t want to code, it you could try re-organizing your file with more columns, e.g.
color1 text1 color2 text2 color3 text3… and so on up to text6. Then you will have different variables to refer to in the builder, e.g. $text5
In that case, each row would refer to a set of questions rather than an individual question.