def main(self, *args, **kwargs): t = get_time() # Update sawtooth a = 1. p = 2. sawtooth = - 2 * a / np.pi * np.arctan(1. / np.tan(np.pi * t / p)) self.sawtooth_attr.write(sawtooth) # Update poisson_1p200 if self.poisson_high_end >= get_time(): new_state = True else: self.poisson_high_end = 0. new_state = np.random.randint(200) == 0 if new_state: # Show high state for 5ms self.poisson_high_end = get_time() + 0.005 self.poisson_1p20_attr.write(new_state)
def start_phase(self): self.start_visual() self.set_record_group_attrs({ 'start_time': get_time(), 'visual_module': self.current_visual.__module__, 'visual_name': str(self.current_visual.__class__.__qualname__), 'target_duration': self.current_protocol.current_phase.duration, 'target_sample_rate': config.CONF_DISPLAY_FPS })
def main(self, *args, **kwargs): t = get_time() self.whitenoise.write(3. * np.random.normal() + np.sin(t * 2. * np.pi * 20) + np.sin(t * 2. * np.pi * 180))
def main(self, *args, **kwargs): t = get_time() sig = int(t / 2) % 2 self.test_onoff.write(sig)
def main(self, **frames): # Read frame frame = frames.get(self.camera_device_id) # Check if frame was returned if frame is None: return # Reduce to mono if frame.ndim > 2: frame = frame[:,:,0] # Write frame to buffer self.frame.write(frame.T) # Do eye detection and angular position estimation if not bool(self.rois): return # If eyes were marked: iterate over ROIs and extract eye positions saccade_happened = False for id, rect_params in self.rois.items(): #### # Extract rectanglular ROI # Convert from pyqtgraph image coordinates to openCV # rect_params = (tuple(self.coord_transform_pg2cv(rect_params[0])), tuple(rect_params[1]), -rect_params[2],) # Get rect and frame parameters center, size, angle = rect_params[0], rect_params[1], rect_params[2] center, size = tuple(map(int, center)), tuple(map(int, size)) height, width = frame.shape[0], frame.shape[1] # Rotate M = cv2.getRotationMatrix2D(center, angle, 1) rotFrame = cv2.warpAffine(frame, M, (width, height)) # Crop rect from frame cropRect = cv2.getRectSubPix(rotFrame, size, center) # Rotate rect so that "up" direction in image corresponds to "foward" for the fish center = (size[0]/2, size[1]/2) width, height = size M = cv2.getRotationMatrix2D(center, 90, 1) absCos = abs(M[0, 0]) absSin = abs(M[0, 1]) # New bound width/height wBound = int(height * absSin + width * absCos) hBound = int(height * absCos + width * absSin) # Subtract old image center M[0, 2] += wBound / 2 - center[0] M[1, 2] += hBound / 2 - center[1] # Rotate rot_rect = cv2.warpAffine(cropRect, M, (wBound, hBound)) #### # Calculate eye angular POSITIONS # Apply detection function on cropped rect which contains eyes (le_pos, re_pos), new_rect = self.from_ellipse(rot_rect) # Get shared attributes le_pos_attr = get_attribute(f'{self.ang_le_pos_prefix}{id}') re_pos_attr = get_attribute(f'{self.ang_re_pos_prefix}{id}') le_vel_attr = get_attribute(f'{self.ang_le_vel_prefix}{id}') re_vel_attr = get_attribute(f'{self.ang_re_vel_prefix}{id}') le_sacc_attr = get_attribute(f'{self.le_sacc_prefix}{id}') re_sacc_attr = get_attribute(f'{self.re_sacc_prefix}{id}') rect_roi_attr = get_attribute(f'{self.extracted_rect_prefix}{id}') # Calculate eye angular VELOCITIES _, _, last_le_pos = le_pos_attr.read() last_le_pos = last_le_pos[0] _, last_time, last_re_pos = re_pos_attr.read() last_re_pos = last_re_pos[0] last_time = last_time[-1] if last_time is None: last_time = -np.inf # Calculate time elapsed since last frame current_time = get_time() dt = (current_time - last_time) # Calculate velocities le_vel = np.abs((le_pos - last_le_pos) / dt) re_vel = np.abs((re_pos - last_re_pos) / dt) # Calculate saccade trigger _, _, last_le_vel = le_vel_attr.read() last_le_vel = last_le_vel[0] _, _, last_re_vel = re_vel_attr.read() last_re_vel = last_re_vel[0] le_sacc = int(last_le_vel < self.saccade_threshold < le_vel) re_sacc = int(last_re_vel < self.saccade_threshold < re_vel) is_saccade = bool(le_sacc) or bool(re_sacc) saccade_happened = saccade_happened or is_saccade if is_saccade: self.emit_trigger('saccade_trigger') # Write to buffer le_pos_attr.write(le_pos) re_pos_attr.write(re_pos) le_vel_attr.write(le_vel) re_vel_attr.write(re_vel) le_sacc_attr.write(le_sacc) re_sacc_attr.write(re_sacc) # Set current rect ROI data rect_roi_attr.write(new_rect) self.saccade_trigger.write(saccade_happened)
def _handle_protocol(self): """Method can be called by all processes that in some way respond to the protocol control states. Returns True of protocol is currently running and False if not. """ if self.name not in self._protocolized: return ######## # RUNNING if self.in_state(State.RUNNING): # If phase stoptime is exceeded: end phase phase_stop = vxipc.Control.Protocol[ProtocolCtrl.phase_stop] if phase_stop is not None and phase_stop < time.time(): self.set_record_group_attrs({'end_time': api.get_time()}) # Call implementation of end_phase self.end_phase() self.set_state(State.PHASE_END) # Do NOT execute return False # Default: set phase time and execute protocol self.phase_time = time.time() - self.phase_start_time # Execute return True # IDLE elif self.in_state(State.IDLE): # Check if new protocol is set and prepare it on module-side if self.in_state(State.PREPARE_PROTOCOL, PROCESS_CONTROLLER): # Fetch protocol class _protocol = vxprotocol.get_protocol(vxipc.Control.Protocol[ProtocolCtrl.name]) if _protocol is None: # Controller should abort this return # Instantiate protocol self.current_protocol = _protocol() # Call implemented preparation function of module self.prepare_protocol() # Set next state self.set_state(State.WAIT_FOR_PHASE) # Do NOT execute return False # WAIT_FOR_PHASE elif self.in_state(State.WAIT_FOR_PHASE): if not self.in_state(State.PREPARE_PHASE, PROCESS_CONTROLLER): return False # Set record group to write to in file if not self._disable_phases: self.set_record_group(f'phase{vxipc.Control.Recording[RecCtrl.record_group_counter]}') # Set current phase self.current_protocol.current_phase_id = vxipc.Control.Protocol[ProtocolCtrl.phase_id] # Prepare implemented phase initialization self.prepare_phase() # Set next state self.set_state(State.READY) # Do NOT execute return False # READY elif self.in_state(State.READY): # If Controller is not yet running, don't wait for go time, because there may be an abort if not self.in_state(State.RUNNING, PROCESS_CONTROLLER): return False # Wait for go-time phase_id = vxipc.Control.Protocol[ProtocolCtrl.phase_id] while self.in_state(State.RUNNING, PROCESS_CONTROLLER): now = time.time() if vxipc.Control.Protocol[ProtocolCtrl.phase_start] <= now: log.debug(f'Start phase {phase_id} in module {self.name} at {(now-self.program_start_time):.3f}') self.set_state(State.RUNNING) self.phase_start_time = vxipc.Control.Protocol[ProtocolCtrl.phase_start] break # Immediately start phase now self.start_phase() # Execute return True ######## # PHASE_END elif self.in_state(State.PHASE_END): # Ctrl in PREPARE_PHASE -> there's a next phase if self.in_state(State.PREPARE_PHASE, PROCESS_CONTROLLER): self.set_state(State.WAIT_FOR_PHASE) # Ctrl in PROTOCOL_END -> clean up protocol remnants elif self.in_state(State.PROTOCOL_END, PROCESS_CONTROLLER): # Call implemented module method self.end_protocol() # Set protocol to none self.current_protocol = None # Reset state to idle self.set_state(State.IDLE) # Do NOT execute return False ######## # Fallback: timeout else: pass