示例#1
0
    def updateparams(self, i):
        """Updates stimulus parameters, given sweep table index i"""
        if i == None: # do a blank sweep
            self.tsp.on = False # turn off the movie, leave all other parameters unchanged
            self.postval = C.MAXPOSTABLEINT # posted to DT port to indicate a blank sweep
            self.nvsyncs = sec2intvsync(self.blanksweeps.sec) # this many vsyncs for this sweep
            self.npostvsyncs = 0 # this many post-sweep vsyncs for this sweep, blank sweeps have no post-sweep delay
        else: # not a blank sweep
            self.tsp.on = True # ensure texture stimulus is on
            self.postval = i # sweep table index will be posted to DT port
            self.nvsyncs = sec2intvsync(self.st.sweepSec[i]) # this many vsyncs for this sweep
            self.npostvsyncs = sec2intvsync(self.st.postsweepSec[i]) # this many post-sweep vsyncs for this sweep

            # Update texture
            frame = self.frames[self.st.framei[i]] # get the frame for this sweep
            #frame = self[self.st.framei[i]] # get the frame for this sweep
            if self.st.invert[i]:
                frame = 255 - frame # give the frame inverted polarity
            self.to.put_sub_image(frame, data_format=gl.GL_LUMINANCE, data_type=gl.GL_UNSIGNED_BYTE)

            # Update texturestimulus
            self.tsp.angle = self.static.orioff + self.st.ori[i]
            self.tsp.position = self.xorig+deg2pix(self.st.xposDeg[i]), self.yorig+deg2pix(self.st.yposDeg[i])

            # Update background parameters
            self.bgp.color = self.st.bgbrightness[i], self.st.bgbrightness[i], self.st.bgbrightness[i], 1.0

            # Update fixationspot
            self.fsp.on = bool(self.st.fixationspotDeg[i])
            self.fsp.size = deg2pix(self.st.fixationspotDeg[i]), deg2pix(self.st.fixationspotDeg[i])
示例#2
0
 def __init__(self, *args, **kwargs):
     super(ForagingSweeps, self).__init__(*args, **kwargs)
     self.width = deg2pix(self.static.widthDeg) # do this here so it doesn't have to be done repeatedly in self.updateparams()
     self.height = deg2pix(self.static.heightDeg)
     
     self.terrain = self.static.terrain
     
     #square initialization
     self.brightness = self.terrain.color
     
     #set up encoder
     self.static.encoder.start()
     self.lastDx = 0
     if self.static.encoder.getVin() < 1:
         print 'Encoder not connected or powered on.'
         
     #set up reward
     self.framescorrect = 0
     self.static.reward.start()
     
     #set up data logs
     self.laps = []
     self.rewards = []
     self.posx = []
     self.dx = []
     self.terrainlog = []
示例#3
0
    def updateparams(self, i):
        """Updates stimulus parameters, given sweep table index i"""
        if i == None: # do a blank sweep
            self.tp.on = False # turn off the target, leave all other parameters unchanged
            self.postval = C.MAXPOSTABLEINT # posted to DT port to indicate a blank sweep
            self.nvsyncs = sec2intvsync(self.blanksweeps.sec) # this many vsyncs for this sweep
            self.npostvsyncs = 0 # this many post-sweep vsyncs for this sweep, blank sweeps have no post-sweep delay
        else: # not a blank sweep
            self.tp.on = True # ensure stimulus is on
            self.postval = i # sweep table index will be posted to DT port
            self.nvsyncs = sec2intvsync(self.st.sweepSec[i]) # this many vsyncs for this sweep
            self.npostvsyncs = sec2intvsync(self.st.postsweepSec[i]) # this many post-sweep vsyncs for this sweep

            # Generate position as a f'n of vsynci for this sweep, even if speedDegSec is 0
            distance = degSec2pixVsync(self.st.speedDegSec[i]) * self.nvsyncs # total distance to travel on this sweep
            direction = self.static.orioff + self.st.ori[i] + 90 # direction to travel on this sweep, always |_ to current ori
            xdistance = distance * math.cos(direction / 180 * math.pi)
            ydistance = distance * math.sin(direction / 180 * math.pi)
            xstep = xdistance / self.nvsyncs # pix to travel per vsync
            ystep = ydistance / self.nvsyncs
            x0 = self.xorig - xdistance / 2
            y0 = self.yorig - ydistance / 2
            self.x = x0 + xstep * np.arange(self.nvsyncs) + deg2pix(self.st.xposDeg[i]) # deg2pix returns 0 if deg is None
            self.y = y0 + ystep * np.arange(self.nvsyncs) + deg2pix(self.st.yposDeg[i])

            # Update non-positional target parameters
            self.tp.orientation = self.static.orioff + self.st.ori[i]
            self.tp.size = deg2pix(self.st.widthDeg[i]), deg2pix(self.st.heightDeg[i])
            self.tp.color = self.st.rbrightness[i], self.st.gbrightness[i], self.st.bbrightness[i], 1.0
            self.tp.anti_aliasing = self.st.antialiase[i]

            # Update background parameters
            self.bgp.color = self.st.bgbrightness[i], self.st.bgbrightness[i], self.st.bgbrightness[i], 1.0
