Screen frozen following core.wait?

Hi all!

I have text, sound and a key response in each trial of my experiment. Following the sound, I would like for participants to have 1 second following the end of the auditory stimulus to respond using their keyboard although they can also respond during the stimulus. I am using core.wait(1) to do so, although it just ‘freezes’ on the text on screen (on the first trial) and I am unable to press anything other than ‘esc’ to stop this.

I saw someone had a similar issue, however, I don’t think my screen is actually freezing, just that I have made an error coding the wait time. The relevant code is below (‘core.wait’ is just above ‘check for quit’) . I would greatly appreciate any help! :slight_smile:

            trial_sound.setSound(Stimulus, hamming=True)
            trial_sound.setVolume(1, log=False)
            
            # keep track of which components have finished
            trial_Components = [trial_text, trial_key_resp, trial_sound]
            for thisComponent in trial_Components:
                thisComponent.tStart = None
                thisComponent.tStop = None
                thisComponent.tStartRefresh = None
                thisComponent.tStopRefresh = None
                if hasattr(thisComponent, 'status'):
                    thisComponent.status = NOT_STARTED
            # reset timers
            t = 0
            _timeToFirstFrame = win.getFutureFlipTime(clock="now")
            trialClock.reset(-_timeToFirstFrame)  # t0 is time of first possible flip
            frameN = -1
            
            # -------Run Routine "trial"-------
            while continueRoutine:
                # get current time
                t = trialClock.getTime()
                tThisFlip = win.getFutureFlipTime(clock=trialClock)
                tThisFlipGlobal = win.getFutureFlipTime(clock=None)
                frameN = frameN + 1  # number of completed frames (so 0 is the first frame)
                # update/draw components on each frame
                
                # *trial_text* updates
                if trial_text.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance:
                    # keep track of start time/frame for later
                    trial_text.frameNStart = frameN  # exact frame index
                    trial_text.tStart = t  # local t and not account for scr refresh
                    trial_text.tStartRefresh = tThisFlipGlobal  # on global time
                    win.timeOnFlip(trial_text, 'tStartRefresh')  # time at next scr refresh
                    trial_text.setAutoDraw(True)
                
                # *trial_key_resp* updates
                waitOnFlip = False
                if trial_key_resp.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance:
                    # keep track of start time/frame for later
                    trial_key_resp.frameNStart = frameN  # exact frame index
                    trial_key_resp.tStart = t  # local t and not account for scr refresh
                    trial_key_resp.tStartRefresh = tThisFlipGlobal  # on global time
                    win.timeOnFlip(trial_key_resp, 'tStartRefresh')  # time at next scr refresh
                    trial_key_resp.status = STARTED
                    # keyboard checking is just starting
                    waitOnFlip = True
                    win.callOnFlip(trial_key_resp.clock.reset)  # t=0 on next screen flip
                    win.callOnFlip(trial_key_resp.clearEvents, eventType='keyboard')  # clear events on next screen flip
                    
                if trial_key_resp.status == STARTED:
                    # is it time to stop? (based on global clock, using actual start)
                    if tThisFlipGlobal > trial_key_resp.tStartRefresh + 0.0-frameTolerance:
                        # keep track of stop time/frame for later
                        trial_key_resp.tStop = t  # not accounting for scr refresh
                        trial_key_resp.frameNStop = frameN  # exact frame index
                        win.timeOnFlip(trial_key_resp, 'tStopRefresh')  # time at next scr refresh
                        trial_key_resp.status = FINISHED
                if trial_key_resp.status == STARTED and not waitOnFlip:
                    theseKeys = trial_key_resp.getKeys(keyList=['left', 'right'], waitRelease=False)
                    _trial_key_resp_allKeys.extend(theseKeys)
                    if len(_trial_key_resp_allKeys):
                        trial_key_resp.keys = _trial_key_resp_allKeys[-1].name  # just the last key pressed
                        trial_key_resp.rt = _trial_key_resp_allKeys[-1].rt
                        # was this correct?
                        if (trial_key_resp.keys == str(corrAns)) or (trial_key_resp.keys == corrAns):
                            trial_key_resp.corr = 1
                        else:
                            trial_key_resp.corr = 0
                        # a response ends the routine
                        continueRoutine = False
                # start/stop trial_sound
                if trial_sound.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance:
                    # keep track of start time/frame for later
                    trial_sound.frameNStart = frameN  # exact frame index
                    trial_sound.tStart = t  # local t and not account for scr refresh
                    trial_sound.tStartRefresh = tThisFlipGlobal  # on global time
                    trial_sound.play(when=win)  # sync with win flip

                core.wait(1)
                win.close()
                
                # check for quit (typically the Esc key)
                if endExpNow or defaultKeyboard.getKeys(keyList=["escape"]):
                    core.quit()
                
                # 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 trial_Components:
                    if hasattr(thisComponent, "status") and thisComponent.status != FINISHED:
                        continueRoutine = True
                        break  # at least one component has not yet finished
                                
                # refresh the screen
                if continueRoutine:  # don't flip if this routine is over or we'll get a blank screen
                    win.flip()

It looks like you are modifying a Builder-generated script.

  • There is almost never a reason to do this. Use code components within the Builder interface instead - that way, you can still keep tweaking things graphically as required, and also know that your custom code will be inserted at the right place for you.
  • You should basically never use wait() or waitKeys() in Builder scripts. Builder generates a script that is inherently based around an active drawing cycle of updating the screen content and doing other tasks on every screen refresh. By using these functions, you are effectively pausing that active cycle, which will wipe out all of the script’s timing and have many non-obvious consequences.

So use Builder code components and they will force you into the right way of inserting custom code. eg instead of using waitKeys(), use getKeys() in the “each frame” tab. ie instead of waiting indefinitely for a response, actively check for a response instantaneously on every screen refresh.

1 Like

Dear Michael,

Thank you for your reply! I am indeed modifying a builder-generated script, however, I am unable to change it using the builder as a large portion of the rest of the experiment has been altered using the coder view.

Is there a way in which one could add that 1s delay without interfering with Psyhopy’s process? One solution which I am considering is simply padding my sound stimuli with 1s of 0s at the end, although I would like to avoid this if possible as it is more difficult to change if needed! Thank you :slight_smile:

Sure there might be a perfectly simple way to do this without problems. But I wouldn’t be keen to advise on this, precisely because the scripts are quite complicated and it is hard to know what should go where. So I’m only really able to give suggestions that are based on using features and custom code within the graphical interface (or on scripts that a person has written from scratch and so they are in control of the event loop).