def update_rect(self): line_points = self.parent.lines[self.id].listPoints() line_coords = [[line_points[0].x(), line_points[0].y()], [line_points[1].x(), line_points[1].y()]] line_start = np.array(line_coords[0]) lineEnd = np.array(line_coords[1]) line = geometry.vecNormalize(lineEnd - line_start) line_angle_rad = np.arccos( np.dot(geometry.vecNormalize(np.array([-1.0, 0.0])), line)) if line[1] > 0: line_angle_rad = 2 * np.pi - line_angle_rad self.setPos(line_start, finish=False) self.setAngle(360 * line_angle_rad / (2 * np.pi), finish=False) self.translate( -0.5 * self.size().x() * np.array([np.cos(line_angle_rad), np.sin(line_angle_rad)]) + 0.5 * self.size().y() * np.array([np.sin(line_angle_rad), -np.cos(line_angle_rad)]), finish=False) self.rect = [ line_start, np.array(self.size()), 360 * line_angle_rad / (2 * np.pi) ] # Set updates ROI parameters self.parent.roi_params[self.id] = self.rect # Send update to detector routine ipc.rpc(PROCESS_CAMERA, zf_tracking.EyePositionDetection.set_roi, self.id, self.rect)
def rpc(self, function: Callable, *args, **kwargs) -> None: """Send a remote procedure call of given function to another modules. @param process_name: @param function: @param args: @param kwargs: """ vxipc.rpc(self.name, function, *args, **kwargs)
def start_protocol(self): protocol_path = self.protocol_list.currentItem().data(QtCore.Qt.ItemDataRole.UserRole) self.current_protocol = vxprotocol.get_protocol(protocol_path)() # Start recording vxipc.rpc(PROCESS_CONTROLLER, vxmodules.Controller.start_recording) # Start protocol vxipc.rpc(PROCESS_CONTROLLER, vxmodules.Controller.run_protocol, protocol_path)
def prompt_shutdown_confirmation(self): reply = QtWidgets.QMessageBox.question(self.window, 'Confirm shutdown', 'Program is still busy. Shut down anyways?', QtWidgets.QMessageBox.StandardButton.Cancel | QtWidgets.QMessageBox.StandardButton.Yes, QtWidgets.QMessageBox.StandardButton.Cancel) if reply == QtWidgets.QMessageBox.StandardButton.Yes: vxipc.rpc(vxmodules.Controller.name, vxmodules.Controller._force_shutdown)
def _start_shutdown(self): log.debug('Shutdown requested. Checking.') # Check if any processes are still busy shutdown_state = True for p, _ in self._registered_processes: shutdown_state &= self.in_state(definitions.State.IDLE, p.name) or self.in_state(definitions.State.NA, p.name) # Check if recording is running shutdown_state &= not (ipc.Control.Recording[definitions.RecCtrl.active]) if not shutdown_state: log.debug('Not ready for shutdown. Confirming.') ipc.rpc(modules.Gui.name, modules.Gui.prompt_shutdown_confirmation) return self._force_shutdown()
def _update(value): ipc.rpc(PROCESS_DISPLAY, modules.Display.update_visual, {name: value})
def restart_camera(): vxipc.rpc(PROCESS_CONTROLLER, vxmodules.Controller.initialize_process, vxmodules.Camera)
def emit(self): for process_name, callback in self._registered: vxipc.rpc(process_name, callback)
def update_particle_minsize(minsize): ipc.rpc(PROCESS_CAMERA, zf_tracking.EyePositionDetection.set_min_particle_size, minsize)
def display_rpc(function, *args, **kwargs): ipc.rpc(PROCESS_DISPLAY, function, *args, **kwargs)
def controller_rpc(function, *args, **kwargs): ipc.rpc(PROCESS_CONTROLLER, function, *args, **kwargs)
def camera_rpc(function, *args, **kwargs): ipc.rpc(PROCESS_CAMERA, function, *args, **kwargs)
def stop_visual(self): self.clear_layout(self.tuner.layout()) self.tab_widget.setCurrentWidget(self.overview_tab) self.tab_widget.setTabEnabled(1, False) ipc.rpc(PROCESS_DISPLAY, modules.Display.stop_visual)
def _trigger(): ipc.rpc(PROCESS_DISPLAY, modules.Display.trigger_visual, function.__name__)
def toggle_enable(newstate): vxipc.rpc(PROCESS_CONTROLLER, vxmodules.Controller.set_enable_recording, newstate)
def set_compression_opts(self): vxipc.rpc(PROCESS_CONTROLLER, vxmodules.Controller.set_compression_opts, self.get_compression_opts())
def gui_rpc(function, *args, **kwargs): ipc.rpc(PROCESS_GUI, function, *args, **kwargs)
def abort_protocol(self): vxipc.rpc(PROCESS_CONTROLLER, vxmodules.Controller.abort_protocol)
def worker_rpc(function, *args, **kwargs): ipc.rpc(PROCESS_WORKER, function, *args, **kwargs)
def update_sacc_threshold(sacc_thresh): ipc.rpc(PROCESS_CAMERA, zf_tracking.EyePositionDetection.set_saccade_threshold, sacc_thresh)
def io_rpc(function, *args, **kwargs): ipc.rpc(PROCESS_IO, function, *args, **kwargs)
def update_image_threshold(im_thresh): ipc.rpc(PROCESS_CAMERA, zf_tracking.EyePositionDetection.set_threshold, im_thresh)
def set_recording_folder(self): vxipc.rpc(PROCESS_CONTROLLER, vxmodules.Controller.set_recording_folder, self.rec_folder.text())
def register_with_plotter(attr_name: str, *args, **kwargs): ipc.rpc(PROCESS_GUI, core_widgets.PlottingWindow.add_buffer_attribute, attr_name, *args, **kwargs)
def start_recording(): vxipc.rpc(PROCESS_CONTROLLER, vxmodules.Controller.start_manual_recording)
def restart_display(): vxipc.rpc(PROCESS_CONTROLLER, vxmodules.Controller.initialize_process, vxmodules.Display)
def pause_recording(): vxipc.rpc(PROCESS_CONTROLLER, vxmodules.Controller.pause_recording)
def finalize_recording(): # First: pause recording vxipc.rpc(PROCESS_CONTROLLER, vxmodules.Controller.pause_recording) # Finally: stop recording vxipc.rpc(PROCESS_CONTROLLER, vxmodules.Controller.stop_manual_recording)
def start_visual(self, item=False): # Reset label list self._uniform_label_width.clear() # Get item data if not item: item = self.visual_list.currentItem() new_visual = item.data(QtCore.Qt.ItemDataRole.UserRole) if new_visual is None: return # Clear layout self.clear_layout(self.tuner.layout()) # Import visual class visual_module, visual_name = new_visual module = importlib.reload(importlib.import_module(visual_module)) visual_class: Type[vxvisual.AbstractVisual] = getattr( module, visual_name) # Instantiate visual current_visual = visual_class() # Set up parameter widgets for interaction j = 0 # Add static parameters (not meant to be updated at runtime, but still possible) if len(current_visual.static_parameters) > 0: label = QLabel('Static parameters') label.setStyleSheet('font-weight:bold;') self.tuner.layout().addWidget(label, j, 0, 1, 2) j += 1 for i, parameter in enumerate(current_visual.static_parameters): if self._add_parameter_widget(j, parameter): j += 1 # Add variable parameters (meant to be updated online) if len(current_visual.variable_parameters) > 0: label = QLabel('Variable parameters') label.setStyleSheet('font-weight:bold;') self.tuner.layout().addWidget(label, j, 0, 1, 2) j += 1 for i, parameter in enumerate(current_visual.variable_parameters): if self._add_parameter_widget(j, parameter): j += 1 # Set up custom triggers if len(current_visual.trigger_functions) > 0: label = QLabel('Triggers') label.setStyleSheet('font-weight:bold;') self.tuner.layout().addWidget(label, j, 0, 1, 2) j += 1 for trigger_fun in current_visual.trigger_functions: btn = QtWidgets.QPushButton(trigger_fun.__name__) btn.clicked.connect(self.trigger_visual_function(trigger_fun)) self.tuner.layout().addWidget(btn, j, 0, 1, 2) j += 1 # Add spacer for better layout spacer = QtWidgets.QSpacerItem(1, 1, QtWidgets.QSizePolicy.Policy.Minimum, QtWidgets.QSizePolicy.Policy.Expanding) self.tuner.layout().addItem(spacer) # Run visual defaults = { name: wdgt.get_value() for name, wdgt in self._parameter_widgets.items() } ipc.rpc(PROCESS_DISPLAY, modules.Display.run_visual, visual_class, defaults) self.tab_widget.setTabEnabled(1, True) self.tab_widget.setCurrentWidget(self.parameter_tab)