示例#4
0
    def updateparams(self, i):
        """Updates stimulus parameters, given sweep table index i"""
        if i == None: # do a blank sweep
            self.tp.on = False # turn off the target, leave all other parameters unchanged
            self.postval = C.MAXPOSTABLEINT # posted to DT port to indicate a blank sweep
            self.nvsyncs = sec2intvsync(self.blanksweeps.sec) # this many vsyncs for this sweep
            self.npostvsyncs = 0 # this many post-sweep vsyncs for this sweep, blank sweeps have no post-sweep delay
        else: # not a blank sweep
            self.tp.on = True # ensure stimulus is on
            self.postval = i # sweep table index will be posted to DT port
            self.nvsyncs = sec2intvsync(self.st.sweepSec[i]) # this many vsyncs for this sweep
            self.npostvsyncs = sec2intvsync(self.st.postsweepSec[i]) # this many post-sweep vsyncs for this sweep

            # Update target position
            ori = self.static.orioff + self.st.ori[i]
            theta = ori / 180 * pi

            dxi = self.st.xi[i] - self.xi0 # destination index - origin index
            dyi = self.st.yi[i] - self.yi0
            sintheta = math.sin(theta)
            costheta = math.cos(theta)
            dx = dxi*self.barWidth*costheta - dyi*self.barHeight*sintheta # see SparseNoise.png for the trigonometry
            dy = dxi*self.barWidth*sintheta + dyi*self.barHeight*costheta

            x = self.xorig + deg2pix(self.st.xposDeg[i]) + dx
            y = self.yorig + deg2pix(self.st.yposDeg[i]) + dy
            self.tp.position = (x, y)

            # Update non-positional target parameters
            self.tp.orientation = ori
            self.tp.color = self.st.brightness[i], self.st.brightness[i], self.st.brightness[i], 1.0
            self.tp.anti_aliasing = self.st.antialiase[i]

            # Update background parameters
            self.bgp.color = self.st.bgbrightness[i], self.st.bgbrightness[i], self.st.bgbrightness[i], 1.0
示例#5
0
    def build(self):
        """Builds the SweepTable and the Header for this Experiment"""
        super(SparseNoise, self).build()
        self.header.NVS.data[C.STT_STS] = 11 # enter NVS stimulus code for sparse noise (actually, 'reverse correlation')

        self.barWidth = deg2pix(self.static.widthDeg / self.static.ncellswide) # in pix
        self.barHeight = deg2pix(self.static.heightDeg / self.static.ncellshigh) # in pix

        self.xi0 = (self.static.ncellswide - 1) / 2 # center of grid, in units of 0-based cell index
        self.yi0 = (self.static.ncellshigh - 1) / 2
示例#6
0
 def loadManbar(self, n):
     """Load Manbar n setting in dimstim config file and assign it to the current manual bar"""
     mbn = "Manbar" + str(n)
     self.x = intround(
         deg2pix(dc.get(mbn, "xorigDeg")) + I.SCREENWIDTH / 2
     )  # int pix, since pygame.mouse pos works with ints
     self.y = intround(deg2pix(dc.get(mbn, "yorigDeg")) + I.SCREENHEIGHT / 2)
     self.widthDeg = dc.get(mbn, "widthDeg")
     self.heightDeg = dc.get(mbn, "heightDeg")
     self.ori = dc.get(mbn, "orioff")
     self.fp.position = self.x, self.y
