Doesn't accept blank duration

I want my routine to end only upon demand (pressing a certain key), However, pschopy doesn’t allow me to leave the ‘‘duration’’ as blank, and I get the following message:

  File "C:\Users\Usuario\Desktop\PsychoPy2\lib\site-packages\psychopy\experiment\components\sound\__init__.py", line 65, in writeInitCode
    if float(inits['stopVal'].val) > 2:
ValueError: could not convert string to float: None

If i determine a duration time (any duration time), the experiment works fine.
Anyone knows how to solve this issue?

Thanks in advance

Hi @pasoneto, this problem was answered in this post.. However, you could also update your version of PsychoPy to 1.90.1, as this has the fix included.

Thank you very much, @dvbridges

hi @dcbridges,

I am using version 1.90.1 and I just encountered this exact bug. The fix outlined in the previous post worked (Problem with the offset of a sound component worked), but the bug is still clearly there in version 1.90.1. Any ideas?

Also as a note, the sound components are still not playing even with the above fix (i.e. the experiment starts but the sound still does not play). We are encountering the following error message:

ValueError: non-broadcastable output operand with shape (128,1) doesn’t match the broadcast shape (128,2)

Does this have anything to do with the above bug? We plan on posting this issue in a new post with the relevant background info but I also figured I would reply to this post to let you know that this bug is still seemingly apparent in version 1.90.1.

Thanks!

Hi @rosem09, these bugs are fixed in recent releases of PsychoPy. I think the ValueError you are seeing relates to a mismatch in array sizes resulting from PsychoPY attempting to append a mono track to a stereo track. In Psychopy 3, we added a preference to “Force stereo”, which should fix your issue.

Hi @dvbridges. Thanks for your quick response. So before I saw your response, we realized we were using a stereo track and figured Psychopy 1.90.1 could only read mono tracks.

We thus changed all of our tracks from stereo to mono and the experiment plays with the appropriate sounds and theoretically works but it still requires a specification of the stop duration time. Is this part only updated in Psychopy3? If this helps, here is our code (sorry we are new to Psychopy so I apologize in advance for the unattractive code):

#!/usr/bin/env python

-- coding: utf-8 --

“”"
This experiment was created using PsychoPy2 Experiment Builder (v1.90.1),
on Mon Oct 1 08:07:13 2018
If you publish work using this script please cite the PsychoPy publications:
Peirce, JW (2007) PsychoPy - Psychophysics software in Python.
Journal of Neuroscience Methods, 162(1-2), 8-13.
Peirce, JW (2009) Generating stimuli for neuroscience using PsychoPy.
Frontiers in Neuroinformatics, 2:10. doi: 10.3389/neuro.11.010.2008
“”"

from future import absolute_import, division
from psychopy import locale_setup, sound, gui, visual, core, data, event, logging, clock
from psychopy.constants import (NOT_STARTED, STARTED, PLAYING, PAUSED,
STOPPED, FINISHED, PRESSED, RELEASED, FOREVER)
import numpy as np # whole numpy lib is available, prepend ‘np.’
from numpy import (sin, cos, tan, log, log10, pi, average,
sqrt, std, deg2rad, rad2deg, linspace, asarray)
from numpy.random import random, randint, normal, shuffle
import os # handy system and path functions
import sys # to get file system encoding

Ensure that relative paths start from the same directory as this script

_thisDir = os.path.dirname(os.path.abspath(file))
os.chdir(_thisDir)

Store info about the experiment session

expName = ‘TestTestTest2’ # from the Builder filename that created this script
expInfo = {‘participant’: ‘’, ‘session’: ‘001’}
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

Data file name stem = absolute path + name; later add .psyexp, .csv, .log, etc

filename = thisDir + os.sep + u’data/%s%s_%s’ % (expInfo[‘participant’], expName, expInfo[‘date’])

An ExperimentHandler isn’t essential but helps with data saving

thisExp = data.ExperimentHandler(name=expName, version=’’,
extraInfo=expInfo, runtimeInfo=None,
originPath=None,
savePickle=True, saveWideText=True,
dataFileName=filename)

save a log file for detail verbose info

