def _addRuntimeInfoToDisplayConfig(self): if self not in Display._enabled_display_instances: Display._enabled_display_instances.append(self) display_config=self.getConfiguration() runtime_info=display_config.get('runtime_info',None) if runtime_info is None: runtime_info=self._getRuntimeInfoByIndex(self.device_number) display_config['runtime_info']=runtime_info self._createPsychopyCalibrationFile() pixel_width=runtime_info['pixel_width'] pixel_height=runtime_info['pixel_height'] phys_width=display_config["physical_dimensions"]['width'] phys_height=display_config["physical_dimensions"]['height'] phys_unit_type=display_config["physical_dimensions"]['unit_type'] # add pixels_per_degree to runtime info ppd_x=misc.deg2pix(1.0,self._psychopy_monitor)#math.tan(math.radians(0.5))*2.0*viewing_distance*pixel_width/phys_width ppd_y=misc.deg2pix(1.0,self._psychopy_monitor)#math.tan(math.radians(0.5))*2.0*viewing_distance*pixel_height/phys_height runtime_info['pixels_per_degree']=ppd_x,ppd_y self. _calculateCoordMappingFunctions(pixel_width,pixel_height,phys_unit_type, phys_width,phys_height) left,top,right,bottom=runtime_info['bounds'] coord_left,coord_top=self._pixel2DisplayCoord(left,top,self.device_number) coord_right,coord_bottom=self._pixel2DisplayCoord(right,bottom,self.device_number) runtime_info['coordinate_bounds']= coord_left,coord_top,coord_right,coord_bottom
def draw(self, wind): ''' draws the maze to window wind''' try: self.maze.draw() return except AttributeError: 'do nothing' elem=[] temp=np.array(self.lineXY) edges=visual.ElementArrayStim(wind,fieldShape='sqr', nElements=len(self.lineXY)*2,sizes=self.lw,units='deg', elementMask='circle',elementTex=None, xys=np.reshape(temp,(temp.shape[0]*2,2))) elem.append(edges) # todo try elem array instead of line for line in self.lineXY: #print line body=visual.Line(wind,line[0],line[1], lineWidth=deg2pix(self.lw,wind.monitor)) elem.append(body) frame=visual.Rect(wind,width=self.dispSize[0], height=self.dispSize[1],lineColor=(1,1,1),pos=(0,0), lineWidth=deg2pix(self.lw,wind.monitor),units='deg') if len(self.lineXY)==0: self.maze=frame else: elem.append(frame) self.maze=visual.BufferImageStim(wind,stim=elem)
def __init__(self, size=(800, 600), position=None, units="pix", monitor=None): """ Parameters ---------- size : *(800, 600)* or tuple tuple containing the width and the height of the window in pixel position : *None* or tuple if None screen center, otherwise the position given in a tuple containing the center of the window relative to the center of the screen (positive values mean up/right) units : "pix", "deg", "cm", "norm" (optional) psychopy units to calculate size and position of the window. If units is different from "pix" monitor must be present. Default is "pix." monitor : psychopy.monitors.Monitor (optional) psychopy monitor object, that is used to convert units. """ if units != "pix": if not monitor: raise ValueError( "if units is not 'pix', monitor must be supplied") # convert to pixel if units == "deg": size = [misc.deg2pix(x, monitor) for x in size] if position: position = [misc.deg2pix(x, monitor) for x in position] elif units == "cm": size = [misc.cm2pix(x, monitor) for x in size] if position: position = [misc.cm2pix(x, monitor) for x in position] elif units == "norm": size = [ int(monitor.getSizePix()[0] * (float(size[0]) / 2)), int(monitor.getSizePix()[1] * (float(size[1]) / 2)) ] if position: position = [ int(monitor.getSizePix()[0] * position[0]), int(monitor.getSizePix()[1] * position[1]) ] else: raise ValueError( "only 'pix', 'deg', 'cm', or 'norm' are accepted units.") # call parent with calculated parameters super(PsyTMLPsychopy, self).__init__(size, position)
def traj2movie(traj,width=5,outsize=64,elem=None,wind=None,rot=2, hz=85.0,SX=0.3,SY=0.3,ST=20): ''' extracts window at position 0,0 of width WIDTH deg from trajectories and subsamples to OUTSIZExOUTSIZE pixels HZ - trajectory sampling frequency ROT - int number of rotations to output or float angle in radians SX,SY,ST - standard deviation of gaussian filter in deg,deg,ms ''' if type(wind)==type(None): close=True; wind=Q.initDisplay() else: close=False if type(elem)==type(None): elem=visual.ElementArrayStim(wind,fieldShape='sqr', nElements=traj.shape[1], sizes=Q.agentSize, elementMask=RING,elementTex=None,colors='white') try: sig=[ST/1000.0*hz] sig.append(deg2pix(SX,wind.monitor)) sig.append(deg2pix(SY,wind.monitor)) w=int(np.round(deg2pix(width,wind.monitor)/2.0)) D=np.zeros((traj.shape[0],outsize,outsize,rot),dtype=np.uint8) Ims=[] for f in range(0,traj.shape[0]): Im=position2image(traj[f,:,:],wind=wind) cx=int(Im.size[0]/2.0);cy=int(Im.size[1]/2.0) Im=Im.crop(np.int32((cx-1.5*w,cy-1.5*w,cx+1.5*w,cy+1.5*w))) Im=np.asarray(Im,dtype=np.float32) Ims.append(Im) Ims=np.array(Ims) if np.any(np.array(sig)!=0):Ims=gaussian_filter(Ims,sig) if np.any(Ims>255): print 'warning, too large' if np.any(Ims<0): print 'warning, too small' Ims=np.uint8(np.round(Ims)) for f in range(Ims.shape[0]): Im=Image.fromarray(np.array(Ims[f,:,:])) bb=int(Im.size[0]/2.0) I=Im.crop((bb-w,bb-w,bb+w,bb+w)) I=np.asarray(I.resize((outsize,outsize),Image.ANTIALIAS)) D[f,:,:,0]=I for r in range(1,rot): I2=Im.rotate(90/float(rot)*r) I2=I2.crop((bb-w,bb-w,bb+w,bb+w)) I2=np.asarray(I2.resize((outsize,outsize),Image.ANTIALIAS)) D[f,:,:,r]=I2 if close: wind.close() return D except: if close: wind.close() raise
def getCurrentFixation(self, units='deg'): ''' returns the triple gc,fc,fix where gc is current gaze position, fc is current fixation position (or nans if not available) and fix indicates whether a fixation is currently taking place units - units of output coordinates 'norm', 'pix', 'cm' and 'deg' are currently supported ''' gc=self.getCurrentGazePosition(units=units) fd=self.fixdur/self.hz fc=self.fixsum/float(Settings.FUSS)#/float(max(self.fixdur,1)) if units is 'cm': fc=deg2cm(fc, self.win.monitor) elif units is 'pix': fc=deg2pix(fc, self.win.monitor) elif units is 'norm': fc = deg2pix(fc, self.win.monitor) / self.win.size*2 return gc,fc, fd>Settings.FIXMINDUR,0
def degcoord2pix(self, degx, degy, display_index=None): if display_index == self.getIndex(): return psychopy2displayPix( misc.deg2pix( degx, self._psychopy_monitor), misc.cm2pix( degy, self._psychopy_monitor)) return degx, degy
def __init__(self, tracker, win, settings): """ Initializes PsychopyCustomDisplay object. """ super().__init__() self.tracker = tracker self.win = win self.settings = settings # from session self.txtcol = -1 #self.__target_beep__ = sound.Sound(800, secs=.1) # THIS WILL GIVE A SEGFAULT! #self.__target_beep__done__ = sound.Sound(1200, secs=.1) # THIS WILL GIVE A SEGFAULT! #self.__target_beep__error__ = sound.Sound(400, secs=.1) # THIS WILL GIVE A SEGFAULT! self.backcolor = self.win.color dot_size_pix = misc.deg2pix( self.settings['eyetracker'].get('dot_size'), self.win.monitor) self.targetout = Circle(self.win, pos=(0, 0), radius=dot_size_pix, fillColor='black', units='pix', lineColor='black') self.targetin = Circle(self.win, pos=(0, 0), radius=3, fillColor=0, lineColor=0, units='pix', opacity=0) win.flip()
def getOffScreenFrames(self): """ Returns a list of frames when the foreground stimulus is offscreen UNFINISHED""" objectwidthDeg = int(self.terrain['objectwidthDeg']) mon = monitors.Monitors('testMonitor') objectwidthPix = misc.deg2pix(objectwidthDeg,mon) posx = array(self.posx)
def _addRuntimeInfoToDisplayConfig(self): if self not in Display._enabled_display_instances: Display._enabled_display_instances.append(self) display_config = self.getConfiguration() runtime_info = display_config.get('runtime_info', None) if runtime_info is None: runtime_info = self._getRuntimeInfoByIndex(self.device_number) display_config['runtime_info'] = runtime_info if _ispkg is False: self._createPsychopyCalibrationFile() pixel_width = runtime_info['pixel_width'] pixel_height = runtime_info['pixel_height'] phys_width = display_config['physical_dimensions']['width'] phys_height = display_config['physical_dimensions']['height'] phys_unit_type = display_config['physical_dimensions']['unit_type'] # add pixels_per_degree to runtime info try: from psychopy import misc # math.tan(math.radians(0.5))*2.0*viewing_distance*pixel_width/phys_width ppd_x = misc.deg2pix(1.0, self._psychopy_monitor) # math.tan(math.radians(0.5))*2.0*viewing_distance*pixel_height/phys_height ppd_y = misc.deg2pix(1.0, self._psychopy_monitor) runtime_info['pixels_per_degree'] = ppd_x, ppd_y except ImportError as e: pass self._calculateCoordMappingFunctions(pixel_width, pixel_height, phys_unit_type, phys_width, phys_height) left, top, right, bottom = runtime_info['bounds'] coord_left, coord_top = self._pixel2DisplayCoord( left, top, self.device_number) coord_right, coord_bottom = self._pixel2DisplayCoord( right, bottom, self.device_number) runtime_info[ 'coordinate_bounds'] = coord_left, coord_top, coord_right, coord_bottom
def __init__(self, size=(800, 600), position=None, units="pix", monitor=None): """ Parameters ---------- size : *(800, 600)* or tuple tuple containing the width and the height of the window in pixel position : *None* or tuple if None screen center, otherwise the position given in a tuple containing the center of the window relative to the center of the screen (positive values mean up/right) units : "pix", "deg", "cm", "norm" (optional) psychopy units to calculate size and position of the window. If units is different from "pix" monitor must be present. Default is "pix." monitor : psychopy.monitors.Monitor (optional) psychopy monitor object, that is used to convert units. """ if units != "pix": if not monitor: raise ValueError("if units is not 'pix', monitor must be supplied") # convert to pixel if units == "deg": size = [misc.deg2pix(x, monitor) for x in size] if position: position = [misc.deg2pix(x, monitor) for x in position] elif units == "cm": size = [misc.cm2pix(x, monitor) for x in size] if position: position = [misc.cm2pix(x, monitor) for x in position] elif units == "norm": size = [int(monitor.getSizePix()[0] * (float(size[0])/2)), int(monitor.getSizePix()[1] * (float(size[1])/2))] if position: position = [int(monitor.getSizePix()[0] * position[0]), int(monitor.getSizePix()[1] * position[1])] else: raise ValueError("only 'pix', 'deg', 'cm', or 'norm' are accepted units.") # call parent with calculated parameters super(PsyTMLPsychopy, self).__init__(size, position)
def deg2norm_y(position, window): return pix2norm_y(deg2pix(position, window.monitor), window)
# Run through the trial in trialList trial_no = 1 for trial in trials: # Set position of dot and draw it, and show (flip) it on the screen target_x, target_y = trial['posx']*sc_f,trial['posy']*sc_f dot.setPos((target_x, target_y)) dot.draw() dot_center.setPos((target_x, target_y)) dot_center.draw() flip_time = win.flip() # Send message about trial trial['trial_id'] = trial_no trial['TRIAL_START'] = flip_time trial['posx'] = misc.deg2pix(target_x,thisMon) # Convert to pixels to match EDQ scripts trial['posy'] = misc.deg2pix(target_y,thisMon) # Convert to pixels to match EDQ scripts # Show the dot for the duration specified in the Excel sheet # (would be more accurate to wait in multiples of the screen refresh rate) dot_duration = trial['dt']/1000.0 core.wait(dot_duration) trial['TRIAL_END']=flip_time + dot_duration # Add trial info to iohub io.addRowToConditionVariableTable(trial.values()) # increment trial number trial_no += 1
# set screen: myWin = visual.Window(size=(PixW, PixH), screen=0, winType='pyglet', allowGUI=False, allowStencil=False, fullscr=True, monitor=moni, color=[0, 0, 0], colorSpace='rgb', units='pix', blendMode='avg', autoLog=False) # The size of the field. fieldSizeinPix = np.round(misc.deg2pix(cfg.fovHeight, moni)) logFile.write('fieldSizeinDeg=' + unicode(cfg.fovHeight) + '\n') logFile.write('fieldSizeinPix=' + unicode(fieldSizeinPix) + '\n') # %% CONDITIONS # get timings for apertures and motion directions strPathParentUp = os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) filename = os.path.join( strPathParentUp, 'Conditions', 'Conditions_PrepRun_run' + str(expInfo['run']) + '.npz') npzfile = np.load(filename) conditions = npzfile["conditions"].astype('int8') targets = npzfile["targets"]
def preTrial(self, trial, calibTrial, win,autoDrift=False): '''Set up each trial with the eye tracker ''' self.tracker.doSetup=False if calibTrial: cond = "Test/Calibration Trial" else: cond = "Non-test/no calibration trial" message ="record_status_message 'Trial %d %s'"%(trial+1, cond) self.tracker.sendCommand(message) msg = "TRIALID %s"%trial self.tracker.sendMessage(msg) #Do drift correction if necissary if calibTrial: win.flip() while True: try: error = self.tracker.doDriftCorrect(self.screenSize[0]/2,self.screenSize[1]/2,1,1) if error != 27: self.tracker.applyDriftCorrect() break else: #self.tracker.doTrackerSetup() win.flip() except: print("Exception") break win.flip() print("Switching to record mode") error = self.tracker.startRecording(1,1,1,1) pylink.beginRealTimeMode(100) if error: return error if not self.tracker.waitForBlockStart(1000, 1, 0): endTrial() print "ERROR: No link samples received!" return "ABORT_EXPT" self.eye_used = self.tracker.eyeAvailable(); #determine which eye(s) are available if self.eye_used == RIGHT_EYE: self.tracker.sendMessage("PRETRIAL EYE_USED 1 RIGHT") elif self.eye_used == LEFT_EYE : self.tracker.sendMessage("PRETRIAL EYE_USED 0 LEFT") elif self.eye_used == BINOCULAR: self.tracker.sendMessage("PRETRIAL EYE_USED 2 BINOCULAR") else: print "Error in getting the eye information!" return "ABORT_EXPT" self.tracker.flushKeybuttons(0) if autoDrift: self.tracker.target.setPos((0, 0)) self.tracker.target.draw() win.flip() x,y=self.screenSize/2.0 i=0 leftFinished=False rightFinished=False core.wait(0.5) self.tracker.resetData() while i<10 and not (leftFinished and rightFinished): sampleType = self.tracker.getNextData() if sampleType == pylink.FIXUPDATE: sample = self.tracker.getFloatData() gazePos=sample.getAverageGaze() #self.sendMessage('eyePos %.3f %.3f type %d, eye %d'%(gazePos[0],gazePos[1],sample.getType(),sample.getEye())) if (( (x-gazePos[0])**2+(y-gazePos[1])**2)**0.5<misc.deg2pix(3,win.monitor) and gazePos[0]>0 and gazePos[0]<2*x and gazePos[1]>0 and gazePos[1]<2*y): cmd='drift_correction %f %f %f %f' % (x-gazePos[0], y-gazePos[1],x,y) if sample.getEye()==1: rightFinished=True; cmd+=' R' else: leftFinished=True; cmd+=' L' self.sendCommand(cmd) else: core.wait(0.1) self.tracker.resetData() i+=1 if i==10: self.postTrial() self.tracker.doTrackerSetup() self.preTrial(trial, calibTrial, win,autoDrift) else: core.wait(0.25+random.random()/2) return
myWin = visual.Window( size=(PixW, PixH), screen=0, winType='pyglet', allowGUI=False, allowStencil=False, fullscr=True, monitor=moni, color=[0, 0, 0], colorSpace='rgb', units='pix', blendMode='avg', autoLog=False) # The size of the field. fieldSizeinPix = np.round(misc.deg2pix(cfg.fovHeight, moni)) logFile.write('fieldSizeinDeg=' + unicode(cfg.fovHeight) + '\n') logFile.write('fieldSizeinPix=' + unicode(fieldSizeinPix) + '\n') # %% CONDITIONS strPathParentUp = os.path.abspath( os.path.join(os.path.dirname(__file__), '..')) filename = os.path.join(strPathParentUp, 'conditions', 'Conditions_MotLoc_run' + str(expInfo['run']) + '.npz') npzfile = np.load(filename) conditions = npzfile["conditions"].astype('int8') targets = npzfile["targets"]
# for psychoph lab: make 'fullscr = True', set size =(1920, 1080) myWin = visual.Window( size=(PixW, PixH), screen=0, winType='pyglet', # winType : None, ‘pyglet’, ‘pygame’ allowGUI=False, allowStencil=True, fullscr=True, # for psychoph lab: fullscr = True monitor=moni, color=[0, 0, 0], colorSpace='rgb', units='pix', blendMode='avg') # Speed of the dots (in deg per second) speedPixPerSec = misc.deg2pix(30, moni) # 0.01 # The size of the field. fieldSizeinDeg = 24 fieldSizeinPix = np.round(misc.deg2pix(fieldSizeinDeg, moni)) logFile.write('speedPixPerSec=' + unicode(speedPixPerSec) + '\n') logFile.write('fieldSizeinDeg=' + unicode(fieldSizeinDeg) + '\n') logFile.write('fieldSizeinPix=' + unicode(fieldSizeinPix) + '\n') # %% """CONDITIONS""" # retrieve masks from npz file (stored in folder Masks) str_path_masks = str_path_parent_up + os.path.sep + 'Masks' + \ os.path.sep + str(expInfo['maskType']) + '.npy' masks = np.load(str_path_masks) # turn 0 to -1 (since later on this will be used as mask for GratingStim),
def deg2pix(self,deg): return deg2pix(deg,self.monitor)
#CREATE BACKGROUND STIMULUS grating = visual.GratingStim(window,tex="sin",mask="None",texRes=64, size=[160,160], sf=1, ori = 0, name='grating', autoLog=False, units = 'deg') #CREATE BACKGROUND FRAME PARAMETERS (what changes between frames and how much) bgFrame = {} #CREATE BACKGROUND SWEEP PARAMETERS (what changes between sweeps, and in what order) bgSweep = {} bgSweep['Ori'] = (range(0,360,45),0) bgSweep['SF'] = ([0.2],1) bgSweep['Contrast'] = ([1],3) bgSweep['TF'] = ([2],2) bgSweep['Phase'] = ([0],4) #CREATE FOREGROUND STIMULUS monitor = monitors.Monitor('testMonitor') target = visual.GratingStim(window, tex = None, size = (misc.deg2pix(terrain.objectwidthDeg,monitor), misc.deg2pix(terrain.objectwidthDeg,monitor)), units = 'pix', color = -1, autoLog=False) #img = visual.ImageStim(window, image = "C:\\Users\\derricw\\Pictures\\facepalm.jpg", size = [450,300], units = 'pix', autoLog=False) #creates an image from an image in specified directory #CREATE FOREGROUND STIMULUS FRAME PARAMETERS (what changes between frames and how much (BESIDES XPOSITITON WHICH IS AUTOMATIC FOR THIS EXPERIMENT) fgFrame = {} #CREATE FOREGROUND SWEEP PARAMETERS (what changes between sweeps) fgSweep = {} #CREATE FORAGING CLASS INSTANCE g = Foraging(window = window, terrain = terrain, params = params, bgStim = grating, bgFrame = bgFrame, bgSweep = bgSweep, fgStim = target) #RUN IT g.run()