def _handleNativeEvent(self,*args,**kwargs): """ This method is called every time there is new eye data available from the Tobii system, which will be roughly equal to the sampling rate eye data is being recorded at. The callback needs to return as quickly as possible so there is no chance of overlapping calls being made to the callback. Therefore this method simply puts the event data received from the eye tracker device, and the local ioHub time the callback was called, into a buffer for processing by the ioHub event system. """ if self.isReportingEvents(): try: eye_data_event=args[1] logged_time_iohub_usec=Computer.getTime()/self.DEVICE_TIMEBASE_TO_SEC logged_time_tobii_local_usec=self._tobii._getTobiiClockTime() data_time_in_tobii_local_time=self._tobii._sync_manager.convert_from_remote_to_local(eye_data_event.Timestamp) data_delay=logged_time_tobii_local_usec-data_time_in_tobii_local_time logged_time=logged_time_iohub_usec*self.DEVICE_TIMEBASE_TO_SEC device_event_time=data_time_in_tobii_local_time*self.DEVICE_TIMEBASE_TO_SEC iohub_event_time=(logged_time_iohub_usec-data_delay)*self.DEVICE_TIMEBASE_TO_SEC # in sec.msec_usec data_delay=data_delay*self.DEVICE_TIMEBASE_TO_SEC self._addNativeEventToBuffer((logged_time,device_event_time,iohub_event_time,data_delay,eye_data_event)) return True except: ioHub.print2err("ERROR IN _handleNativeEvent") ioHub.printExceptionDetailsToStdErr() else: ioHub.print2err("self._handleNativeEvent called but isReportingEvents == false")
def getPositionAndDelta(self,return_display_index=False): """ Returns a tuple of tuples, being the current position of the ioHub Mouse Device as an (x,y) tuple, and the amount the mouse position changed the last time it was updated (dx,dy). Mouse Position and Delta are in display coordinate units. Args: None Return (tuple): ( (x,y), (dx,dy) ) position of mouse, change in mouse position, both in Display coordinate space. """ try: cpos=self._position lpos=self._lastPosition change_x=cpos[0]-lpos[0] change_y=cpos[1]-lpos[1] if return_display_index is True: return (cpos, (change_x,change_y), self._display_index) return cpos, (change_x,change_y) except Exception, e: ioHub.print2err(">>ERROR getPositionAndDelta: "+str(e)) ioHub.printExceptionDetailsToStdErr() if return_display_index is True: return ((0.0,0.0),(0.0,0.0), self._display_index) return (0.0,0.0),(0.0,0.0)
def _nativeEventCallback(self,event): try: if self.isReportingEvents(): logged_time=currentSec() event_array=event[0] event_array[3]=Computer._getNextEventID() display_index=self._display_device.getIndex() x,y=self._display_device.pixel2DisplayCoord(event_array[15],event_array[16],display_index) event_array[15]=x event_array[16]=y self._lastPosition=self._position self._position=x,y self._last_display_index=self._display_index self._display_index=display_index self._addNativeEventToBuffer(event_array) self._last_callback_time=logged_time except: ioHub.printExceptionDetailsToStdErr() # Must return original event or no mouse events will get to OSX! return 1
def shutdown(self): try: self._running=False if Computer.system=='linux2': if self._hookManager: self._hookManager.cancel() while len(self.deviceMonitors) > 0: m=self.deviceMonitors.pop(0) m.running=False self.clearEventBuffer() try: self.closeDataStoreFile() except: pass while len(self.devices) > 0: d=self.devices.pop(0) try: if d is not None: d._close() except: pass gevent.sleep() except: ioHub.print2err("Error in ioSever.shutdown():") ioHub.printExceptionDetailsToStdErr()
def run(initial_time_offset,rootScriptPathDir,configFilePath): import tempfile tdir=tempfile.gettempdir() cdir,cfile=os.path.split(configFilePath) if tdir==cdir: tf=open(configFilePath) msgpk_unpacker.feed(tf.read()) ioHubConfig=msgpk_unpack() tf.close() os.remove(configFilePath) else: ioHubConfig=load(file(configFilePath,'r'), Loader=Loader) try: s = ioServer(initial_time_offset, rootScriptPathDir, ioHubConfig) except Exception,e: ioHub.printExceptionDetailsToStdErr() sys.stdout.flush() try: s.shutdown() except: pass return -1
def displayCoord2Pixel( cls, dx, dy, ): try: dw, dh = cls.getScreenResolution() coordSpace = cls.getDisplayCoordinateType() if coordSpace == 'pix': px = dx + dw / 2 py = (dy + dh / 2) return px, py elif coordSpace == 'deg': ioHub.print2err( ">>>> getDisplayCoordinateType for degrees not implemented yet.: " + coordSpace) return 0.0, 0.0 else: ioHub.print2err(">>>> UNIMPLEMENTED dispCoordType: " + coordSpace) return 0.0, 0.0 except Exception, e: ioHub.print2err('ERROR displayCoord2Pixel: ' + str(e)) ioHub.printExceptionDetailsToStdErr() return 0.0, 0.0
def pixel2DisplayCoord(cls, px, py): try: dw, dh = cls.getScreenResolution() coordSpace = cls.getDisplayCoordinateType() dx = px - dw / 2 dy = -(py - dh / 2) if coordSpace == 'pix': return dx, dy elif coordSpace == 'deg': #distH,distV=cls.pixelToDist(swidth/float(pixHres),sheight/float(pixVres),swidth,sheight,px,py) #eyeDist=cls._settings['default_eye_to_calibration_surface_distance']['plane_center'] #r=cls.convertDistToNd(eyeDist,distH,distV) #ioHub.print2stderr(">>>> Pixels x,y to Angle h,v: "+str((px,py))+" : "+str(r)) ioHub.print2err(">>>> UNIMPLEMENTED dispCoordType: " + coordSpace) return 0.0, 0.0 else: ioHub.print2err(">>>> UNKNOWN dispCoordType: " + coordSpace) return 0.0, 0.0 except Exception, e: ioHub.print2err('ERROR pixel2DisplayCoord: ' + str(e)) ioHub.printExceptionDetailsToStdErr() return 0.0, 0.0
def checkIfSessionCodeExists(self,sessionCode): try: if self.iohub.emrt_file: return self.iohub.emrt_file.checkIfSessionCodeExists(sessionCode) return False except: ioHub.printExceptionDetailsToStdErr()
def _nativeEventCallback(self, event): try: if self.isReportingEvents(): logged_time = getTime() event_array = event[0] if event_array[4] == EventConstants.KEYBOARD_PRESS: repeat_pressed_count = event_array[-7] if self._report_auto_repeats is False and repeat_pressed_count > 0: return True event_array[3] = Computer._getNextEventID() mod_key = event_array[-3] if mod_key in self._modifier_states.keys(): current_state = self._modifier_states[mod_key] if event_array[4] == EventConstants.KEYBOARD_PRESS and current_state is False: self._modifier_states[mod_key] = True self._modifier_value += KeyboardConstants._modifierCodes.getID(mod_key) elif event_array[4] == EventConstants.KEYBOARD_RELEASE and current_state is True: self._modifier_states[mod_key] = False self._modifier_value -= KeyboardConstants._modifierCodes.getID(mod_key) event_array[-2] = self._modifier_value self._addNativeEventToBuffer(event_array) self._last_callback_time = logged_time except: printExceptionDetailsToStdErr() # Must return original event or no mouse events will get to OSX! return 1
def pixel2DisplayCoord(cls,px,py): try: dw,dh=cls.getScreenResolution() coordSpace=cls.getDisplayCoordinateType() dx= px-dw/2 dy=-(py-dh/2) if coordSpace == 'pix': return dx,dy elif coordSpace == 'deg': #distH,distV=cls.pixelToDist(swidth/float(pixHres),sheight/float(pixVres),swidth,sheight,px,py) #eyeDist=cls._settings['default_eye_to_calibration_surface_distance']['plane_center'] #r=cls.convertDistToNd(eyeDist,distH,distV) #ioHub.print2stderr(">>>> Pixels x,y to Angle h,v: "+str((px,py))+" : "+str(r)) ioHub.print2err(">>>> UNIMPLEMENTED dispCoordType: "+coordSpace) return 0.0,0.0 else: ioHub.print2err(">>>> UNKNOWN dispCoordType: "+coordSpace) return 0.0,0.0 except Exception, e: ioHub.print2err('ERROR pixel2DisplayCoord: '+str(e)) ioHub.printExceptionDetailsToStdErr() return 0.0,0.0
def __init__(self, *args, **kwargs): """ """ AnalogInputDevice.__init__(self, *args, **kwargs) self._labjack=None if self.model_name in self._SUPPORTED_MODELS.keys(): try: self._labjack = self._SUPPORTED_MODELS[self.model_name]() self._calibration_data=self._labjack.getCalibrationData() self._labjack.streamConfig( NumChannels = self.input_channel_count, ChannelNumbers = range(self.input_channel_count), ChannelOptions = [ 0 ]*self.input_channel_count, SettlingFactor = self.settling_factor, ResolutionIndex = self.resolution_index, SampleFrequency = self.channel_sampling_rate) self._data_streaming_thread=LabJackDataReader(self) self._data_streaming_thread.start() except: ioHub.print2err("ERROR DURING LABJACK INIT") ioHub.printExceptionDetailsToStdErr() else: ioHub.print2err("AnalogInput Model %s is not supported. Supported models are %s, using model_name parameter."%(self.model_name,str(self._SUPPORTED_MODELS.keys()),)) raise ioDeviceError(self,"AnalogInput Model not supported: %s"%(self.model_name)) sys.exit(0) self._scan_count=0
def run(self): getTime=Computer.getTime try: self.running = True while self.running: # wait for threading event to become True self.stream_start_time_pre=None self.stream_start_time_post=None self.stream_stop_time=None self.request_count = 0 self.channel_array_read_count = 0 self.missed_count = 0 self.error_count = 0 self.stream_data_event.wait(None) # start streaming self.stream_start_time_pre = getTime() self.labjack_device.streamStart() self.stream_start_time_post = getTime() # Stream until either the ioHub server has set running to False, # or until threading event is False again while self.running and self.isStreamingData(): # Calling with convert = False, # because we are going to convert in the main thread. returnDict = self.labjack_device.streamData(convert = False).next() # record and print any errors during streaming if returnDict['errors'] != 0: self.error_count+=returnDict['errors'] ioHub.print2err('ERRORS DURING LABJACK STREAMING: current: {0} total: {1}'.format(returnDict['errors'],self.error_count)) if returnDict['missed'] != 0: self.missed_count+=returnDict['missed'] ioHub.print2err('DROPPED SAMPLES DURING LABJACK STREAMING: current: {0} total: {1}'.format(returnDict['missing'],self.missed_count)) # put a copy of the new analog input events in the queue for pickup by the ioHub Device Poll self.iohub_device._nativeEventCallback([self.stream_start_time_pre, self.stream_start_time_post, copy.deepcopy(self.labjack_device.processStreamData(returnDict['result']))]) self.request_count += 1 self.labjack_device.streamStop() self.stream_stop_time=getTime() total = self.request_count * self.labjack_device.packetsPerRequest * self.labjack_device.streamSamplesPerPacket total -= self.missed_count run_time = self.stream_stop_time-self.stream_start_time_post ioHub.print2err("%s samples / %s seconds = %s Hz" % ( total, run_time, float(total)/run_time )) self.iohub_device=None self.labjack_device=None except: ioHub.print2err("ERROR IN THREAD RUN:") ioHub.printExceptionDetailsToStdErr()
def flush(self): try: if self.emrtFile: self.emrtFile.flush() except ClosedFileError: pass except: ioHub.printExceptionDetailsToStdErr()
def shutDown(self): try: self.disableHighPriority() self.iohub.shutdown() self._running=False self.stop() except: ioHub.print2err("Error in ioSever.shutdown():") ioHub.printExceptionDetailsToStdErr() sys.exit(1)
def getPositionAndChange(self): try: cpos=self._position lpos=self._lastPosition change_x=cpos[0]-lpos[0] change_y=cpos[1]-lpos[1] if change_x or change_y: return cpos, (change_x,change_y) return cpos, None except Exception, e: ioHub.print2err(">>ERROR getPositionAndChange: "+str(e)) ioHub.printExceptionDetailsToStdErr() return (0.0,0.0),(0.0,0.0)
def getPositionAndChange(self): try: cpos = self._position lpos = self._lastPosition change_x = cpos[0] - lpos[0] change_y = cpos[1] - lpos[1] if change_x or change_y: return cpos, (change_x, change_y) return cpos, None except Exception, e: ioHub.print2err(">>ERROR getPositionAndChange: " + str(e)) ioHub.printExceptionDetailsToStdErr() return (0.0, 0.0), (0.0, 0.0)
def _initializeConditionVariableTable(self,experiment_id,np_dtype): experimentConditionVariableTable=None self._EXP_COND_DTYPE=N.dtype(np_dtype) try: expCondTableName="EXP_CV_%d"%(experiment_id) experimentConditionVariableTable=self.emrtFile.root.data_collection.condition_variables._f_getChild(expCondTableName) self.TABLES['EXP_CV']=experimentConditionVariableTable except NoSuchNodeError, nsne: try: experimentConditionVariableTable=self.emrtFile.createTable(self.emrtFile.root.data_collection.condition_variables,expCondTableName,self._EXP_COND_DTYPE,title='Condition Variables for Experiment id %d'%(experiment_id)) self.TABLES['EXP_CV']=experimentConditionVariableTable self.emrtFile.flush() except: ioHub.printExceptionDetailsToStdErr() return False
def _poll(self): sTime=int(currentUsec()) try: ci=0 if self._lastPollTime is not None: ci=sTime-self._lastPollTime self._joystickButtonStates[0]=self._joystickButtonStates[1] self._joystickPositionStates[0]=self._joystickPositionStates[1] self._joystickButtonStates[1]=glfw.GetJoystickButtons(self._jid) self._joystickPositionStates[1]=glfw.GetJoystickPos(self._jid) if not N.array_equal(self._joystickPositionStates[1],self._joystickPositionStates[0]): #ioHub.print2stderr("Joystick Position Event: "+str(self._jid)+' : '+str(self._joystickPositionStates[1]-self._joystickPositionStates[0])) #jpe= [0,0,Computer.getNextEventID(),ioHub.devices.EventConstants.EVENT_TYPES['JOYSTICK_POSITIONAL_EVENT'], # ioHub.DEVICE_TYPES['JOYSTICK_DEVICE'], self.instance_code, currentTime, # currentTime, currentTime, ci,ci/2.0,self.base_address,self.address_offset,currentValue,lrv] #self.I_nativeEventBuffer.append(jbe) pass if not N.array_equal(self._joystickButtonStates[1],self._joystickButtonStates[0]): #ioHub.print2stderr("Joystick Button Event: "+str(self._jid)+' : '+str(self._joystickButtonStates[1]-self._joystickButtonStates[0])) bchanges=self._joystickButtonStates[1]-self._joystickButtonStates[0] multibuttonEventCount=N.count_nonzero(bchanges) devicetype=ioHub.devices.EventConstants.DEVICE_TYPES['JOYSTICK_DEVICE'] for i, bstate in enumerate(bchanges): is_pressed = 0 etype=None button_id=i+1 if bstate < 0: is_pressed = False etype=ioHub.devices.EventConstants.EVENT_TYPES['JOYSTICK_BUTTON_RELEASE'] elif bstate > 0 : is_pressed = True etype=ioHub.devices.EventConstants.EVENT_TYPES['JOYSTICK_BUTTON_PRESS'] if etype: jbe= [0,0,Computer.getNextEventID(),etype, self.instance_code, sTime, sTime, sTime, ci, ci/2.0, self._jid, is_pressed, button_id,multibuttonEventCount] #ioHub.print2stderr("Joystick Button Event: "+str(jbe)) self.I_nativeEventBuffer.append(jbe) except Exception as e: ioHub.printExceptionDetailsToStdErr() raise ioHub.devices.ioDeviceError(self,"An error orricced what polling GAMEPAD_%d"%(self._jid+1),e) finally: self._lastPollTime=sTime
def _processDeviceEventIteration(self): for device in self.devices: try: events=device._getNativeEventBuffer() #if events and len(events)>0: # ioHub.print2err("_processDeviceEventIteration.....", device._event_listeners) while len(events)>0: evt=events.popleft() e=device._getIOHubEventObject(evt) if e is not None: for l in device._getEventListeners(e[DeviceEvent.EVENT_TYPE_ID_INDEX]): l._handleEvent(e) except: ioHub.printExceptionDetailsToStdErr() ioHub.print2err("Error in processDeviceEvents: ", device, " : ", len(events), " : ", e) ioHub.print2err("Event type ID: ",e[DeviceEvent.EVENT_TYPE_ID_INDEX], " : " , EventConstants.getName(e[DeviceEvent.EVENT_TYPE_ID_INDEX])) ioHub.print2err("--------------------------------------")
def enableEventReporting(self, enable): try: current = self.isReportingEvents() if current == enable: return enable if AnalogInputDevice.enableEventReporting(self, enable) is True: self._scan_count=0 self._data_streaming_thread.enableDataStreaming(True) else: self._data_streaming_thread.enableDataStreaming(False) except: ioHub.print2err("----- LabJack AnalogInput enableEventReporting ERROR ----") ioHub.printExceptionDetailsToStdErr() ioHub.print2err("---------------------------------------------------------")
def _addRowToConditionVariableTable(self,session_id,data): if self.emrtFile and 'EXP_CV' in self.TABLES and self._EXP_COND_DTYPE is not None: try: etable=self.TABLES['EXP_CV'] for i,d in enumerate(data): if isinstance(d,(list,tuple)): data[i]=tuple(d) np_array= N.array([tuple(data),],dtype=self._EXP_COND_DTYPE) etable.append(np_array) self.bufferedFlush() return True except: ioHub.printExceptionDetailsToStdErr() return False
def displayCoord2Pixel(cls,dx,dy,): try: dw,dh=cls.getScreenResolution() coordSpace=cls.getDisplayCoordinateType() if coordSpace == 'pix': px=dx+dw/2 py=(dy+dh/2) return px,py elif coordSpace == 'deg': ioHub.print2err(">>>> getDisplayCoordinateType for degrees not implemented yet.: "+coordSpace) return 0.0,0.0 else: ioHub.print2err(">>>> UNIMPLEMENTED dispCoordType: "+coordSpace) return 0.0,0.0 except Exception, e: ioHub.print2err('ERROR displayCoord2Pixel: '+str(e)) ioHub.printExceptionDetailsToStdErr() return 0.0,0.0
def runSetupProcedure(self,starting_state=EyeTrackerConstants.DEFAULT_SETUP_PROCEDURE): """ runSetupProcedure performs a calibration routine for the Tobii eye tracking system. The current calibration options are relatively limited for the Tobii ioHub interface compared to a standard Tobii calibration procedure. It is hoped that this will be improved in the ioHub Tobii interface as time permits. Result: bool: True if setup / calibration procedue passed, False otherwise. If false, should likely exit experiment. """ try: calibration_properties=self.getConfiguration().get('calibration') circle_attributes=calibration_properties.get('target_attributes') targetForegroundColor=circle_attributes.get('outer_color') # [r,g,b] of outer circle of targets targetBackgroundColor=circle_attributes.get('inner_color') # [r,g,b] of inner circle of targets screenColor=calibration_properties.get('screen_background_color') # [r,g,b] of screen targetOuterDiameter=circle_attributes.get('outer_diameter') # diameter of outer target circle (in px) targetInnerDiameter=circle_attributes.get('inner_diameter') # diameter of inner target circle (in px) genv=TobiiPsychopyCalibrationGraphics(self, targetForegroundColor=targetForegroundColor, targetBackgroundColor=targetBackgroundColor, screenColor=screenColor, targetOuterDiameter=targetOuterDiameter, targetInnerDiameter=targetInnerDiameter) calibrationOK=genv.runCalibration() genv.window.close() genv._unregisterEventMonitors() genv.clearAllEventBuffers() return calibrationOK except: ioHub.print2err("Error during runSetupProcedure") ioHub.printExceptionDetailsToStdErr() return EyeTrackerConstants.EYETRACKER_ERROR
def sendResponse(self,data,address): packet_data=None try: max_size=client.MAX_PACKET_SIZE/2-20 packet_data=self.pack(data)+'\r\n' packet_data_length=len(packet_data) if packet_data_length>= max_size: num_packets=len(packet_data)/max_size+1 self.sendResponse(('IOHUB_MULTIPACKET_RESPONSE',num_packets),address) for p in xrange(num_packets-1): self.socket.sendto(packet_data[p*max_size:(p+1)*max_size],address) self.socket.sendto(packet_data[(p+1)*max_size:packet_data_length],address) else: self.socket.sendto(packet_data,address) except: ioHub.print2err('Error trying to send data to experiment process:') ioHub.print2err('data length:',len(data)) first_data_element="NO_DATA_AVAILABLE" if data: ioHub.print2err('Data was [{0}]'.format(data)) try: first_data_element=data[0] except: pass packet_data_length=0 if packet_data: packet_data_length=len(packet_data) ioHub.print2err('packet Data length: ',len(packet_data)) ioHub.printExceptionDetailsToStdErr() data=createErrorResult('IOHUB_SERVER_RESPONSE_ERROR', msg="The ioHub Server Failed to send the intended response.", first_data_element=str(first_data_element), packet_data_length=packet_data_length, max_packet_size=max_size) packet_data=self.pack(data)+'\r\n' packet_data_length=len(packet_data) self.socket.sendto(packet_data,address)
def getPixelsPerDegree(self): """ Returns the Display's horizontal and vertical pixels per degree calculation based on the physical Display settings provided by the monitor in the device's configuration file settings and the resolution of the Display reported by the OS. Args: None Returns: tuple: (ppd_x, ppd_y) given the monitors current resolution and the physical settings provided in the device's configuration file. """ try: return self.getConfiguration()['runtime_info']['pixels_per_degree'] except Exception: ioHub.print2err("ERROR GETTING PPD !") ioHub.printExceptionDetailsToStdErr() return ioHub.server.createErrorResult("DEVICE_ATTRIBUTE_ERROR", error_message="An error occurred while calling a display \ instances getPixelsPerDegree() method.", method="Display.getPixelsPerDegree")
def _getIOHubEventObject(self,native_event_data): """ The _getIOHubEventObject method is called by the ioHub Server to convert new native device event objects that have been received to the appropriate ioHub Event type representation. The Tobii ioHub eye tracker implementation uses a callback method to register new native device events with the ioHub Server. Therefore this method converts the native Tobii event data into an appropriate ioHub Event representation. Args: native_event_data: object or tuple of (callback_time, native_event_object) Returns: tuple: The appropriate ioHub Event type in list form. """ try: logged_time,device_event_time,iohub_event_time,data_delay,eye_data_event=native_event_data # TO DO: Convert the middle layer representation of a Tobii data event to # the array format needed by ioHub for the appropriete data type. # TO DO: integrate data into ioHub event handling # eyes[LEFT]['gaze_mm'][0]=eye_data_event.LeftGazePoint3D.x # eyes[LEFT]['gaze_mm'][1]=eye_data_event.LeftGazePoint3D.y # eyes[LEFT]['gaze_mm'][2]=eye_data_event.LeftGazePoint3D.z # eyes[LEFT]['eye_location_norm'][0]=eye_data_event.LeftEyePosition3DRelative.x # eyes[LEFT]['eye_location_norm'][1]=eye_data_event.LeftEyePosition3DRelative.y # eyes[LEFT]['eye_location_norm'][2]=eye_data_event.LeftEyePosition3DRelative.z # eyes[RIGHT]['gaze_mm'][0]=eye_data_event.RightGazePoint3D.x # eyes[RIGHT]['gaze_mm'][1]=eye_data_event.RightGazePoint3D.y # eyes[RIGHT]['gaze_mm'][2]=eye_data_event.RightGazePoint3D.z # eyes[RIGHT]['eye_location_norm'][0]=eye_data_event.RightEyePosition3DRelative.x # eyes[RIGHT]['eye_location_norm'][1]=eye_data_event.RightEyePosition3DRelative.y # eyes[RIGHT]['eye_location_norm'][2]=eye_data_event.RightEyePosition3DRelative.z event_type=EventConstants.BINOCULAR_EYE_SAMPLE left_gaze_x=eye_data_event.LeftGazePoint2D.x left_gaze_y=eye_data_event.LeftGazePoint2D.y right_gaze_x=eye_data_event.RightGazePoint2D.x right_gaze_y=eye_data_event.RightGazePoint2D.y if left_gaze_x != -1 and left_gaze_y != -1: left_gaze_x,left_gaze_y=self._eyeTrackerToDisplayCoords((left_gaze_x,left_gaze_y)) if right_gaze_x != -1 and right_gaze_y != -1: right_gaze_x,right_gaze_y=self._eyeTrackerToDisplayCoords((right_gaze_x,right_gaze_y)) # TO DO: Set CI to be equal to current time error stated in Tobii Sync manager confidenceInterval=0.0 binocSample=[ 0, 0, 0, #device id (not currently used) Computer._getNextEventID(), event_type, device_event_time, logged_time, iohub_event_time, confidenceInterval, data_delay, 0, # filtered id (always 0 right now) left_gaze_x, left_gaze_y, EyeTrackerConstants.UNDEFINED, # Left Eye Angle z eye_data_event.LeftEyePosition3D.x, eye_data_event.LeftEyePosition3D.y, eye_data_event.LeftEyePosition3D.z, EyeTrackerConstants.UNDEFINED, # Left Eye Angle x EyeTrackerConstants.UNDEFINED, # Left Eye Angle y EyeTrackerConstants.UNDEFINED, # Left Camera Sensor position x EyeTrackerConstants.UNDEFINED, # Left Camera Sensor position y eye_data_event.LeftPupil, EyeTrackerConstants.PUPIL_DIAMETER_MM, EyeTrackerConstants.UNDEFINED, # Left pupil size measure 2 EyeTrackerConstants.UNDEFINED, # Left pupil size measure 2 type EyeTrackerConstants.UNDEFINED, # Left PPD x EyeTrackerConstants.UNDEFINED, # Left PPD y EyeTrackerConstants.UNDEFINED, # Left velocity x EyeTrackerConstants.UNDEFINED, # Left velocity y EyeTrackerConstants.UNDEFINED, # Left velocity xy right_gaze_x, right_gaze_y, EyeTrackerConstants.UNDEFINED, # Right Eye Angle z eye_data_event.RightEyePosition3D.x, eye_data_event.RightEyePosition3D.y, eye_data_event.RightEyePosition3D.z, EyeTrackerConstants.UNDEFINED, # Right Eye Angle x EyeTrackerConstants.UNDEFINED, # Right Eye Angle y EyeTrackerConstants.UNDEFINED, #Right Camera Sensor position x EyeTrackerConstants.UNDEFINED, #Right Camera Sensor position y eye_data_event.RightPupil, EyeTrackerConstants.PUPIL_DIAMETER_MM, EyeTrackerConstants.UNDEFINED, # Right pupil size measure 2 EyeTrackerConstants.UNDEFINED, # Right pupil size measure 2 type EyeTrackerConstants.UNDEFINED, # Right PPD x EyeTrackerConstants.UNDEFINED, # Right PPD y EyeTrackerConstants.UNDEFINED, # right velocity x EyeTrackerConstants.UNDEFINED, # right velocity y EyeTrackerConstants.UNDEFINED, # right velocity xy int(str(eye_data_event.LeftValidity)+str(eye_data_event.RightValidity)) ] self._latest_sample=binocSample if eye_data_event.LeftValidity>=2 and eye_data_event.RightValidity >=2: self._latest_gaze_position=None elif eye_data_event.LeftValidity<2 and eye_data_event.RightValidity<2: self._latest_gaze_position=[(right_gaze_x+left_gaze_x)/2.0, (right_gaze_y+left_gaze_y)/2.0] elif eye_data_event.LeftValidity<2: self._latest_gaze_position=[left_gaze_x,left_gaze_y] elif eye_data_event.RightValidity<2: self._latest_gaze_position=[right_gaze_x,right_gaze_y] self._last_callback_time=logged_time return binocSample except: ioHub.printExceptionDetailsToStdErr() return None
def enableEventReporting(self,enable): current=self.isReportingEvents() ioHub.print2err('AnalogInput.enableEventReporting: {0} {1}'.format(current,enable)) if current == enable: return current if AnalogInputDevice.enableEventReporting(self,enable) is True: try: # set sample buffers of the correct type and size based on the a2d resolution if self._a2d_resolution.value > 12: #ioHub.print2err("** Using cbWinBufAlloc for 16 bit card **") self._memory_handle=self._DLL.cbWinBufAlloc(c_int(self._input_sample_buffer_size)) self._sample_data_buffer = cast(self._memory_handle,POINTER(c_uint16)) else: self._memory_handle=self._DLL.cbWinBufAlloc(c_int(self._input_sample_buffer_size)) self._sample_data_buffer = cast(self._memory_handle,POINTER(c_uint16)) # Make sure memory handle to sample buffer is a valid pointer if self._memory_handle == 0: ioHub.print2err("\nERROR ALLOCATING DAQ MEMORY: out of memory\n") sys.exit(1) except: ioHub.print2err('------------- Error creating buffers -----------') ioHub.printExceptionDetailsToStdErr() ioHub.print2err('-------------------------------------------------') # set the device status to RUNNING while events are steaming self._device_status=c_short(RUNNING) # start streaming analog input data from the device self._last_start_recording_time_pre=currentSec() try: self._DLL.cbAInScan(self.device_number, self._local_sample_buffer.low_channel, self._local_sample_buffer.high_channel, c_int(self._input_sample_buffer_size), byref(self.channel_sampling_rate), self.gain, self._memory_handle, self.options) except: ioHub.print2err('------------- Error calling cbAInScan -----------') ioHub.printExceptionDetailsToStdErr() ioHub.print2err('-------------------------------------------------') return ioHub.server.createErrorResult("ANALOGINPUT_START_RECORDING_ERROR", msg="Error occurred calling Measurement Computing function cbAInScan") self._last_start_recording_time_post=currentSec() else: self._DLL.cbStopBackground (self.device_number) # this should be taking board ID and AIFUNCTION # but when ever I give it second param ctypes throws # a `4 bytes too much`error self._device_status=c_short(IDLE) self._local_sample_buffer.zero() # initialize various counters and index values for use during data collection self._current_sample_buffer_index=c_long(0) self._last_sample_buffer_index=c_long(0) self._samples_received_count=c_long(0) self._local_sample_count_created=0 self._last_start_recording_time_pre=0.0 self._last_start_recording_time_post=0.0 if self._memory_handle!=0: result=self._DLL.cbWinBufFree(self._memory_handle) if result != 0: ioHub.print2err("ERROR calling cbWinBufFree TO FREE DAQ MEMORY: {0}".format(result)) return enable
def _nativeEventCallback(self,*args): try: proxy, etype, event, refcon = args if self.isReportingEvents(): logged_time=getTime() if etype == Qz.kCGEventTapDisabledByTimeout: print2err("** WARNING: Keyboard Tap Disabled due to timeout. Re-enabling....: ", etype) Qz.CGEventTapEnable(self._tap, True) return event confidence_interval=logged_time-self._last_poll_time delay=0.0 # No point trying to guess for the keyboard or mouse. # May add a 'default_delay' prefernce to the device config settings, # so if a person knows the average delay for something like the kb or mouse # they are using, then they could specify it in the config file and it could be used here. iohub_time = logged_time-delay device_time=Qz.CGEventGetTimestamp(event)*self.DEVICE_TIME_TO_SECONDS key_code = Qz.CGEventGetIntegerValueField(event, Qz.kCGKeyboardEventKeycode) key_name=None window_number=0 ioe_type=None ucode=0 # the int version of the unicode utf-8 ichar is_auto_repeat= Qz.CGEventGetIntegerValueField(event, Qz.kCGKeyboardEventAutorepeat) #np_key=keyFromNumpad(flags) # This is a modifier state change event, so we need to manually determine # which mod key was either pressed or released that resulted in the state change.... if etype == Qz.kCGEventFlagsChanged: try: ioe_type, key_name=self._handleModifierChangeEvent(event) # print2err('_handleModifierChangeEvent: ',ioe_type, ' ',key_name) except Exception, e: print2err("kCGEventFlagsChanged failed: ",e) printExceptionDetailsToStdErr() else: # This is an actual button press / release event, so handle it.... try: keyEvent = NSEvent.eventWithCGEvent_(event) key_name,ucode,key_code=self._getKeyNameForEvent(keyEvent) window_number=keyEvent.windowNumber() if etype == Qz.kCGEventKeyUp: ioe_type=EventConstants.KEYBOARD_RELEASE elif etype == Qz.kCGEventKeyDown: ioe_type=EventConstants.KEYBOARD_PRESS except Exception,e: print2err("Create NSEvent failed: ",e) printExceptionDetailsToStdErr() if ioe_type: # The above logic resulted in finding a key press or release event # from the expected events OR from modifier state changes. So, # send the iohub event version to ioHub. # # FILL IN AND CREATE EVENT # index 0 and 1 are session and exp. ID's # index 3 is device id (not yet supported) #key_name='£' if ioe_type == EventConstants.KEYBOARD_PRESS: if is_auto_repeat > 0 and self._report_auto_repeats is False: return event if key_name is None or len(key_name)==0: # TO DO: dead char we need to deal with?? key_name=u'DEAD_KEY?' print2err("DEAD KEY HIT?") else: ioe=self._EVENT_TEMPLATE_LIST ioe[3]=Computer._getNextEventID() ioe[4]=ioe_type #event type code ioe[5]=device_time ioe[6]=logged_time ioe[7]=iohub_time ioe[8]=confidence_interval ioe[9]=delay # index 10 is filter id, not used at this time ioe[11]=is_auto_repeat ioe[12]=key_code # Quartz does not give the scancode, so fill this with keycode ioe[13]=key_code #key_code ioe[14]=ucode ioe[15]=key_name.encode('utf-8') ioe[16]=self._mods_sum ioe[17]=window_number self._addNativeEventToBuffer(copy(ioe)) #print2err("**Final values:key_name [",key_name,"] ucode: ",ucode, ' key_code: ',key_code) else: print2err("\nWARNING: KEYBOARD RECEIVED A [ {0} ] KB EVENT, BUT COULD NOT GENERATE AN IOHUB EVENT FROM IT !!".format(etype)," [",key_name,"] ucode: ",ucode, ' key_code: ',key_code) self._last_callback_time=logged_time
ioe[16]=self._mods_sum ioe[17]=window_number self._addNativeEventToBuffer(copy(ioe)) #print2err("**Final values:key_name [",key_name,"] ucode: ",ucode, ' key_code: ',key_code) else: print2err("\nWARNING: KEYBOARD RECEIVED A [ {0} ] KB EVENT, BUT COULD NOT GENERATE AN IOHUB EVENT FROM IT !!".format(etype)," [",key_name,"] ucode: ",ucode, ' key_code: ',key_code) self._last_callback_time=logged_time #cdur=getTime()-logged_time #print2err('callback dur: ',cdur) # Must return original event or no keyboard events will get to OSX! return event except: printExceptionDetailsToStdErr() Qz.CGEventTapEnable(self._tap, False) return event @classmethod def _checkForLeftRightModifiers(cls,mod_state): mod_value=0 mod_strs=[] for k,v in cls._OS_MODIFIERS: if mod_state & k > 0: mod_value+=KeyboardConstants._modifierCodes.getID(v) mod_strs.append(v) return mod_value,mod_strs def _getIOHubEventObject(self,native_event_data):
""" The start method should be called by the main portion of your experiment script. This method simply wraps a call to self.run() in an exception handler that tries to ensure any error that occurs is printed out in detail, and that the ioHub server process is terminates even in the case of an exception that may not have been handled explicitly in your script. Args: None Return: None """ try: self.run() except ioHub.ioHubError, e: print e except: ioHub.printExceptionDetailsToStdErr() finally: # _close ioHub, shut down ioHub process, clean-up..... self._close() def prePostExperimentVariableCallback(self,expVarDict): return expVarDict def prePostSessionVariableCallback(self,sessionVarDict): sess_code=sessionVarDict['code'] scount=1 while self.isSessionCodeNotInUse(sess_code) is True: sess_code='%s-%d'%(sessionVarDict['code'],scount) scount+=1 sessionVarDict['code']=sess_code
def _nativeEventCallback(self, *args): try: proxy, etype, event, refcon = args if self.isReportingEvents(): logged_time = currentSec() if etype == kCGEventTapDisabledByTimeout: ioHub.print2err("** WARNING: Mouse Tap Disabled due to timeout. Re-enabling....: ", etype) CGEventTapEnable(self._tap, True) return event else: confidence_interval = 0.0 delay = 0.0 iohub_time = logged_time device_time = CGEventGetTimestamp(event) * self.DEVICE_TIME_TO_SECONDS ioe_type = EventConstants.UNDEFINED px, py = CGEventGetLocation(event) multi_click_count = CGEventGetIntegerValueField(event, kCGMouseEventClickState) mouse_event = NSEvent.eventWithCGEvent_(event) window_handle = mouse_event.windowNumber() # TO DO: Implement multimonitor location based on mouse location support. # Currently always uses monitor index 0 display_index = self.getDisplayIndexForMousePosition((px, py)) if display_index == -1: if self._last_display_index is not None: display_index = self._last_display_index else: ioHub.print2err( "!!! _nativeEventCallback error: mouse event pos {0} not in any display bounds!!!".format( event.Position ) ) ioHub.print2err("!!! -> SKIPPING EVENT") ioHub.print2err("===============") return event result = self._validateMousePosition((px, py), display_index) if result != True: ioHub.print2err( "!!! _validateMousePosition made ajustment: {0} to {1}".format((px, py), result) ) nx, ny = result display_index = self.getDisplayIndexForMousePosition((nx, ny)) ioHub.print2err( "Going to Update mousePosition: {0} => {1} on D {2}".format( (px, py), (ny, ny), display_index ) ) px, py = nx, ny self._nativeSetMousePos(px, py) px, py = self._display_device.pixel2DisplayCoord(px, py, display_index) self._lastPosition = self._position self._position = px, py self._last_display_index = self._display_index self._display_index = display_index # TO DO: Supported reporting scroll x info for OSX. # This also suggests not having scoll up and down events and # just having the one scroll event type, regardless of direction / dimension scroll_dx = 0 scroll_dy = 0 button_state = 0 if etype in pressID: button_state = MouseConstants.MOUSE_BUTTON_STATE_PRESSED if multi_click_count > 1: ioe_type = EventConstants.MOUSE_MULTI_CLICK else: ioe_type = EventConstants.MOUSE_BUTTON_PRESS elif etype in releaseID: button_state = MouseConstants.MOUSE_BUTTON_STATE_RELEASED ioe_type = EventConstants.MOUSE_BUTTON_RELEASE elif etype in dragID: ioe_type = EventConstants.MOUSE_DRAG elif etype == kCGEventMouseMoved: ioe_type = EventConstants.MOUSE_MOVE elif etype == kCGEventScrollWheel: ioe_type = EventConstants.MOUSE_SCROLL scroll_dy = CGEventGetIntegerValueField(event, kCGScrollWheelEventPointDeltaAxis1) scroll_dx = CGEventGetIntegerValueField(event, kCGScrollWheelEventPointDeltaAxis2) self._scrollPositionX += scroll_dx self._scrollPositionY += scroll_dy iohub_button_id = self._IOHUB_BUTTON_ID_MAPPINGS.get(etype, 0) if iohub_button_id in self.activeButtons: self.activeButtons[iohub_button_id] = int( button_state == MouseConstants.MOUSE_BUTTON_STATE_PRESSED ) pressed_buttons = 0 for k, v in self.activeButtons.iteritems(): pressed_buttons += k * v # Create Event List # index 0 and 1 are session and exp. ID's # index 2 is (yet to be used) device_id ioe = self._EVENT_TEMPLATE_LIST ioe[3] = Computer._getNextEventID() ioe[4] = ioe_type # event type code ioe[5] = device_time ioe[6] = logged_time ioe[7] = iohub_time ioe[8] = confidence_interval ioe[9] = delay # index 10 is filter id, not used at this time ioe[11] = display_index ioe[12] = button_state ioe[13] = iohub_button_id ioe[14] = pressed_buttons ioe[15] = px ioe[16] = py ioe[17] = int(scroll_dx) ioe[18] = int(self._scrollPositionX) ioe[19] = int(scroll_dy) ioe[20] = int(self._scrollPositionY) ioe[21] = window_handle self._addNativeEventToBuffer(copy(ioe)) self._last_callback_time = logged_time except: ioHub.printExceptionDetailsToStdErr() CGEventTapEnable(self._tap, False) # Must return original event or no mouse events will get to OSX! return event
def __init__(self, initial_time_offset, rootScriptPathDir, config=None): import ioHub Computer.isIoHubProcess=True Computer.globalClock=ioHub.ioClock(None,initial_time_offset) self._hookManager=None self.emrt_file=None self.config=config self.devices=[] self.deviceMonitors=[] self.sessionInfoDict=None self.experimentInfoList=None self.filterLookupByInput={} self.filterLookupByOutput={} self.filterLookupByName={} ioServer.eventBuffer=deque(maxlen=config.get('global_event_buffer',2048)) ioServer._logMessageBuffer=deque(maxlen=128) self._running=True # start UDP service self.udpService=udpServer(self,':%d'%config.get('udpPort',9000)) # read temp paths file ioHub.data_paths=None try: expJsonPath=os.path.join(rootScriptPathDir,'exp.paths') f=open(expJsonPath,'r') ioHub.data_paths=msgpack.loads(f.read()) f.flush() f.close() os.remove(expJsonPath) except: pass #ioHub.print2err("#### ioHub.data_paths: ",ioHub.data_paths) self._all_device_config_errors=dict() device_instance_list=[] try: #built device list and config from yaml config settings for iodevice in config.get('monitor_devices',()): for device_class_name,deviceConfig in iodevice.iteritems(): #ioHub.print2err("======================================================") #ioHub.print2err("Started load process for: {0}".format(device_class_name)) device_instance_and_config=self.addDeviceToMonitor(device_class_name,deviceConfig) if device_instance_and_config: device_instance_list.append(device_instance_and_config) else: ioHub.print2err('## Device was not started by the ioHub Server: ',device_class_name) raise ioHub.ioHubError("Device config validation failed") DeviceConstants.addClassMappings() EventConstants.addClassMappings() except: ioHub.print2err("Error during device creation ....") ioHub.printExceptionDetailsToStdErr() raise ioHub.ioHubError("Error during device creation ....") try: # dataStore setup if 'data_store' in config: experiment_datastore_config=config.get('data_store') default_datastore_config_path=os.path.join(ioHub.IO_HUB_DIRECTORY,'ioDataStore','default_iodatastore.yaml') _dslabel,default_datastore_config=load(file(default_datastore_config_path,'r'), Loader=Loader).popitem() for default_key,default_value in default_datastore_config.iteritems(): if default_key not in experiment_datastore_config: experiment_datastore_config[default_key]=default_value #ioHub.print2err("Merged ioDataStoreConfig: {0}".format(experiment_datastore_config)) if experiment_datastore_config.get('enable', True): #ioHub.print2err("Creating ioDataStore....") if ioHub.data_paths is None: resultsFilePath=rootScriptPathDir else: resultsFilePath=ioHub.data_paths[u'IOHUB_DATA'] self.createDataStoreFile(experiment_datastore_config.get('filename','events')+'.hdf5',resultsFilePath,'a',experiment_datastore_config) #ioHub.print2err("Created ioDataStore.") except: ioHub.print2err("Error during ioDataStore creation....") ioHub.printExceptionDetailsToStdErr() self.log("Adding ioServer and DataStore event listeners......") # add event listeners for saving events if self.emrt_file is not None: for device_instance,device_instance_config,eventIDs in device_instance_list: if device_instance_config['save_events']: device_instance._addEventListener(self.emrt_file,eventIDs) self.log("DataStore listener for device added: device: %s eventIDs: %s"%(device_instance.__class__.__name__,eventIDs)) #ioHub.print2err("DataStore listener for device added: device: %s eventIDs: %s"%(device_instance.__class__.__name__,eventIDs)) else: #ioHub.print2err("DataStore saving disabled for device: %s"%(device_instance.__class__.__name__,)) self.log("DataStore saving disabled for device: %s"%(device_instance.__class__.__name__,)) else: #ioHub.print2err("DataStore Not Evabled. No events will be saved.") self.log("DataStore Not Enabled. No events will be saved.") # try: # #built filter graph and config from yaml config settings # for iofilters in config.get('filters',()): # for filter_class,filterConfig in iofilters.iteritems(): # self.addFilterToMonitor(filter_class,filterConfig) # except: # ioHub.print2err("Error during filter creation ....") # ioHub.printExceptionDetailsToStdErr() deviceDict=ioServer.deviceDict iohub=self if ('Mouse' in deviceDict or 'Keyboard' in deviceDict): if Computer.system == 'win32': iohub.log("Creating pyHook Monitors....") #ioHub.print2err("Creating pyHook Monitors....") class pyHookDevice(object): def __init__(self): import pyHook self._hookManager=pyHook.HookManager() if 'Mouse' in deviceDict: #ioHub.print2err("Hooking Mouse.....") self._hookManager.MouseAll = deviceDict['Mouse']._nativeEventCallback self._hookManager.HookMouse() if 'Keyboard' in deviceDict: #ioHub.print2err("Hooking Keyboard.....") self._hookManager.KeyAll = deviceDict['Keyboard']._nativeEventCallback self._hookManager.HookKeyboard() iohub.log("WindowsHook PumpEvents Periodic Timer Created.") def _poll(self): import pythoncom # PumpWaitingMessages returns 1 if a WM_QUIT message was received, else 0 if pythoncom.PumpWaitingMessages() == 1: raise KeyboardInterrupt() #ioHub.print2err("Creating pyHook Monitor......") hookMonitor=DeviceMonitor(pyHookDevice(),0.00375) self.deviceMonitors.append(hookMonitor) #ioHub.print2err("Created pyHook Monitor.") elif Computer.system == 'linux2': # TODO: consider switching to xlib-ctypes implementation of xlib # https://github.com/garrybodsworth/pyxlib-ctypes iohub.log("Creating pyXHook Monitors....") import ioHub.devices.pyXHook self._hookManager = ioHub.devices.pyXHook.HookManager() if 'Keyboard' in deviceDict: ioHub.print2err("Hooking Keyboard.....") self._hookManager.HookKeyboard() self._hookManager.KeyDown = deviceDict['Keyboard']._nativeEventCallback self._hookManager.KeyUp = deviceDict['Keyboard']._nativeEventCallback if 'Mouse' in deviceDict: ioHub.print2err("Hooking Mouse.....") self._hookManager.HookMouse() self._hookManager.MouseAllButtonsDown = deviceDict['Mouse']._nativeEventCallback self._hookManager.MouseAllButtonsUp = deviceDict['Mouse']._nativeEventCallback self._hookManager.MouseAllMotion = deviceDict['Mouse']._nativeEventCallback #ioHub.print2err("Starting pyXHook.HookManager.....") self._hookManager.start() iohub.log("pyXHook Thread Created.") #ioHub.print2err("pyXHook.HookManager thread created.") else: # OSX if 'Mouse' in deviceDict: mouseHookMonitor=DeviceMonitor(deviceDict['Mouse'],0.004) self.deviceMonitors.append(mouseHookMonitor) deviceDict['Mouse']._CGEventTapEnable(deviceDict['Mouse']._tap, True) if 'Keyboard' in deviceDict: kbHookMonitor=DeviceMonitor(deviceDict['Keyboard'],0.004) self.deviceMonitors.append(kbHookMonitor) deviceDict['Keyboard']._CGEventTapEnable(deviceDict['Keyboard']._tap, True) # import ioHub.devices.pyXHook # # self._hookManager = ioHub.devices.pyXHook.HookManager() # if 'Keyboard' in deviceDict: # ioHub.print2err("Hooking Keyboard.....") # self._hookManager.HookKeyboard() # self._hookManager.KeyDown = deviceDict['Keyboard']._nativeEventCallback # self._hookManager.KeyUp = deviceDict['Keyboard']._nativeEventCallback # if 'Mouse' in deviceDict: # ioHub.print2err("Hooking Mouse.....") # self._hookManager.HookMouse() # self._hookManager.MouseAllButtonsDown = deviceDict['Mouse']._nativeEventCallback # self._hookManager.MouseAllButtonsUp = deviceDict['Mouse']._nativeEventCallback # self._hookManager.MouseAllMotion = deviceDict['Mouse']._nativeEventCallback # # #ioHub.print2err("Starting pyXHook.HookManager.....") # self._hookManager.start() # iohub.log("pyXHook Thread Created.") #ioHub.print2err("pyXHook.HookManager thread created.") self.log("Time Offset: {0}".format(initial_time_offset))
def _poll(self): try: if self._eyegaze_control is None or not self.isRecordingEnabled(): return False logged_time=Computer.getTime() current_tracker_time=self.trackerSec() sample_count_available=self._eyegaze_control.iNPointsAvailable confidence_interval=logged_time-self._last_poll_time self._last_poll_time=logged_time if sample_count_available ==0: return True if self._eyegaze_control.iNBufferOverflow > 0: # Eye Samples were lost. # TBD what to do here (lof to dataStore log?, log to LC data file?) ioHub.print2err("\nWARNING: %d EyeGaze Eye Samples Have Been Lost.\n"%(self._eyegaze_control.iNBufferOverflow)) for i in range(sample_count_available): pEyeGaze.EgGetData(byref(self._eyegaze_control)) sample_data0=self._eyegaze_control.pstEgData[0] device_event_timestamp=sample_data0.dGazeTimeSec # is this really calculating delay?? event_delay = (current_tracker_time - device_event_timestamp) - (sample_data0.dReportTimeSec - device_event_timestamp) iohub_time=logged_time-event_delay pupil_measure1_type = EyeTrackerConstants.PUPIL_RADIUS_MM if self._camera_count == 1: #monocular event_type=EventConstants.MONOCULAR_EYE_SAMPLE eye = EyeTrackerConstants.UNKNOWN_MONOCULAR gaze_x, gaze_y = self._eyeTrackerToDisplayCoords((sample_data0.iIGaze, sample_data0.iJGaze)) pupil_measure1 = sample_data0.fPupilRadiusMm status = int(sample_data0.bGazeVectorFound) monoSample=[ 0, # experiment_id (filled in by ioHub) 0, # session_id (filled in by ioHub) Computer._getNextEventID(), event_type, device_event_timestamp, logged_time, iohub_time, confidence_interval, event_delay, 0, # ioHub filter id (always 0 now) eye, gaze_x, gaze_y, EyeTrackerConstants.UNDEFINED, # gaze z EyeTrackerConstants.UNDEFINED, # x eye pos in space EyeTrackerConstants.UNDEFINED, # y eye pos in space EyeTrackerConstants.UNDEFINED, # z eye pos in space EyeTrackerConstants.UNDEFINED, # eye angle in head x EyeTrackerConstants.UNDEFINED, # eye angle in head y EyeTrackerConstants.UNDEFINED, # uncalibrated x eye pos EyeTrackerConstants.UNDEFINED, # uncalibrated y eye pos pupil_measure1, pupil_measure1_type, EyeTrackerConstants.UNDEFINED, # pupil measure 2 EyeTrackerConstants.UNDEFINED, # pupil measure 2 type EyeTrackerConstants.UNDEFINED, # pixels per degree x EyeTrackerConstants.UNDEFINED, # pixels per degree y EyeTrackerConstants.UNDEFINED, # sample velocity x EyeTrackerConstants.UNDEFINED, # sample velocity y EyeTrackerConstants.UNDEFINED, # 2D sample velocity status ] self._latest_gaze_position=gaze_x,gaze_y self._latest_sample=monoSample self._addNativeEventToBuffer(monoSample) elif self._camera_count == 2: #binocular event_type=EventConstants.MONOCULAR_EYE_SAMPLE sample_data1=self._eyegaze_control.pstEgData[1] sample_data4=self._eyegaze_control.pstEgData[4] left_gaze_x, left_gaze_y = self._eyeTrackerToDisplayCoords( (sample_data4.iIGaze,sample_data4.iJGaze)) right_gaze_x, right_gaze_y = self._eyeTrackerToDisplayCoords( (sample_data1.iIGaze,sample_data1.iJGaze)) left_pupil_measure1 = sample_data4.fPupilRadiusMm right_pupil_measure1 = sample_data1.fPupilRadiusMm status = int(sample_data4.bGazeVectorFound*2+sample_data1.bGazeVectorFound) binocSample=[ 0, # experiment_id (filled in by ioHub) 0, # session_id (filled in by ioHub) Computer._getNextEventID(), event_type, device_event_timestamp, logged_time, iohub_time, confidence_interval, event_delay, 0, # ioHub filter id (always 0 now) # LEFT EYE DATA left_gaze_x, left_gaze_y, EyeTrackerConstants.UNDEFINED, # gaze z EyeTrackerConstants.UNDEFINED, # x eye pos in space EyeTrackerConstants.UNDEFINED, # y eye pos in space EyeTrackerConstants.UNDEFINED, # z eye pos in space EyeTrackerConstants.UNDEFINED, # eye angle in head x EyeTrackerConstants.UNDEFINED, # eye angle in head y EyeTrackerConstants.UNDEFINED, # uncalibrated x eye pos EyeTrackerConstants.UNDEFINED, # uncalibrated y eye pos left_pupil_measure1, pupil_measure_type, EyeTrackerConstants.UNDEFINED, # pupil measure 2 EyeTrackerConstants.UNDEFINED, # pupil measure 2 type EyeTrackerConstants.UNDEFINED, # pixels per degree x EyeTrackerConstants.UNDEFINED, # pixels per degree y EyeTrackerConstants.UNDEFINED, # sample velocity x EyeTrackerConstants.UNDEFINED, # sample velocity y EyeTrackerConstants.UNDEFINED, # 2D sample velocity right_gaze_x, right_gaze_y, EyeTrackerConstants.UNDEFINED, # gaze z EyeTrackerConstants.UNDEFINED, # x eye pos in space EyeTrackerConstants.UNDEFINED, # y eye pos in space EyeTrackerConstants.UNDEFINED, # z eye pos in space EyeTrackerConstants.UNDEFINED, # eye angle in head x EyeTrackerConstants.UNDEFINED, # eye angle in head y EyeTrackerConstants.UNDEFINED, # uncalibrated x eye pos EyeTrackerConstants.UNDEFINED, # uncalibrated y eye pos right_pupil_measure1, pupil_measure_type, EyeTrackerConstants.UNDEFINED, # pupil measure 2 EyeTrackerConstants.UNDEFINED, # pupil measure 2 type EyeTrackerConstants.UNDEFINED, # pixels per degree x EyeTrackerConstants.UNDEFINED, # pixels per degree y EyeTrackerConstants.UNDEFINED, # sample velocity x EyeTrackerConstants.UNDEFINED, # sample velocity y EyeTrackerConstants.UNDEFINED, # 2D sample velocity status ] self._latest_sample=binocSample g=[0.0,0.0] if right_pupil_measure1>0.0 and left_pupil_measure1>0.0: g=[(left_gaze_x+right_gaze_x)/2.0,(left_gaze_y+right_gaze_y)/2.0] elif left_pupil_measure1>0.0: g=[left_gaze_x,left_gaze_y] elif right_pupil_measure1>0.0: g=[right_gaze_x,right_gaze_y] self._latest_gaze_position=g self._addNativeEventToBuffer(binocSample) else: # WTF ioHub.print2err("ERROR: EyeGaze reported camers count is invalid: ",self._camera_count) # Code below can be reused if fixation event detection is added. # # elif isinstance(ne,pylink.EndFixationEvent): # etype=EventConstants.FIXATION_END # # estatus = ne.getStatus() # # which_eye=ne.getEye() # if which_eye: # which_eye=EyeTrackerConstants.RIGHT_EYE # else: # which_eye=EyeTrackerConstants.LEFT_EYE # # start_event_time= ne.getStartTime()*DEVICE_TIMEBASE_TO_SEC # end_event_time = ne.event_timestamp # event_duration = end_event_time-start_event_time # # fee=[0, # 0, # Computer._getNextEventID(), # etype, # ne.event_timestamp, # ne.logged_time, # ne.timestamp, # confidenceInterval, # ne.event_delay, # 0, # which_eye, # event_duration, # s_gaze[0], # s_gaze[1], # EyeTrackerConstants.UNDEFINED, # s_href[0], # s_href[1], # EyeTrackerConstants.UNDEFINED, # EyeTrackerConstants.UNDEFINED, # s_pupilsize, # EyeTrackerConstants.PUPIL_AREA, # EyeTrackerConstants.UNDEFINED, # EyeTrackerConstants.UNDEFINED, # s_ppd[0], # s_ppd[1], # EyeTrackerConstants.UNDEFINED, # EyeTrackerConstants.UNDEFINED, # s_vel, # e_gaze[0], # e_gaze[1], # EyeTrackerConstants.UNDEFINED, # e_href[0], # e_href[1], # EyeTrackerConstants.UNDEFINED, # EyeTrackerConstants.UNDEFINED, # e_pupilsize, # EyeTrackerConstants.PUPIL_AREA, # EyeTrackerConstants.UNDEFINED, # EyeTrackerConstants.UNDEFINED, # e_ppd[0], # e_ppd[1], # EyeTrackerConstants.UNDEFINED, # EyeTrackerConstants.UNDEFINED, # e_vel, # a_gaze[0], # a_gaze[1], # EyeTrackerConstants.UNDEFINED, # a_href[0], # a_href[1], # EyeTrackerConstants.UNDEFINED, # EyeTrackerConstants.UNDEFINED, # a_pupilsize, # EyeTrackerConstants.PUPIL_AREA, # EyeTrackerConstants.UNDEFINED, # EyeTrackerConstants.UNDEFINED, # EyeTrackerConstants.UNDEFINED, # EyeTrackerConstants.UNDEFINED, # EyeTrackerConstants.UNDEFINED, # EyeTrackerConstants.UNDEFINED, # a_vel, # EyeTrackerConstants.UNDEFINED, # EyeTrackerConstants.UNDEFINED, # peak_vel, # estatus # ] # #EyeTracker._eventArrayLengths['FIXATION_END']=len(fee) # self._addNativeEventToBuffer(fee) # elif isinstance(ne,pylink.StartFixationEvent): # etype=EventConstants.FIXATION_START # # which_eye=ne.getEye() # if which_eye: # which_eye=EyeTrackerConstants.RIGHT_EYE # else: # which_eye=EyeTrackerConstants.LEFT_EYE # # # se=[ # 0, # exp ID # 0, # sess ID # Computer._getNextEventID(), # event ID # etype, # event type # ne.event_timestamp, # ne.logged_time, # ne.timestamp, # confidenceInterval, # ne.event_delay, # 0, # which_eye, # eye # gaze[0], # gaze x # gaze[1], # gaze y # EyeTrackerConstants.UNDEFINED, # gaze z # href[0], # angle x # href[1], # angle y # EyeTrackerConstants.UNDEFINED, # raw x # EyeTrackerConstants.UNDEFINED, # raw y # pupil_size, # pupil area # EyeTrackerConstants.PUPIL_AREA, # pupil measure type 1 # EyeTrackerConstants.UNDEFINED, # pupil measure 2 # EyeTrackerConstants.UNDEFINED, # pupil measure 2 type # ppd[0], # ppd x # ppd[1], # ppd y # EyeTrackerConstants.UNDEFINED, # velocity x # EyeTrackerConstants.UNDEFINED, # velocity y # velocity, # velocity xy # estatus # status # ] # self._addNativeEventToBuffer(se) except Exception: ioHub.print2err("ERROR occurred during poll:") ioHub.printExceptionDetailsToStdErr()
def _poll(self): sTime = int(currentUsec()) try: ci = 0 if self._lastPollTime is not None: ci = sTime - self._lastPollTime self._joystickButtonStates[0] = self._joystickButtonStates[1] self._joystickPositionStates[0] = self._joystickPositionStates[1] self._joystickButtonStates[1] = glfw.GetJoystickButtons(self._jid) self._joystickPositionStates[1] = glfw.GetJoystickPos(self._jid) if not N.array_equal(self._joystickPositionStates[1], self._joystickPositionStates[0]): #ioHub.print2stderr("Joystick Position Event: "+str(self._jid)+' : '+str(self._joystickPositionStates[1]-self._joystickPositionStates[0])) #jpe= [0,0,Computer.getNextEventID(),ioHub.devices.EventConstants.EVENT_TYPES['JOYSTICK_POSITIONAL_EVENT'], # ioHub.DEVICE_TYPES['JOYSTICK_DEVICE'], self.instance_code, currentTime, # currentTime, currentTime, ci,ci/2.0,self.base_address,self.address_offset,currentValue,lrv] #self.I_nativeEventBuffer.append(jbe) pass if not N.array_equal(self._joystickButtonStates[1], self._joystickButtonStates[0]): #ioHub.print2stderr("Joystick Button Event: "+str(self._jid)+' : '+str(self._joystickButtonStates[1]-self._joystickButtonStates[0])) bchanges = self._joystickButtonStates[ 1] - self._joystickButtonStates[0] multibuttonEventCount = N.count_nonzero(bchanges) devicetype = ioHub.devices.EventConstants.DEVICE_TYPES[ 'JOYSTICK_DEVICE'] for i, bstate in enumerate(bchanges): is_pressed = 0 etype = None button_id = i + 1 if bstate < 0: is_pressed = False etype = ioHub.devices.EventConstants.EVENT_TYPES[ 'JOYSTICK_BUTTON_RELEASE'] elif bstate > 0: is_pressed = True etype = ioHub.devices.EventConstants.EVENT_TYPES[ 'JOYSTICK_BUTTON_PRESS'] if etype: jbe = [ 0, 0, Computer.getNextEventID(), etype, self.instance_code, sTime, sTime, sTime, ci, ci / 2.0, self._jid, is_pressed, button_id, multibuttonEventCount ] #ioHub.print2stderr("Joystick Button Event: "+str(jbe)) self.I_nativeEventBuffer.append(jbe) except Exception as e: ioHub.printExceptionDetailsToStdErr() raise ioHub.devices.ioDeviceError( self, "An error orricced what polling GAMEPAD_%d" % (self._jid + 1), e) finally: self._lastPollTime = sTime