How to use number that is entered in dialog box to define condition of participant

Hi there! I am trying to use counterbalancing in my experiment so I want the condition entered in the dialogue box (it will be a number from 1-8) at the beginning to determine which set of cues is used later in the experiment and I am not sure how to do this.
The code for the dialogue box looks like this

expName = 'testcodingHW'  # from the Builder filename that created this script
expInfo = {'condition' : '','session': '001', 'participant': '', }
dlg = gui.DlgFromDict(dictionary=expInfo, title=expName)
if dlg.OK == False:
    core.quit()  # user pressed cancel
expInfo['date'] = data.getDateStr()  # add a simple timestamp
expInfo['expName'] = expName

Based on the condition we were hoping it would pull from an excel file that would determine which set of cues to use. The excel file looks like this

Then we have a different excel file which looks like this


and it specifies the rest of the information about the trial and we were hoping to connect the excel files so the “Conditions” file pulls from the “Counterbalancing” file so it knows what cues to use, but we want it to only refer to the row in the “Counterbalancing” file that corresponds to the condition for that specific participant.

The code we have for the “conditions file” is like this but we are not sure how to change it so it does the above.

    extraInfo=expInfo, originPath=-1,
    trialList=data.importConditions('conditions.xlsx', selection="0:280"),
    seed=None, name='trials')
thisExp.addLoop(trials)  # add the loop to the experiment
thisTrial = trials.trialList[0]  # so we can initialise stimuli with some values
# abbreviate parameter names if possible (e.g. rgb = thisTrial.rgb)
if thisTrial != None:
    for paramName in thisTrial:
        exec('{} = thisTrial[paramName]'.format(paramName))

Thank you so much, we are totally beginners so would appreciate any help at all!!

Hi,

I wouldn’t be sure how to access the information in the counterbalancing file when the path to it is part of the conditions file. Therefore, I would tend to go for a different solution. To clarify: I assume the cues are constant across the course of the experiment for a given participant?

If yes: Option 1 would be to keep your current counterbalancing file, read it in at the beginning of the experiment and select the cue information based on the condition (e.g., you could do this using pandas).

Option 2 would be to not use a counterbalancing file, but simply add the following code after the expinfo dialogue information has been processed:

if expInfo["condition"] == "1":  # I think the condition will be a string
    GoFear = "Cue1.tiff"
    NoGoFear = "Cue2.tiff"
    GoNeut = "Cue3.tiff"
    NoGoNeut = "Cue4.tiff"
elif expInfo["condition"] == "2":
    GoFear = "Cue1.tiff"
    NoGoFear = "Cue2.tiff"
    GoNeut = "Cue4.tiff"
    NoGoNeut = "Cue3.tiff"
# etc.

This will require a bit more typing, but might be quicker if you’re not familiar with pandas.

Hope this helps.

Jan

1 Like

Hi @jderrfuss

Thank you so much for your help!! This was great.

This brought up another error though because it is now trying to look for an image named “GoFear” so we aren’t sure how to tell it to use “GoFear” to look in this code to determine what cue image to use based on what condition we are in.

if expInfo["condition"] == "1":  # I think the condition will be a string
    GoFear = "Cue1.tiff"
    NoGoFear = "Cue2.tiff"
    GoNeut = "Cue3.tiff"
    NoGoNeut = "Cue4.tiff"
elif expInfo["condition"] == "2":
    GoFear = "Cue1.tiff"
    NoGoFear = "Cue2.tiff"
    GoNeut = "Cue4.tiff"
    NoGoNeut = "Cue3.tiff"

The error says this:

ObjectCue.setImage(condition)
NameError: name 'condition' is not defined

and I think its coming from the part of the code that says this

# ------Prepare to start Routine "trial"-------
    t = 0
    trialClock.reset()  # clock
    frameN = -1
    continueRoutine = True
    routineTimer.add(6.000000)
    # update component parameters for each repeat
    ObjectCue.setImage(condition)
    Trial_Response = event.BuilderKeyResponse()
    OutcomeImage.setImage(OutcomeFile)
    # keep track of which components have finished
    trialComponents = [ObjectCue, Trial_Response, text_3, OutcomeImage, text_2]
    for thisComponent in trialComponents:
        if hasattr(thisComponent, 'status'):
            thisComponent.status = NOT_STARTED

and ObjectCue is defined earlier as

trialClock = core.Clock()
ObjectCue = visual.ImageStim( #Number 
    win=win, name='ObjectFile',
    image='sin', mask=None,
    ori=0, pos=(0, 0), size=(.5, .5),
    color=[1,1,1], colorSpace='rgb', opacity=1,
    flipHoriz=False, flipVert=False,
    texRes=128, interpolate=True, depth=0.0)

But now ObjectFile isn’t in the excel sheet because the excel sheet just has the trial type in it and we want it to use the trial type from the excel file to look for what image to use later in the code.

Does that make sense? Thank you so much for your help!

Hayley

@hayley13, let me ask a question for clarification: Why are you using the Coder instead of the Builder?

Jan

The error is actually very clear: The line ObjectCue.setImage(condition) throws an error because the variable 'condition' is not defined.
What you have defined is expInfo["condition"] which is a “1” or “2”.
And you also have relative paths to 4 pictures: GoFear, etc.

In your start Routine of trial, you need another variable that tells you which image should be shown in this particular trial. Put the respective name into ObjectCue.setImage(...), e.g. ObjectCue.setImage(NoGoNeut).

I hope this helps.
Best regards,
Mario

Sure. It’s just that Hayley said that “we are totally beginners”. Thus, I wondered if there is a good reason for using the Coder and if using the Builder might not be more straightforward.

Jan

Hi Jan,

We did mostly use the builder but thought it would be necessary to do this part with code. Thank you for your help though.

Hayley

Thank you so much this was super helpful!

Hi @hayley13,

If you’d like to learn to code PsychoPy, editing Builder-generated code is a great way to get started. However, if your focus is on getting the experiment running as quickly as possible, you could use the Builder to do what you want. You would need to add a code component (Components → Custom) at the top (i.e., as the first component) of the routine in which the cue is presented.

In the tab Begin Experiment, you would add the code I previously posted. Having looked at your conditions file, however, I noticed that your trialType values are identical to the ones you used as headers in your counterbalancing file. Therefore, it would be better to use something like goFearPic etc. for the cues.

In the tab Begin Routine, you would then add something along these lines:

if trialType == "GoFear":
    cuePic = goFearPic
elif trialType == "GoNeut":
    cuePic = goNeutPic
# etc.

This assumes that your image component for the cue looks like this (Cues is the path, os.sep is the path separator):
image

Hope this helps.

Jan