示例#7
0
 def updatestimuli(self):
     """Update stimuli"""
     # Update target params
     width = deg2pix(self.widthDeg) # convenience
     height = deg2pix(self.heightDeg)
     self.tp.position = self.x, self.y
     self.tp.size = width, height # convert to pix
     self.tp.orientation = self.ori
     self.tp.color = (self.brightness, self.brightness, self.brightness, 1.0)
     self.bgp.color = (self.bgbrightness, self.bgbrightness, self.bgbrightness, 1.0)
     self.cp.position = self.x, self.y # update center spot position
     self.wlp.position = I.SCREENWIDTH/2 - self.terrain.windowwidth, self.y #DW
     self.wrp.position = I.SCREENWIDTH/2 + self.terrain.windowwidth, self.y #DW
     
     # Update grating parms if grating is turned on
     if self.gp.on:
         self.gp.position = I.SCREENWIDTH/2,I.SCREENHEIGHT/2
         self.gp.orientation = self.gratingori
         sfreq = cycDeg2cycPix(self.sfreqCycDeg)
         try:
             self.phase
         except AttributeError: # phase hasn't been init'd yet
             """phaseoffset is req'd to make phase0 the initial phase at the centre of the grating, instead of at the edge of the grating as VE does. Take the distance from the centre to the edge along the axis of the sinusoid (which in this case is the height), multiply by spatial freq to get numcycles between centre and edge, multiply by 360 deg per cycle to get req'd phaseoffset. THE EXTRA 180 DEG IS NECESSARY FOR SOME REASON, DON'T REALLY UNDERSTAND WHY, BUT IT WORKS!!!"""
             phaseoffset = self.gratingHeight / 2 * sfreq * 360 + 180
             self.phase = -self.phase0 - phaseoffset
         phasestep = cycSec2cycVsync(self.tfreqCycSec * self.nscreens) * 360 # delta cycles per vsync, in degrees of sinusoid, adjust for buffer flips on multiple screens
         self.phase = self.phase - phasestep # update phase
         self.gp.spatial_freq = sfreq
         self.gp.phase_at_t0 = self.phase
         self.gp.contrast = self.contrast
         self.bgp.color = (self.bgbrightness, self.bgbrightness, self.bgbrightness, 1.0)
         self.cp.position = I.SCREENWIDTH/2, I.SCREENHEIGHT/2 # update center spot position
     
     # Update text params
     self.mbtp.text = 'x, y = (%5.1f, %5.1f) deg  |  size = (%.1f, %.1f) deg  |  ori = %5.1f deg' \
                      % ( pix2deg(self.x - I.SCREENWIDTH / 2), pix2deg(self.y - I.SCREENHEIGHT / 2),
                          self.widthDeg, self.heightDeg, self.ori)
     self.dtp.text = "%i Rewards | %.1f Rewards/minute " \
                     % (self.reward.rewardcount, 
                        self.reward.rewardcount/(self.sc.secondselapsed()+0.001)*60) #reward counter
     self.ttp.text = "Session time : %s" % str(self.sc.elapsed())[:10]  #shows session time
     
     if self.brightenText == 'Manbar0':
         self.mbtp.color = (1.0, 1.0, 0.0, 1.0) # set to yellow
     elif self.brightenText == 'Manbar1':
         self.mbtp.color = (1.0, 0.0, 0.0, 1.0) # set to red
     elif self.brightenText == 'Eye':
         self.stp.color = (1.0, 0.0, 0.0, 1.0) # set to red
     else:
         self.mbtp.color = (0.0, 1.0, 0.0, 1.0) # set it back to green
示例#8
0
    def build(self):
        """Builds the SweepTable and the Header for this Experiment"""
        # Build the sweep table
        self.sweeptable = Core.SweepTable(experiment=self)
        self.st = self.sweeptable.data # synonym, used a lot by Experiment subclasses

        # Do time and space conversions of applicable static and dynamic parameters - or maybe do this in init - is this really necessary, can't it be done on the fly, or would that be too slow? If too slow, write it inline in C and use scipy.weave?
        # Is there a better place to store these, rather than polluting self namespace?
        self.xorig = deg2pix(self.static.xorigDeg) + I.SCREENWIDTH / 2 # do this once, since it's static, save time in main loop
        self.yorig = deg2pix(self.static.yorigDeg) + I.SCREENHEIGHT / 2
        self.y = self.static.ypos
        self.x = self.xorig
        self.offscreen = self.off_screen_distance(self.static.terrain.orientation)
        self.encDeg = self.static.encoder.getDegrees()
        
        # Calculate Experiment duration
        self.sec = self.calcduration()
        info('Expected experiment duration: %s' % isotime(self.sec, 6), tolog=False)
