Use data from output file to do analysis within experiment

Hi,

I need to include an analysis of the output data in my experiment in order to show the results to the participants immediately after they finish the task. Is there any way to do this - I assume the output file is only generated after the experiment has ended?

Thanks & happy new year :slight_smile:

Zora

Hi There,

You are correct that the output file is not generated untill the experiment has ended. How complex is the analysis? if it is simple (like showing mean between 2 conditions) you can keep track of data within your experiment.

e.g.

Begin experiment tab:

rts_cond1=[]
rts_cond2=[]

End routine tab:

rts_cond1.append(thisRT)
rts_cond2.append(thisRT)

In your last routine:

np.average(rts_cond1)
np.average(rts_cond2)

If you want to show the data as a graph you can use matplotlib.

Hope this helps,

Becca
ps. if you want to do this online at all you will need some edits

Hi Becca,

thank you for your help! I’ve now written the code below, do you maybe have a minute to check if it’s correct? I’ve never coded in python before… It’s probably very inefficient, but I just need it to work :smiley:

Zora

## PREPARATION
## check if test was invalid: if rt was < 300ms for > 10% of answers, the test is invalid
invalidAnswers = 0
for i in rts_36:
    if rts_36[i] < 0.3:
        invalidAnswers = invalidAnswers + 1
for i in rts_47:
    if rts_47[i] < 0.3:
        invalidAnswers = invalidAnswers + 1

## remove any answers the participant needed > 10s for 
for i in rts_36:
    if rts_36[i] > 10:
        del rts_36[i]

for i in rts_47:
    if rts_47[i] > 10:
        del rts_47[i]

for i in rts_block3:
    if rts_block3[i] > 10:
        del rts_block3[i]

for i in rts_block4:
    if rts_block4[i] > 10:
        del rts_block4[i]

for i in rts_block6:
    if rts_block6[i] > 10:
        del rts_block6[i]

for i in rts_block7:
    if rts_block7[i] > 10:
        del rts_block7[i]

## calculate sd of all rt times in blocks 3 and 6
sd36 = stdev(rts_36)

## calculate sd of all rt times in blocks 4 and 7
sd47 = stdev(rts_47)

## calculate average rt for each block (3, 4, 6, 7)
avg3 = np.average(rts_block3)
avg4 = np.average(rts_block4)
avg6 = np.average(rts_block6)
avg7 = np.average(rts_block7)

## difference of avg rt block 6 and 3 & divide by sd for standardization
d63 = (avg6 - avg3) / sd36

## difference of avg rt block 7 and 4 & divide by sd for std.
d74 = (avg7 - avg4) / sd47

## calculate mean of the two difference scores => strength of implicit association
finalScore = (d63 + d74) / 2

## DEFINE MESSAGE
## if the value is positive, the association tested in blocks 3/4 is stronger
## (lower reaction times)
## if the value is negative, the association tested in blocks 6/7 is stronger

if finalScore >= 0:
    msg = 'Your responses suggested an automatic association between the concepts "Male" and "Science" and between "Female" and "Liberal Arts".'
elif finalScore < 0:
    msg = 'Your responses suggested an automatic association between the concepts "Female" and "Science" and between "Male" and "Liberal Arts".'

if (invalidAnswers / (len(rts_36) + len(rts_47))) > 0.1:
    msg = 'The test is invalid. You responded too quickly.'

Hi Zora,

Please could you possibly format the code blocks to make it easier to read indentation and so on? you can highlight and use the </> symbol to do that.

A couple of notes:

For loops in python don’t quite work how I think you are expecting them to there:
e.g. you probably want

for i in rts_36:
    if rts_36[i] <.3:
        invalidAnswers = invalidAnswers +1

to read as

for thisRT in rts_36:
    if thisRT <.3:
        invalidAnswers +=1

For removing items from a list in python you probably want something like .pop https://www.programiz.com/python-programming/methods/list/pop

For stdev you will want to use the numpy.std https://numpy.org/doc/stable/reference/generated/numpy.std.html

For a general resource on anlysing data in python this might be helpful https://workshops.psychopy.org/3days/coding/arraysAndPlotting_Dublin.html#plottingposner
Hope this helps,
Becca

Hi Becca,

thank you!
I now changed the code to the following, but I have a question about .pop

