Present ratingScale and movieStim2 in the same window to measure and record continuous rating

Using Psychopy2, I am trying to present a movie using moviestim2 and a rating scale using ratingScale in the same window concurrently so that participants can continuously rate the video in terms of their subjective experience.

However, I have found that whenever the same window is used to do this, the video becomes very dark and flickers lots.

When I present them seperately and using different windows this is not a problem.

If anyone has come across this issue and overcome it, I would appreciate some advice.

Here is the code I have been working on:

filmDict = data.TrialHandler(nReps = 1, method = 'sequential', trialList = data.importConditions('filmList.csv'), name = 'filmList') # dictionary containing film names
TimingsDict ={'Participant_number': part_number} # dictionary for the data to be entered into the 'timings.csv' file

#Creates fullscreen black window for stimuli to be presented on throughout task.
win = visual.Window([1024, 768], fullscr = False, allowGUI = True,
                    units = "pix", color = (1,1,1))
# Creates text stimuli to be updated on each trial.
stim = visual.TextStim(win, "")

#Presents ready screen at the start of practice trials.
stim.setText("Press Enter to begin.")
stim.color = (-1,-1,-1)
stim.draw()
win.flip()

#create a RatingScale object:
myRatingScale = visual.RatingScale(win, choices=['Uncertainty','Certainty']) # creates rating scale 

# the item to-be-rated or respond to:
myItem = visual.TextStim(win, text="Please continuously rate the amount of uncertainty felt", height=.12, units='norm')

event.clearEvents()
myItem.draw()
myRatingScale.draw()
win.flip()
if event.getKeys(['escape']):
    core.quit()

#Start a clock right before the experiment starts
tasktime = core.Clock()
tasktime.reset()

for film in filmDict:
    start =time.time()
    #videoStart = strftime("%H:%M:%S", gmtime())
    videoStart = tasktime.getTime()
    mov = visual.MovieStim2(win, film[videoCondition], size=(564, 360), flipVert=False, flipHoriz=False, loop=False)
    while mov.status != visual.FINISHED:
        mov.draw()
        win.flip()
    #videoEnd = strftime("%H:%M:%S", gmtime())
    videoEnd = tasktime.getTime()
    #qEnd=strftime("%H:%M:%S", gmtime())
    qEnd = tasktime.getTime()
    end =time.time()
    trial_duration = (end-start)

Try using Slider slider instead of RatingScale ratingscale. It’s more efficient in rendering, has fewer settings, and more flexible too.

Oh, if you’re in Coder then the docs are here:
https://www.psychopy.org/api/visual/slider.html

In particular slider allows access to .markerPos and .rating values where the form is available continuously (as son as the mouse is clicked somewhere) and the latter is changed each time the mouse is released

Thanks for that Jon. I will need to download Psychopy3 to try this.

Do you know whether the slider can be controlled using the wheel of the mouse? I have made the ratingScale work with the left and right keys to continuously record but I would much prefer to use the wheel of the mouse instead when I try the Slider.

Hi @BronteMckeown, you can control the slider with the mouse wheel using a code component. Note, you will first have to set the marker position for this to work, perhaps in a neutral position

# Begin Routine
slider.markerPos = 0

# Each Frame
slider.markerPos += mouse.getWheelRel()[1]

@dvbridges Thank you for that- it worked really well. I can now control the slider with the wheel of the mouse. However, when I move the slider with the wheel it doesn’t seem to be updating the rating as when I print getRating(), it prints none until I use the mouse to click. Do you know a way to make the mouse wheel actually change the rating which is being stored rather than just the position of the slider?

Here is my code currently:

from psychopy import gui, data, core, visual, event
import csv
import time
from time import localtime, strftime, gmtime
from datetime import datetime

from psychopy.iohub import launchHubServer
from psychopy.iohub.constants import EventConstants

# Make a dictionary to store information from the dialogue box
inputbox = {'expdate': datetime.now().strftime('%Y%m%d_%H%M'),'part_number':'','videoCondition':''}

# Create the dialogue box
# In the dialogue box you enter the participant number and the video condition (i.e. the Header of the column of video lists in the csvFile)
dlg=gui.DlgFromDict(inputbox, title = 'Input participation info',
                  	fixed='expdate',
                  	order=['expdate', 'part_number','videoCondition'])

# If the user doesn't press ok, the programme will quit and inform user.
if not dlg.OK:
	print ("User exited")
	core.quit()

# Store participant details as variables 
part_number = inputbox['part_number']
videoCondition = inputbox['videoCondition']
expdate = inputbox['expdate']

# Create participant timings csv
tcsvFile = open('{}_{}_{}_{}.csv'.format(part_number, expdate,videoCondition,'timings'),'w')
fieldnames = ['Participant_number', 'videoName','Video_startTime','Video_endTime', 'TrialDuration']
twriter = csv.DictWriter(tcsvFile, fieldnames)
twriter.writeheader()

# Presents films in order from csv file containing list of film names
filmDict = data.TrialHandler(nReps = 1, method = 'sequential', trialList = data.importConditions('filmList.csv'), name = 'filmList') # dictionary containing film names
TimingsDict ={'Participant_number': part_number} # dictionary for the data to be entered into the 'timings.csv' file

# Presents films in order from csv file containing list of film names
filmDict = data.TrialHandler(nReps = 1, method = 'sequential', trialList = data.importConditions('filmList.csv'), name = 'filmList') # dictionary containing film names

# Creates fullscreen black window for stimuli to be presented on throughout task.
win = visual.Window([1024, 768], fullscr = False, allowGUI = True, color = (1,1,1))
                    


# Need instruction screen

# Create sliding scale to take continuous rating of uncertainty while movie plays
slidingscale = visual.Slider(win, ticks = [0,100], labels = ['certain', 'uncertain'], pos = (0.0, -0.7), granularity = 0)

# Start a clock right before the experiment starts
tasktime = core.Clock()
tasktime.reset()

# Name mouse to be able to use for continuous rating below
mouse = event.Mouse()

# Loops round and presents every movie in filmDict
for film in filmDict:
    start =time.time()
    videoStart = tasktime.getTime()
    # creates movie 
    mov = visual.MovieStim3(win, film[videoCondition], size=(564, 360), flipVert=False, flipHoriz=False, loop=False)
    # sets position of marker to 0 
    slidingscale.markerPos = 50
    # sets rating scale frame to 0 for calculation below 
    rtscaleframe = 0
    while mov.status != visual.FINISHED:
        slidingscale.markerPos += mouse.getWheelRel()[1]
        slidingscale.draw()
        mov.draw()
        win.flip()
        if rtscaleframe % 60 == 0:
            rating = slidingscale.getRating()
            print (rating)

Sure, so getRating() gets the final rating that was given, rather than the position of the marker. If you want to print the current rating to the screen, you could use:

print(slider.markerPos)