示例#9
0
    def build(self):
        """Builds the SweepTable and the Header for this Experiment"""
        self.sweeptable = Core.SweepTable(experiment=self)
        self.st = self.sweeptable.data # synonym, used a lot by Experiment subclasses

        self.barWidth = deg2pix(self.static.widthDeg / self.static.ncellswide) # in pix
        self.barHeight = deg2pix(self.static.heightDeg / self.static.ncellshigh) # in pix

        self.xi0 = (self.static.ncellswide - 1) / 2 # center of grid, in units of 0-based cell index
        self.yi0 = (self.static.ncellshigh - 1) / 2
        
        self.sec = self.calcduration()
        
        self.xorig = deg2pix(self.static.xorigDeg) + I.SCREENWIDTH / 2 # do this once, since it's static, save time in main loop
        self.yorig = deg2pix(self.static.yorigDeg) + I.SCREENHEIGHT / 2
        
        self.y = self.static.ypos
        self.x = self.xorig
示例#10
0
    def createstimuli(self):
        """Creates the VisionEgg stimuli objects for this Experiment subclass"""
        super(Grating, self).createstimuli()

        # Create instances of the Mask2D class, one for each diameter
        if self.static.mask:
            print 'Generating masks',
            self.nmasksamples = 512  # number of samples in mask, must be power of 2, quality/performance tradeoff
            self.masks = {} # init a dictionary
            samplesperpix = self.nmasksamples / deg2pix(min(self.static.widthDeg, self.static.heightDeg))
            for diameterDeg in toiter(self.dynamic.diameterDeg):
                radius = deg2pix(diameterDeg / 2) # in pix
                radiusSamples = samplesperpix * radius # in mask samples
                self.masks[diameterDeg] = Mask2D(function=self.static.mask,
                                                 radius_parameter=radiusSamples, # sigma for gaussian, radius for circle, in units of mask samples
                                                 num_samples=(self.nmasksamples, self.nmasksamples)) # size of mask texture data (# of texels)
                print '.',
            print
        else:
            self.masks = None

        self.nsinsamples = 2048 # number of samples of sine f'n, must be power of 2, quality/performance tradeoff
        self.grating = SinGrating2D(position=(self.xorig, self.yorig), # init to orig,
                                    anchor='center',
                                    size=(deg2pix(self.static.heightDeg), deg2pix(self.static.widthDeg)), # VE defines grating ori as direction of motion of grating, but we want it to be the orientation of the grating elements, so add 90 deg (this also makes grating ori def'n correspond to bar ori def'n). This means that width and height have to be swapped
                                    ignore_time=True, # don't use this class' own time f'n
                                    #mask=self.masks.values()[0], # init to a random mask in maskobjects
                                    num_samples=self.nsinsamples,
                                    max_alpha=1.0, # opaque
                                    on=False) # keep it off until first sweep starts
        self.gp = self.grating.parameters
        if self.static.syncsq:
            self.sync = Target2D(anchor='center',
                                   anti_aliasing=False,
                                   color=(0.0, 0.0, 0.0, 1.0),
                                   position = self.static.syncsqloc,
                                   on = True,
                                   size = (100,100))
            self.sp = self.sync.parameters

        if self.static.syncsq: 
            self.stimuli = (self.background, self.grating, self.sync) # last entry will be topmost layer in viewport
        else:
            self.stimuli = (self.background, self.grating) # last entry will be topmost layer in viewport
示例#11
0
    def build(self):
        """Builds the SweepTable and the Header for this Experiment"""
        # Build the sweep table
        self.sweeptable = Core.SweepTable(experiment=self)
        self.st = self.sweeptable.data # synonym, used a lot by Experiment subclasses

        # Do time and space conversions of applicable static and dynamic parameters - or maybe do this in init - is this really necessary, can't it be done on the fly, or would that be too slow? If too slow, write it inline in C and use scipy.weave?
        # Is there a better place to store these, rather than polluting self namespace?
        self.xorig = deg2pix(self.static.xorigDeg) + I.SCREENWIDTH / 2 # do this once, since it's static, save time in main loop
        self.yorig = deg2pix(self.static.yorigDeg) + I.SCREENHEIGHT / 2

        # Calculate Experiment duration
        self.sec = self.calcduration()
        info('Expected experiment duration: %s' % isotime(self.sec, 6), tolog=False)

        # Build the Surf file header, the NVS header, and the text header
        self.header = Core.Header(experiment=self)
        info('TextHeader.data:', toscreen=False)
        printf2log(str(self.header.text)) # print text header data to log