logFile = logging.LogFile(filename+’.log’, level=logging.EXP)
logging.console.setLevel(logging.WARNING) # this outputs to the screen, not a file

endExpNow = False # flag for ‘escape’ or other condition => quit the exp

Start Code - component code to be run before the window creation

Setup the Window

win = visual.Window(
size=(1024, 768), fullscr=True, screen=0,
allowGUI=False, allowStencil=False,
monitor=‘testMonitor’, color=[0,0,0], colorSpace=‘rgb’,
blendMode=‘avg’, useFBO=True)

store frame rate of monitor if we can measure it

expInfo[‘frameRate’] = win.getActualFrameRate()
if expInfo[‘frameRate’] != None:
frameDur = 1.0 / round(expInfo[‘frameRate’])
else:
frameDur = 1.0 / 60.0 # could not measure, so guess

Initialize components for Routine “trial”

trialClock = core.Clock()
MaleQ = sound.Sound(‘A’, secs=-1)
MaleQ.setVolume(1)
image = visual.ImageStim(
win=win, name=‘image’,
image=‘sin’, mask=None,
ori=1.0, pos=(0, 0), size=None,
color=[1,1,1], colorSpace=‘rgb’, opacity=1,
flipHoriz=False, flipVert=False,
texRes=128, interpolate=True, depth=-2.0)
FemAnswer = sound.Sound(‘A’, secs=-1)
FemAnswer.setVolume(1)

Create some handy timers

globalClock = core.Clock() # to track the time since experiment started
routineTimer = core.CountdownTimer() # to track time remaining of each (non-slip) routine

set up handler to look after randomisation of conditions etc

Block1 = data.TrialHandler(nReps=1, method=‘sequential’,
extraInfo=expInfo, originPath=-1,
trialList=data.importConditions(‘conditionTestRunTrainingBlock1_TEST.xlsx’),
seed=None, name=‘Block1’)
thisExp.addLoop(Block1) # add the loop to the experiment
thisBlock1 = Block1.trialList[0] # so we can initialise stimuli with some values

abbreviate parameter names if possible (e.g. rgb = thisBlock1.rgb)

if thisBlock1 != None:
for paramName in thisBlock1:
exec(’{} = thisBlock1[paramName]’.format(paramName))

for thisBlock1 in Block1:
currentLoop = Block1
# abbreviate parameter names if possible (e.g. rgb = thisBlock1.rgb)
if thisBlock1 != None:
for paramName in thisBlock1:
exec(’{} = thisBlock1[paramName]’.format(paramName))

# ------Prepare to start Routine "trial"-------
t = 0
trialClock.reset()  # clock
frameN = -1
continueRoutine = True
# update component parameters for each repeat
Forward001 = event.BuilderKeyResponse()
MaleQ.setSound(soundFileQCase, secs=4)
image.setOri(0)
image.setImage(imageFileCase)
FemAnswer.setSound(soundFileACase, secs=6)
# keep track of which components have finished
trialComponents = [Forward001, MaleQ, image, FemAnswer]
for thisComponent in trialComponents:
    if hasattr(thisComponent, 'status'):
        thisComponent.status = NOT_STARTED

