I am trying to use a custom projection to warp a grating stimulus each time it is drawn. I’ve tried using the psychopy.visual.windowarp.Warper class to do this, and it works if I use one of the standard projections like “spherical” or “cylindrical,” but if I try to use a custom warpfile to define the projection, the grating is not warped. Here is a minimal working example which results in this behavior:
from psychopy.visual import Window
from psychopy.visual import GratingStim
from psychopy.visual.windowwarp import Warper
win = Window([1280, 720], useFBO=True)
warper = Warper(win, warp=None, warpfile=<path to warpfile>)
grating = GratingStim(win, size=5, sf=50)
grating.draw()
win.flip()
This example (above) does not warp the grating, but if I do this (below) the warping operation is successful:
I thought maybe I had generated an invalid warpfile, but the warping still does not work when using the example warpfile for a 1280x720 monitor hosted here. Am I doing something wrong, or is this really not working?
For anyone who finds this thread in the future: After playing around with the source code, I was able to determine why the warping wasn’t working for a custom warpfile. The problem lies in the changeProjection method.
def changeProjection(self, warp, warpfile=None, eyepoint=(0.5, 0.5),
flipHorizontal=False, flipVertical=False):
"""Allows changing the warp method on the fly. Uses the same
parameter definitions as constructor.
"""
self.warp = warp
self.warpfile = warpfile
self.eyepoint = list(eyepoint)
self.flipHorizontal = flipHorizontal
self.flipVertical = flipVertical
# warpfile might have changed the size...
self.initDefaultWarpSize()
if self.warp is None:
self.projectionNone()
elif self.warp == 'spherical':
self.projectionSphericalOrCylindrical(False)
elif self.warp == 'cylindrical':
self.projectionSphericalOrCylindrical(True)
elif self.warp == 'warpfile':
self.projectionWarpfile()
else:
raise ValueError('Unknown warp specification: %s' % self.warp)
You have to pass a value as the warp kwarg, so I passed None, but if the warp attribute is set to None, the result is that the projectionNone method is called, even if I also pass a value to the warpfile kwarg. For the warper to work using a custom warpfile, you have to pass the string “warpfile” as the warp kwarg in addition to passing the file path to the warpfile as the warpfile kwarg. This is documented in the docstring for the class, but being the super-genius I am, I totally missed it.