示例#12
0
    def createstimuli(self):
        """Creates the VisionEgg stimuli objects for this Experiment subclass"""
        super(Movie, self).createstimuli()

        # Create an instance of the Mask2D class
        if self.static.mask:
            self.nmasksamples = 512  # number of samples in mask, must be power of 2, quality/performance tradeoff
            samplesperpix = self.nmasksamples / deg2pix(min(self.static.widthDeg, self.static.heightDeg))
            radius = deg2pix(self.static.diameterDeg / 2) # in pix
            radiusSamples = samplesperpix * radius # in mask samples
            self.mask2d = Mask2D(function=self.static.mask,
                                 radius_parameter=radiusSamples, # sigma for gaussian, radius for circle, in units of mask samples
                                 num_samples=(self.nmasksamples, self.nmasksamples)) # size of mask texture data (# of texels)
        else:
            self.mask2d = None

        self.texture = Texture(self.frames[self.st.framei[0]]) # init texture to frame of first sweep in sweep table

        self.texturestimulus = TextureStimulus(texture=self.texture,
                                               position=(self.xorig, self.yorig), # init to orig
                                               anchor='center',
                                               # texture is scaled to this size:
                                               size=(deg2pix(self.static.widthDeg), deg2pix(self.static.heightDeg)),
                                               mask=self.mask2d,
                                               max_alpha=1.0,
                                               mipmaps_enabled=False, # ?
                                               texture_min_filter=gl.GL_NEAREST, # ?
                                               texture_mag_filter=gl.GL_NEAREST, # ?
                                               on=False) # leave it off for now

        self.fixationspot = ve.Core.FixationSpot(position=(self.xorig, self.yorig),
                                                 anchor='center',
                                                 color=(255, 0, 0, 0),
                                                 size=(1, 1),
                                                 on=False) # leave it off for now

        self.stimuli = (self.background, self.texturestimulus, self.fixationspot) # last entry will be topmost layer in viewport

        self.tsp = self.texturestimulus.parameters # synonym
        self.to = self.tsp.texture.get_texture_object()
        self.fsp = self.fixationspot.parameters
示例#13
0
    def updatestimuli(self):
        """Update stimuli"""
        # Update target params
        width = deg2pix(self.widthDeg)  # convenience
        height = deg2pix(self.heightDeg)
        self.tp.position = self.x, self.y
        self.tp.size = width, height  # convert to pix
        self.tp.orientation = self.ori
        self.tp.color = (self.brightness, self.brightness, self.brightness, 1.0)
        self.bgp.color = (self.bgbrightness, self.bgbrightness, self.bgbrightness, 1.0)
        self.tipp.position = (
            self.x + width / 2 * math.cos(math.pi / 180 * self.ori),
            self.y + width / 2 * math.sin(math.pi / 180 * self.ori),
        )
        self.tipp.orientation = self.ori
        self.cp.position = self.x, self.y  # update center spot position
        # Update text params
        self.mbtp.text = "x, y = (%5.1f, %5.1f) deg  |  size = (%.1f, %.1f) deg  |  ori = %5.1f deg" % (
            pix2deg(self.x - I.SCREENWIDTH / 2),
            pix2deg(self.y - I.SCREENHEIGHT / 2),
            self.widthDeg,
            self.heightDeg,
            self.ori,
        )
        self.stp.text = "Eye open: %s  |  " % C.EYESTATES[self.eyei] + self.screenstring

        if self.brightenText == "Manbar0":
            self.mbtp.color = (1.0, 1.0, 0.0, 1.0)  # set to yellow
        elif self.brightenText == "Manbar1":
            self.mbtp.color = (1.0, 0.0, 0.0, 1.0)  # set to red
        elif self.brightenText == "Eye":
            self.stp.color = (1.0, 0.0, 0.0, 1.0)  # set to red
        else:
            self.mbtp.color = (0.0, 1.0, 0.0, 1.0)  # set it back to green
            self.stp.color = (0.0, 1.0, 1.0, 1.0)  # set it back to cyan

        if self.squarelock:
            self.sltp.on = True
        else:
            self.sltp.on = False