# -------Start Routine "trial"-------
while continueRoutine:
    # get current time
    t = trialClock.getTime()
    frameN = frameN + 1  # number of completed frames (so 0 is the first frame)
    # update/draw components on each frame
    
    # *Forward001* updates
    if t >= 0 and Forward001.status == NOT_STARTED:
        # keep track of start time/frame for later
        Forward001.tStart = t
        Forward001.frameNStart = frameN  # exact frame index
        Forward001.status = STARTED
        # keyboard checking is just starting
        win.callOnFlip(Forward001.clock.reset)  # t=0 on next screen flip
        event.clearEvents(eventType='keyboard')
    if Forward001.status == STARTED:
        theseKeys = event.getKeys()
        
        # check for quit:
        if "escape" in theseKeys:
            endExpNow = True
        if len(theseKeys) > 0:  # at least one key was pressed
            Forward001.keys = theseKeys[-1]  # just the last key pressed
            Forward001.rt = Forward001.clock.getTime()
            # a response ends the routine
            continueRoutine = False
    # start/stop MaleQ
    if t >= 0 and MaleQ.status == NOT_STARTED:
        # keep track of start time/frame for later
        MaleQ.tStart = t
        MaleQ.frameNStart = frameN  # exact frame index
        MaleQ.play()  # start the sound (it finishes automatically)
    frameRemains = 0 + 4- win.monitorFramePeriod * 0.75  # most of one frame period left
    if MaleQ.status == STARTED and t >= frameRemains:
        MaleQ.stop()  # stop the sound (if longer than duration)
    
    # *image* updates
    if t >= 0 and image.status == NOT_STARTED:
        # keep track of start time/frame for later
        image.tStart = t
        image.frameNStart = frameN  # exact frame index
        image.setAutoDraw(True)
    # start/stop FemAnswer
    if t >= 4 and FemAnswer.status == NOT_STARTED:
        # keep track of start time/frame for later
        FemAnswer.tStart = t
        FemAnswer.frameNStart = frameN  # exact frame index
        FemAnswer.play()  # start the sound (it finishes automatically)
    frameRemains = 4 + 6- win.monitorFramePeriod * 0.75  # most of one frame period left
    if FemAnswer.status == STARTED and t >= frameRemains:
        FemAnswer.stop()  # stop the sound (if longer than duration)
    
    # check if all components have finished
    if not continueRoutine:  # a component has requested a forced-end of Routine
        break
    continueRoutine = False  # will revert to True if at least one component still running
    for thisComponent in trialComponents:
        if hasattr(thisComponent, "status") and thisComponent.status != FINISHED:
            continueRoutine = True
            break  # at least one component has not yet finished
    
    # check for quit (the Esc key)
    if endExpNow or event.getKeys(keyList=["escape"]):
        core.quit()
    
    # refresh the screen
    if continueRoutine:  # don't flip if this routine is over or we'll get a blank screen
        win.flip()

# -------Ending Routine "trial"-------
for thisComponent in trialComponents:
    if hasattr(thisComponent, "setAutoDraw"):
        thisComponent.setAutoDraw(False)
# check responses
if Forward001.keys in ['', [], None]:  # No response was made
    Forward001.keys=None
Block1.addData('Forward001.keys',Forward001.keys)
if Forward001.keys != None:  # we had a response
    Block1.addData('Forward001.rt', Forward001.rt)
MaleQ.stop()  # ensure sound has stopped at end of routine
FemAnswer.stop()  # ensure sound has stopped at end of routine
# the Routine "trial" was not non-slip safe, so reset the non-slip timer
routineTimer.reset()
thisExp.nextEntry()

completed 1 repeats of ‘Block1’

these shouldn’t be strictly necessary (should auto-save)

thisExp.saveAsWideText(filename+’.csv’)
thisExp.saveAsPickle(filename)
logging.flush()

make sure everything is closed down

thisExp.abort() # or data files will save again on exit
win.close()
core.quit()

Thanks, you can amend your code so that it is all surrounded by backticks? This will help us to read your code and offer suggestions to fix. If you are only using Builder then I suggest you update to Psychopy 3.

Okay here it is. As a note, this was created in builder (this is my first block of my experiment out of 5 plus blocks). I decided to use version 1.90.1 as I was told this version was the most secure (although at that time the person did not know I would be using audio files). Although this simple block was created using builder I am hoping I can learn to code in Python as I do not think that I will be able to create my entire experiment in builder as it will become much more complicated.

# Store info about the experiment session
expName = 'TestTestTest2'  # from the Builder filename that created this script
expInfo = {'participant': '', 'session': '001'}
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

# Data file name stem = absolute path + name; later add .psyexp, .csv, .log, etc
filename = _thisDir + os.sep + u'data/%s_%s_%s' % (expInfo['participant'], expName, expInfo['date'])

# An ExperimentHandler isn't essential but helps with data saving
thisExp = data.ExperimentHandler(name=expName, version='',
    extraInfo=expInfo, runtimeInfo=None,
    originPath=None,
    savePickle=True, saveWideText=True,
    dataFileName=filename)
