Using data from a form component within the same experiment... (Previously "Form object not subscriptable")

When attempting to use data from a Form component e.g., form[1].response, I’m just getting errors about the Form object not being subscriptable. Any suggestions how to get around this?

(I’m essentially trying to get a simple “if any of the form responses >0, do this” sorted.)

Hi,

The form component has an attribute called getData() - see Forms API. This brings up not only the data but also the form’s attributes. The format of the output seems to be an ordered dictionary within a list where one list is one question of the form.

To get the response value from getData(), in a code component end of routine tab type the below where form is then mane of the form component.

for k, v in enumerate(form.getData()): # loop through each list
    for key, value in v.items(): # loop though each dictionary
        if key == 'response':
            if value > 0:
                # do something

Note, if you attempt to print the above to the stdout, rather confusingly only prints the response to the first question only but in the background all responses are saved at the end of the routine.

Hope this helps

Best wishes,
Yiannis

Many many thanks, Yiannis. Very helpful. I’d stumbled upon form.getData(), but didn’t know how to access its lists/properties.

And I’ve tried the code your provided, but get this error:

    if value > 0:
TypeError: '>' not supported between instances of 'NoneType' and 'int'

Any chance you can upload a minimal example of your exp?

Thanks

BW
Yiannis

Thanks for getting back to me and sincere apologies for not responding for so long!

Following your indication that the form.data is a list of dicts, I have been trying to access the ‘response’ key/value by getting the data:

consent_formList = consent_form.getData()

Then attempting to check it:

if consent_formList[2]['response'] == 1.0 \
or consent_formList[3]['response'] == 1.0 \
or consent_formList[4]['response'] == 1.0 \
or consent_formList[5]['response'] == 1.0 \
or consent_formList[6]['response'] == 1.0 :
    dataCollection.finished = True

I’ve tried this and specifying the values as strings, defining variables for each of the values first (e.g., q6 = consent_formList[6]['response'] and then using that variable in the if statement, and probably other nonsensical things, but couldn’t get the experiment to end when any/all of those values were 1.0. I confirmed that these values were being fetched and stored by printing them too (though printing didn’t happen at the time the code was executed, usually at the end of the experiment instead).

I then tried just continueRoutine = False to see if it was even working and that worked as expected, leading me to think that it’s the loop exit code that’s not working somehow. So I tried currentLoop.finished = True as well, but that didn’t work either…

I’m now at a loss again.

All I want to do is essentially skip to the last routine if any of the form responses are 1.0.

Could the loop.finished=True not happening when I want be something to do with the finished attribute is only checked at the start of each rep?

Also, neither break nor continue work (as I would expect).

Sorry to bump, but does anyone have any ideas? It seems that what I’ve done is fetching and storing the response value and checking it results in the correct output, but the loop just won’t be exited based on that data (continueRoutine = False, however, does work to exit a routine).

I’m now thinking it might not be anything to do with the form component or data, but still don’t know why I can’t exit the loop…

And if this is the case (that it’s because the finished attribute is only evaluated at the very start of the loop), how do I exit the loop on the first (and only) rep after it has started? I’ve tried using code in the Each frame tab, but not been successful there either.

Hi @PsyTechMMU, could you show a screenshot of your flow? From what you write it sounds like you want to skip/end the “data collection” if the consent form is not agreed to, right? I am wondering why the form is in a loop at all. Could you explain?

Many many thanks for responding, Adrian.

Screenshot:

The consent form component is in the Consent routine and my last attempts to get this working are in the consentChecker routine, which is the first routine in the dataCollection loop (this contains many routines that needs to be skipped). The loop is followed by just a Debrief routine (to which we want to skip to if full consent is not obtained).

Hope that makes sense! This is how a student has explicitly stated they need it to work. Please feel free to ask any other questions or make any other suggestions. :grinning:

Thanks in advance!

I think the easiest solution would be to set the number of repetitions of this loop to 1 or 0 depending on your condition (consent is given / not given):

End routine

if YourCondition:
    DoDatacollection = 1
else:
    DoDatacollection = 0

and then use $DoDatacollection in the “number of repetitions” field of your loop.

Hope that helps!

1 Like

You’re an absolute beauty! Thank you for this simple and elegant method! :smiley:

1 Like