I’ve used PsychoPy builder for quite a few experiments, but I’m a little stuck with the task I’m building at the moment (and unsure whether it can be realised through the GUI). I’m running v1.85.2 on Windows 10.
We’re running a two-part experiment. In part one, our participants navigate through a virtual hedge-maze, learning to turn left or right at 8 junctions. At each junction there’s a unique landmark present, and in part 2 we want to test participants’ ability to remember the order in which they encountered these landmarks. Here’s where PsychoPy comes in.
Using the builder view, I’ve got the 8 landmarks presented on one screen as image components, and under each image I’ve got a rating scale labelled with category choices from 1-8 (screenshot below). The idea here is that participants use the rating scale to indicate which junction the landmark was at in the hedge-maze. I have single click responses on all rating scales, which are presented indefinitely along with the image components. Participants are instructed to press space when they’ve responded on all 8 scales to end the routine.
There’s two things I can’t achieve:
I’d like to data output to print a correct answer from each rating scale (did the response on the rating scale match the junction that the landmark was at?). Is there a way of specifying a correct answer on a rating scale?
It’s currently possible for participants to end the routine before they’ve made a response on all 8 scales. Is it possible to tell the keyboard component of the routine to ignore presses on space until responses on all 8 scales have been recorded?
Looks like a nice study. Yes, it is possible to do every thing you need in Builder although you might need a little code inserted via a Code Component.
Remove the keyboard component. It doesn’t have the flexibility you need here, and so we need to handle the key checking in code. Insert a Code Component, and in the Each frame tab, put something like this:
keys = event.getKeys()
# need to manually check for escape, as our key checking will interfere with
# Builder's escape check:
if 'escape' in keys:
core.quit()
if 'space' in keys:
# check how many ratings have been completed:
completed_ratings = 0
for scale in [rating_1, rating_2, rating_3, rating_4, rating_5, rating_6, rating_7, rating_8]:
if scale.getRating() is not None:
completed_ratings = completed_ratings + 1
if completed_ratings == 8:
continueRoutine = False # end now
Thanks for your quick reply. As you suggested, I removed the keyboard component, and copied the code you have kindly provided into the each frame tab of a code component. I’ve also changed the names of the scales (e.g. rating_1) so they match the names of the scales in my experiment. Unfortunately I can still press space to terminate the routine before all 8 scales have been answered. I guess PsychoPy isn’t using the counter for the completed ratings for some reason - becasue I get no error messages as I exit the experiment. Do you have any idea what the issue might be?
Sorry for the long delay, not sure if you still need a response…
On the contrary, it must be using the counter, or else it wouldn’t end the routine (as the space will only have an effect if the counter reaches 8). So the problem must be that the counter reaches 8 even though the ratings haven’t been completed. I’m not familiar with the rating scale, so I’d suggest that you need to do some debugging to check what scale.getRating() actually returns for scales that haven’t been completed. e.g. insert the print line like this:
for scale in [rating_1, rating_2, rating_3, rating_4, rating_5, rating_6, rating_7, rating_8]:
print(scale.getRating())
if scale.getRating() is not None:
completed_ratings = completed_ratings + 1
But actually while typing that out, I think I saw what the problem might be: there should have been brackets after .getRating()
[an issue with just typing out code that hasn’t actually been run…]
I’ve amended the original code above accordingly. Try it again and see if it works. If it still doesn’t, insert that print() line for debugging purposes.
Thanks very much for coming back to me. We’re still planning to run this task in PsyhcoPy, so the time you have spent helping with the experiment is very much appreciated. I’m happy to report that the amended code has made the counter function correctly, so we’re just about set.
May I ask another question, please? Currently our participants could input the same rating into multiple rating scales (e.g., they could answer 1 on each and every scale). Is it possible to prevent the end routine until all rating scales have a different answer?*
Best,
Matt
*Please don’t read this as a request for you to spend hours writing code on my behalf (in fact, I feel a little guilty that you’ve already written code because I’m sure you have much better things to do!), I’m just wondering how plausible it is before I bug technical colleagues with a request.
Something like the code below. Instead of just counting responses, we enter a 1 into the slot in an array corresponding to its actual value. Only end the trial if the sum of those values = 8. i.e. that would indicate that there were eight unique values. e.g. if two scales had answer 1, then slot 1 would be set to 1 twice, and some other slot would be zero, so the sum would be 7.
if 'space' in keys:
# check that all ratings have been completed, and that all 8 possible options
# have been chosen:
completed_ratings = np.zeros(9) # a numpy array of nine zeros (ignore the zeroth)
for scale in [rating_1, rating_2, rating_3, rating_4, rating_5, rating_6, rating_7, rating_8]:
rating_value = scale.getRating()
if rating_value is not None:
completed_ratings[int(rating_value)] = 1
if int(completed_ratings.sum()) == 8: # all eight values have been used once
continueRoutine = False # end now
I’m trying to make quite the same thing with a continue button but it does not work. The button is either enabled once one of the slider is completed, or not at all.
I tried the following codes :
First attempt (resulting in the button to be enabled once only one of the sliders has been completed)
in Begin experiment
ContinueButton.draw()
for slider in [slider_1, slider_2, slider_3, slider_4, slider_5, slider_6, slider_7, slider_8]:
if slider.getRating() is not None:
completed_ratings = completed_ratings+1
if completed_ratings == 8:
ContinueButton.buttonEnabled = True
if ContinueButton.buttonSelected:
continueRoutine = False
Second attemt (resulting in the button to never be enabled)
in Begin routine
ContinueButton.draw()
if ContinueButton.draw() == True:
completed_ratings = 0
for slider in [slider_1, slider_2, slider_3, slider_4, slider_5, slider_6, slider_7, slider_8]:
if slider.getRating() is not None:
completed_ratings = completed_ratings+1
if completed_ratings == 8:
ContinueButton.buttonEnabled = True
if ContinueButton.buttonSelected:
continueRoutine = False