# save a log file for detail verbose info
logFile = logging.LogFile(filename+'.log', level=logging.EXP)
logging.console.setLevel(logging.WARNING)  # this outputs to the screen, not a file

endExpNow = False  # flag for 'escape' or other condition => quit the exp

# Start Code - component code to be run before the window creation

# Setup the Window
win = visual.Window(
    size=(1024, 768), fullscr=True, screen=0,
    allowGUI=False, allowStencil=False,
    monitor='testMonitor', color=[0,0,0], colorSpace='rgb',
    blendMode='avg', useFBO=True)
# store frame rate of monitor if we can measure it
expInfo['frameRate'] = win.getActualFrameRate()
if expInfo['frameRate'] != None:
    frameDur = 1.0 / round(expInfo['frameRate'])
else:
    frameDur = 1.0 / 60.0  # could not measure, so guess

# Initialize components for Routine "trial"
trialClock = core.Clock()
MaleQ = sound.Sound('A', secs=-1)
MaleQ.setVolume(1)
image = visual.ImageStim(
    win=win, name='image',
    image='sin', mask=None,
    ori=1.0, pos=(0, 0), size=None,
    color=[1,1,1], colorSpace='rgb', opacity=1,
    flipHoriz=False, flipVert=False,
    texRes=128, interpolate=True, depth=-2.0)
FemAnswer = sound.Sound('A', secs=-1)
FemAnswer.setVolume(1)

# Create some handy timers
globalClock = core.Clock()  # to track the time since experiment started
routineTimer = core.CountdownTimer()  # to track time remaining of each (non-slip) routine 

# set up handler to look after randomisation of conditions etc
Block1 = data.TrialHandler(nReps=1, method='sequential', 
    extraInfo=expInfo, originPath=-1,
    trialList=data.importConditions('conditionTestRunTrainingBlock1_TEST.xlsx'),
    seed=None, name='Block1')
thisExp.addLoop(Block1)  # add the loop to the experiment
thisBlock1 = Block1.trialList[0]  # so we can initialise stimuli with some values
# abbreviate parameter names if possible (e.g. rgb = thisBlock1.rgb)
if thisBlock1 != None:
    for paramName in thisBlock1:
        exec('{} = thisBlock1[paramName]'.format(paramName))