thisRT is the value and not the index, right? So rts_36.pop(thisRT) wouldn’t work because .pop works with the index but thisRT describes an element. So would this be correct: rts_36.pop(rts_36.index(thisRT)) ? Or could I use rts_36.remove(thisRT) ?

## PREPARATION
## check if test was invalid: if rt was < 300ms for > 10% of answers, the test is invalid
invalidAnswers = 0
for thisRT in rts_36:
    if thisRT < .3:
        invalidAnswers += 1
for thisRT in rts_47:
    if thisRT < .3:
        invalidAnswers += 1

## remove any answers the participant needed > 10s for 
for thisRT in rts_36:
    if thisRT > 10:
        del thisRT

for thisRT in rts_47:
    if thisRT > 10:
        del thisRT

for thisRT in rts_block3:
    if thisRT > 10:
        del thisRT

for thisRT in rts_block4:
    if thisRT > 10:
        del thisRT

for thisRT in rts_block6:
    if thisRT > 10:
        del thisRT

for thisRT in rts_block7:
    if thisRT > 10:
        del thisRT

## calculate sd of all rt times in blocks 3 and 6
sd36 = numpy.std(rts_36)

## calculate sd of all rt times in blocks 4 and 7
sd47 = numpy.std(rts_47)

## calculate average rt for each block (3, 4, 6, 7)
avg3 = np.average(rts_block3)
avg4 = np.average(rts_block4)
avg6 = np.average(rts_block6)
avg7 = np.average(rts_block7)

## difference of avg rt block 6 and 3 & divide by sd for standardization
d63 = (avg6 - avg3) / sd36

## difference of avg rt block 7 and 4 & divide by sd for std.
d74 = (avg7 - avg4) / sd47

## calculate mean of the two difference scores => strength of implicit association
finalScore = (d63 + d74) / 2

## DEFINE MESSAGE
## if the value is positive, the association tested in blocks 3/4 is stronger
## (lower reaction times)
## if the value is negative, the association tested in blocks 6/7 is stronger

if finalScore >= 0:
    msg = 'Your responses suggested an automatic association between the concepts "Male" and "Science" and between "Female" and "Liberal Arts".'
elif finalScore < 0:
    msg = 'Your responses suggested an automatic association between the concepts "Female" and "Science" and between "Male" and "Liberal Arts".'

if (invalidAnswers / (len(rts_36) + len(rts_47))) > 0.1:
    msg = 'The test is invalid. You responded too quickly.'

Hi Zora,

Yes you are right about pop.

you would want something like:

myList=[1, 2, 3]

for index, item in enumerate(myList):
    if item==2:
        myList.pop(index)

Hi Becca,

as soon as I add this, I get a syntax error - but I don’t see what’s wrong. Do you have an idea?

for index, thisRT in enumerate(rts_36):
    if thisRT > 10:
        rts_36.pop(index)

whats your syntax error?

in the java script box, see screenshot.

If you click run you will get a more informative error in the std output window of your runner view :slight_smile: Give it a go and it should give something there!

Becca

oops, thanks. The error is:

sd36 = numpy.std(rts_36)
NameError: name 'numpy' is not defined

Do I have to include a library or something? If yes, how and where?

I fixed it, thank you so much for all your help Becca! :slight_smile:

woo! no problem - for future users reading this thread - ‘numpy’ is imported as ‘np’ in psychopy - so we use np.average etc.:slight_smile:

Zora please could you mark the coresponding solution to your question for future readers?

Thanks,
!

Becca

Hi Becca, sorry, I have one last question - if I want to run the experiment online, I can’t use np.average and np.std. Can I just use the standard python functions mean() and pstdev() instead?
Or which edits do I need to make (that you noted in your first reply)?

Hi,

If you want to run online you will need to set code type to be both and use ‘average’ instead of np.average on your JS side.

Then add a code component at the start of your experiment called ‘JS_code’, set code type to be ‘JS’ and in the ‘begin experiment’ tab copy the ‘average’ function outlined in the crib sheet https://docs.google.com/document/d/13jp0QAqQeFlYSjeZS0fDInvgaDzBXjGQNe4VNKbbNHQ/edit

For stdev and plotting you would need to look more into what the javascript equivilents of these are (e.g. https://mathjs.org/docs/reference/functions/std.html#:~:text=Compute%20the%20standard%20deviation%20of,sqrt(variance(A))%20.&text=‘unbiased’%20(default)%20The,divided%20by%20(n%20%2D%201))