示例#14
0
    def updateparams(self, i):
        """Updates stimulus parameters, given sweep table index i"""
        if i == None: # do a blank sweep
            self.gp.on = False # turn off the grating, leave all other parameters unchanged
            self.postval = C.MAXPOSTABLEINT # posted to DT port to indicate a blank sweep
            self.nvsyncs = sec2intvsync(self.blanksweeps.sec) # this many vsyncs for this sweep
            self.npostvsyncs = 0 # this many post-sweep vsyncs for this sweep, blank sweeps have no post-sweep delay
        else: # not a blank sweep
            self.gp.on = True # ensure grating is on
            self.postval = i # sweep table index will be posted to DT port
            self.nvsyncs = sec2intvsync(self.st.sweepSec[i]) # this many vsyncs for this sweep
            self.npostvsyncs = sec2intvsync(self.st.postsweepSec[i]) # this many post-sweep vsyncs for this sweep

            """Generate phase as a f'n of vsynci for this sweep
            sine grating eq'n used by VE: luminance(x) = 0.5*contrast*sin(2*pi*sfreqCycDeg*x + phaseRad) + ml ...where x is the position in deg along the axis of the sinusoid, and phaseRad = phaseDeg/180*pi. Motion in time is achieved by changing phaseDeg over time. phaseDeg inits to phase0"""
            sfreq = cycDeg2cycPix(self.st.sfreqCycDeg[i]) # convert it just once, reuse it for this sweep
            """phaseoffset is req'd to make phase0 the initial phase at the centre of the grating, instead of at the edge of the grating as VE does. Take the distance from the centre to the edge along the axis of the sinusoid (which in this case is the height), multiply by spatial freq to get numcycles between centre and edge, multiply by 360 deg per cycle to get req'd phaseoffset. THE EXTRA 180 DEG IS NECESSARY FOR SOME REASON, DON'T REALLY UNDERSTAND WHY, BUT IT WORKS!!!"""
            phaseoffset = self.height / 2 * sfreq * 360 + 180
            phasestep = cycSec2cycVsync(self.st.tfreqCycSec[i]) * 360 # delta cycles per vsync, in degrees of sinusoid

            self.phase = -self.st.phase0[i] - phaseoffset - phasestep * np.arange(self.nvsyncs) # array of phases for this sweep. -ve makes the grating move in +ve direction along sinusoidal axis, see sin eq'n above

            # Update grating stimulus
            self.gp.position = self.xorig+deg2pix(self.st.xposDeg[i]), self.yorig+deg2pix(self.st.yposDeg[i])
            self.gp.orientation = self.static.orioff + self.st.ori[i] + 90 # VE defines grating ori as direction of motion of grating, but we want it to be the orientation of the grating elements, so add 90 deg (this also makes grating ori def'n correspond to bar ori def'n). This means that width and height have to be swapped (done at creation of grating)
            if self.masks:
                self.gp.mask = self.masks[self.st.diameterDeg[i]]
            self.gp.spatial_freq = sfreq
            self.gp.pedestal = self.st.ml[i]
            
            if self.st.contrastreverse[i]: 
                contraststep = cycSec2cycVsync(self.st.cfreqCycSec[i])*self.st.contrast[i]*2
                self.contrast =self.st.contrast[i]*np.sin(contraststep * np.arange(self.nvsyncs))
            else: self.gp.contrast = self.st.contrast[i]

            # Update background parameters
            self.bgp.color = self.st.bgbrightness[i], self.st.bgbrightness[i], self.st.bgbrightness[i], 1.0
示例#15
0
 def off_screen_distance(self, orientation = 0):
     '''Gets off screen distance using formula to compensate for orientation of object '''
     x = deg2pix(self.static.terrain.objectwidthDeg) # converts width of object to pixels from degrees
     dist = orientation/45*(np.sqrt(2*(x)**2)-x) + x #pythagorean theorem
     return dist/2 #float divide by two because measurement is from center of object
示例#16
0
 def __init__(self, *args, **kwargs):
     super(Grating, self).__init__(*args, **kwargs)
     self.width = deg2pix(self.static.widthDeg) # do this here so it doesn't have to be done repeatedly in self.updateparams()
     self.height = deg2pix(self.static.heightDeg)