for thisBlock1 in Block1:
    currentLoop = Block1
    # abbreviate parameter names if possible (e.g. rgb = thisBlock1.rgb)
    if thisBlock1 != None:
        for paramName in thisBlock1:
            exec('{} = thisBlock1[paramName]'.format(paramName))
    
    # ------Prepare to start Routine "trial"-------
    t = 0
    trialClock.reset()  # clock
    frameN = -1
    continueRoutine = True
    # update component parameters for each repeat
    Forward001 = event.BuilderKeyResponse()
    MaleQ.setSound(soundFileQCase, secs=4)
    image.setOri(0)
    image.setImage(imageFileCase)
    FemAnswer.setSound(soundFileACase, secs=6)
    # keep track of which components have finished
    trialComponents = [Forward001, MaleQ, image, FemAnswer]
    for thisComponent in trialComponents:
        if hasattr(thisComponent, 'status'):
            thisComponent.status = NOT_STARTED
    
    # -------Start Routine "trial"-------
    while continueRoutine:
        # get current time
        t = trialClock.getTime()
        frameN = frameN + 1  # number of completed frames (so 0 is the first frame)
        # update/draw components on each frame
        
        # *Forward001* updates
        if t >= 0 and Forward001.status == NOT_STARTED:
            # keep track of start time/frame for later
            Forward001.tStart = t
            Forward001.frameNStart = frameN  # exact frame index
            Forward001.status = STARTED
            # keyboard checking is just starting
            win.callOnFlip(Forward001.clock.reset)  # t=0 on next screen flip
            event.clearEvents(eventType='keyboard')
        if Forward001.status == STARTED:
            theseKeys = event.getKeys()
            
            # check for quit:
            if "escape" in theseKeys:
                endExpNow = True
            if len(theseKeys) > 0:  # at least one key was pressed
                Forward001.keys = theseKeys[-1]  # just the last key pressed
                Forward001.rt = Forward001.clock.getTime()
                # a response ends the routine
                continueRoutine = False
        # start/stop MaleQ
        if t >= 0 and MaleQ.status == NOT_STARTED:
            # keep track of start time/frame for later
            MaleQ.tStart = t
            MaleQ.frameNStart = frameN  # exact frame index
            MaleQ.play()  # start the sound (it finishes automatically)
        frameRemains = 0 + 4- win.monitorFramePeriod * 0.75  # most of one frame period left
        if MaleQ.status == STARTED and t >= frameRemains:
            MaleQ.stop()  # stop the sound (if longer than duration)
        
        # *image* updates
        if t >= 0 and image.status == NOT_STARTED:
            # keep track of start time/frame for later
            image.tStart = t
            image.frameNStart = frameN  # exact frame index
            image.setAutoDraw(True)
        # start/stop FemAnswer
        if t >= 4 and FemAnswer.status == NOT_STARTED:
            # keep track of start time/frame for later
            FemAnswer.tStart = t
            FemAnswer.frameNStart = frameN  # exact frame index
            FemAnswer.play()  # start the sound (it finishes automatically)
        frameRemains = 4 + 6- win.monitorFramePeriod * 0.75  # most of one frame period left
        if FemAnswer.status == STARTED and t >= frameRemains:
            FemAnswer.stop()  # stop the sound (if longer than duration)
        
        # check if all components have finished
        if not continueRoutine:  # a component has requested a forced-end of Routine
            break
        continueRoutine = False  # will revert to True if at least one component still running
        for thisComponent in trialComponents:
            if hasattr(thisComponent, "status") and thisComponent.status != FINISHED:
                continueRoutine = True
                break  # at least one component has not yet finished
        
        # check for quit (the Esc key)
        if endExpNow or event.getKeys(keyList=["escape"]):
            core.quit()
        
        # refresh the screen
        if continueRoutine:  # don't flip if this routine is over or we'll get a blank screen
            win.flip()
    
    # -------Ending Routine "trial"-------
    for thisComponent in trialComponents:
        if hasattr(thisComponent, "setAutoDraw"):
            thisComponent.setAutoDraw(False)
    # check responses
    if Forward001.keys in ['', [], None]:  # No response was made
        Forward001.keys=None
    Block1.addData('Forward001.keys',Forward001.keys)
    if Forward001.keys != None:  # we had a response
        Block1.addData('Forward001.rt', Forward001.rt)
    MaleQ.stop()  # ensure sound has stopped at end of routine
    FemAnswer.stop()  # ensure sound has stopped at end of routine
    # the Routine "trial" was not non-slip safe, so reset the non-slip timer
    routineTimer.reset()
    thisExp.nextEntry()
    
# completed 1 repeats of 'Block1'

# these shouldn't be strictly necessary (should auto-save)
thisExp.saveAsWideText(filename+'.csv')
thisExp.saveAsPickle(filename)
logging.flush()
# make sure everything is closed down
thisExp.abort()  # or data files will save again on exit
win.close()
core.quit()

Well Builder is very flexible and has the code component should you need some custom functionality. This would be an easier introduction to coding for experiments.

So, with your experiment, what error are you receiving when the duration of your sound is not specified?

Yes I should have clarified that I plan on using Builder to introduce myself to coding for experiments.

In the first block of my experiment, I have two sound components in each trial (one Question sound and one Answer sound). Therefore, the first sound component does have a stop duration time so that the second sound component can start. My second sound component should not have a stop duration time because I have a keyboard response component.

This is the error I am getting:

  File "/Applications/PsychoPy2_PY3.app/Contents/Resources/lib/python3.6/psychopy/experiment/components/sound/__init__.py", line 65, in writeInitCode
    if float(inits['stopVal'].val) > 2:
ValueError: could not convert string to float: 'None'

Ok, well its the same problem as above that has been fixed. You could amend line 65 of the code so that the conditional only takes place if the init['stopVal'] is not None, as was shown in the link. However, you could also use the most recent Psychopy 3 with the fix in place. Is that an option?

It is definitely an option and I will plan to update to Psychopy 3. Thank you!!!