If this template helps then use it. If not then just delete and start from scratch.
OS : Win10
PsychoPy version (e.g. 1.84.x): 2023.2.3
Standard Standalone? (y/n) yes
**What are you trying to achieve?:
Displaying 16 images on screen while controlling them from a condition list
**What did you try to make it work?:
OK, this is going to be a list of related questions.
- Initially I thought I could create one ImageStimuli component, and just use deepcopy() to duplicate it in a code component and flexibly set the file names. This didn’t work due to error:
File "C:\Users\AppData\Local\Programs\PsychoPy\lib\socket.py", line 272, in __getstate__
raise TypeError(f"cannot pickle {self.__class__.__name__!r} object")
TypeError: cannot pickle 'socket' object
Seems that ImageStimuli is not copiable?
- Then I tried creating all stimuli inside a code component (image = visual.ImageStim()), this resulted in nothing, no error message, no image shown.
Looking into the script it generated, I found that compared to the one generated by using the Image component, there are chunks of code missing, specifically:
image_displayComponents = [image]
for thisComponent in image_displayComponents:
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")
frameN = -1
# --- Run Routine "image_display" ---
routineForceEnded = not continueRoutine
while continueRoutine and routineTimer.getTime() < 5.0:
# get current time
t = routineTimer.getTime()
tThisFlip = win.getFutureFlipTime(clock=routineTimer)
tThisFlipGlobal = win.getFutureFlipTime(clock=None)
frameN = frameN + 1 # number of completed frames (so 0 is the first frame)
# update/draw components on each frame
# is it time to end the Routine? (based on local clock)
if tThisFlip > 5-frameTolerance:
continueRoutine = False
# *image* updates
# if image is starting this frame...
if image.status == NOT_STARTED and tThisFlip >= 0.0-frameTolerance:
# keep track of start time/frame for later
image.frameNStart = frameN # exact frame index
image.tStart = t # local t and not account for scr refresh
image.tStartRefresh = tThisFlipGlobal # on global time
win.timeOnFlip(image, 'tStartRefresh') # time at next scr refresh
# add timestamp to datafile
thisExp.timestampOnFlip(win, 'image.started')
# update status
image.status = STARTED
image.setAutoDraw(True)
# if image is active this frame...
if image.status == STARTED:
# update params
pass
# if image is stopping this frame...
if image.status == STARTED:
# is it time to stop? (based on global clock, using actual start)
if tThisFlipGlobal > image.tStartRefresh + 1.0-frameTolerance:
# keep track of stop time/frame for later
image.tStop = t # not accounting for scr refresh
image.frameNStop = frameN # exact frame index
# add timestamp to datafile
thisExp.timestampOnFlip(win, 'image.stopped')
# update status
image.status = FINISHED
image.setAutoDraw(False)
I’m not sure why Builder doesn’t handle manually created ImageStimuli the same way as its prebuilt component equivalent? Can I even realisticly do that in custom code?
I know I can always click Image component 16 times but thought I would ask since it’s an intriguing question. Thank you if you have read through the question.
Mengya
.