def command_callback(reply): _L().debug('%s.%s()', group, command) # Decode content to raise error, if necessary. try: decode_content_data(reply) except Exception: _L().error('Global command error.', exc_info=True)
def command_callback(reply): _L().debug('%s.%s(%r)', group, command, route_data['route_ids']) # Decode content to raise error, if necessary. try: decode_content_data(reply) except Exception: _L().error('Route command error: %s.%s(%r)', group, command, route_data['route_ids'], exc_info=True)
def command_callback(reply): logger.info('[on_canvas_slave__route_command] %s.%s(%r)', group, command, route_data['route_ids']) # Decode content to raise error, if necessary. try: decode_content_data(reply) except: logger.error('Route command error: %s.%s(%r)', group, command, route_data['route_ids'], exc_info=True)
def on_execute__set_electrode_states(self, request): data = decode_content_data(request) try: return self.set_electrode_states(data['electrode_states'], save=data.get('save', True)) except: logger.error(str(data), exc_info=True)
def on_execute__execute_routes(self, request): data = decode_content_data(request) try: df_routes = self.parent.get_routes() step_options = self.parent.get_step_options() # Set transition duration based on request parameter. If no # duration was provided, use the transition duration from the # current step. transition_duration_ms = data.get('transition_duration_ms', step_options ['transition_duration_ms']) # Set trail length based on request parameter. If no trail length # was provided, use the trail length from the current step. trail_length = data.get('trail_length', step_options['trail_length']) if 'route_i' in data: # A route index was specified. Only process transitions from # specified route. df_routes = df_routes.loc[df_routes.route_i == data['route_i']] elif 'electrode_id' in data and data['electrode_id'] is not None: # An electrode identifier was specified. Only process routes # passing through specified electrode. routes_to_execute = df_routes.loc[df_routes.electrode_i == data['electrode_id'], 'route_i'] # Select only routes that include electrode. df_routes = df_routes.loc[df_routes.route_i .isin(routes_to_execute .tolist())].copy() route_controller = RouteController(self) route_controller.execute_routes(df_routes, transition_duration_ms, trail_length=trail_length) except: logger.error(str(data), exc_info=True)
def on_execute__clear_routes(self, request): data = decode_content_data(request) try: return self.parent.clear_routes(electrode_id= data.get('electrode_id')) except: logger.error(str(data), exc_info=True)
def on_execute__register_command(self, request): data = decode_content_data(request) plugin_name = data.get('plugin_name', request['header']['source']) return self.register_command(plugin_name, data['command_name'], namespace=data.get('namespace', ''), title=data.get('title'))
def on_execute__set_electrode_channels(self, request): ''' Set channels for electrode `electrode_id` to `channels`. This includes updating `self.df_electrode_channels`. .. note:: Existing channels assigned to electrode are overwritten. Parameters ---------- electrode_id : str Electrode identifier. channels : list List of channel identifiers assigned to the electrode. .. versionchanged:: 2.25 Emit ``on_dmf_device_changed`` in main GTK thread to ensure thread-safety. ''' data = decode_content_data(request) app = get_app() modified = (app.dmf_device .set_electrode_channels(data['electrode_id'], data['channels'])) if modified: gtk_threadsafe(emit_signal)("on_dmf_device_changed", [app.dmf_device]) return modified
def on_execute__set_electrode_direction_states(self, request): ''' .. versionadded:: 2.28 Turn on static state of neighbour electrodes in specified direction; turning off existing corresponding electrode state. If no neighbour exists in the specified direction for an electrode, leave the current state unchanged. .. versionchanged:: 2.28.3 Log error traceback to debug level. ''' data = decode_content_data(request) try: direction = data['direction'] app = get_app() electrode_states = self.electrode_states.copy() neighbours = (app.dmf_device.electrode_neighbours .loc[electrode_states.index, direction].dropna()) # For electrodes with a neighbour in the specified direction: # - Turn off current electrode state. electrode_states.loc[neighbours.index] = 0 # - Turn on neighbour electrode state. neighbour_states = pd.Series(1, index=neighbours.values) self.electrode_states = electrode_states.append(neighbour_states) except Exception: logger = _L() # use logger with method context logger.debug(str(data), exc_info=True) gtk_threadsafe(ft.partial(logger.error, str(data)))()
def on_execute__set_video_config(self, request): ''' .. versionchanged:: 0.12 Accept empty video configuration as either `None` or an empty `pandas.Series`. ''' data = decode_content_data(request) compare_fields = ['device_name', 'width', 'height', 'name', 'fourcc', 'framerate'] if data['video_config'] is None or not data['video_config'].shape[0]: i = None else: for i, row in self.parent.video_mode_slave.configs.iterrows(): if (row[compare_fields] == data['video_config'][compare_fields]).all(): break else: i = None if i is None: logger.error('Unsupported video config:\n%s', data['video_config']) logger.error('Video configs:\n%s', self.parent.video_mode_slave.configs) self.parent.video_mode_slave.config_combo.set_active(0) else: logger.error('Set video config (%d):\n%s', i + 1, data['video_config']) self.parent.video_mode_slave.config_combo.set_active(i + 1)
def on_execute__clear_routes(self, request): data = decode_content_data(request) try: return self.parent.clear_routes( electrode_id=data.get('electrode_id')) except Exception: _L().error(str(data), exc_info=True)
def on_execute__channel_impedance_structures(self, request): data = decode_content_data(request) df_channel_impedances = \ self.measure_channel_impedances_monitored(**data) return self.parent.channel_impedance_structures(df_channel_impedances)
def on_execute__register_route_command(self, request): data = decode_content_data(request) logger.info('[register_route_command] %s', data) plugin_name = data.get('plugin_name', request['header']['source']) self.parent.canvas_slave.register_route_command(data['command'], group=plugin_name, title=data .get('title'))
def on_execute__set_dynamic_electrode_states(self, request): ''' .. versionadded:: 0.15 Set dynamic electrode states. ''' data = decode_content_data(request) self.parent.on_dynamic_electrode_states_set(data['electrode_states'])
def on_execute__set_default_corners(self, request): data = decode_content_data(request) if 'canvas' in data and 'frame' in data: for k in ('canvas', 'frame'): self.parent.canvas_slave.default_corners[k] = data[k] self.parent.canvas_slave.reset_canvas_corners() self.parent.canvas_slave.reset_frame_corners() self.parent.canvas_slave.update_transforms()
def on_execute__clear_route_commands(self, request): data = decode_content_data(request) logger.info('[clear_route_commands] %s', data) if 'plugin_name' in data and ( data['plugin_name'] in self.parent.canvas_slave.route_commands): del self.parent.canvas_slave.route_commands[data['plugin_name']] else: self.parent.canvas_slave.route_commands.clear()
def on_execute__clear_route_commands(self, request): data = decode_content_data(request) logger.info('[clear_route_commands] %s', data) if 'plugin_name' in data and (data['plugin_name'] in self.parent.canvas_slave .route_commands): del self.parent.canvas_slave.route_commands[data['plugin_name']] else: self.parent.canvas_slave.route_commands.clear()
def check_sockets(self): """ Check for messages on command and subscription sockets and process any messages accordingly. """ try: msg_frames = self.command_socket.recv_multipart(zmq.NOBLOCK) except zmq.Again: pass else: self.on_command_recv(msg_frames) try: msg_frames = self.subscribe_socket.recv_multipart(zmq.NOBLOCK) source, target, msg_type, msg_json = msg_frames if all([ source == 'microdrop.electrode_controller_plugin', msg_type == 'execute_reply' ]): # The 'microdrop.electrode_controller_plugin' plugin maintains # the requested state of each electrode. msg = json.loads(msg_json) if msg['content']['command'] in ('set_electrode_state', 'set_electrode_states'): data = decode_content_data(msg) self.parent.actuated_area = data['actuated_area'] self.parent.update_channel_states(data['channel_states']) elif msg['content']['command'] == 'get_channel_states': data = decode_content_data(msg) self.parent.actuated_area = data['actuated_area'] self.parent.channel_states =\ self.parent.channel_states.iloc[0:0] self.parent.update_channel_states(data['channel_states']) else: self.most_recent = msg_json except zmq.Again: pass except Exception: logger.error( 'Error processing message from subscription ' 'socket.', exc_info=True) return True
def on_execute__unregister_command(self, request): data = decode_content_data(request) commands = self._commands ix = commands.loc[(commands.namespace == data['namespace']) & (commands.plugin_name == data['plugin_name']) & (commands.command_name == data['command_name']) & (commands.title == data['title'])].index self._commands.drop(ix, inplace=True) self._commands.reset_index(drop=True, inplace=True) return self.commands
def on_execute__edit_electrode_channels(self, request): ''' Display dialog to edit the channels mapped to the specified electrode. Parameters ---------- request : dict Request with decoded data field: - ``electrode_id``: electrode identifier (``str``). - e.g., ``"electrode028"`` .. versionadded:: 2.25 ''' data = decode_content_data(request) electrode_id = data['electrode_id'] app = get_app() # Create schema to only accept a well-formed comma-separated list # of integer channel numbers. Default to list of channels # currently mapped to electrode. if electrode_id in app.dmf_device.channels_by_electrode.index: # If there is a single channel mapped to the electrode, the # `...ix[electrode_id]` lookup below returns a `pandas.Series`. # However, if multiple channels are mapped to the electrode the # `...ix[electrode_id]` lookup returns a `pandas.DataFrame`. # Calling `.values.ravel()` returns data in the same form in either # situation. current_channels = (app.dmf_device.channels_by_electrode .ix[[electrode_id]].values.ravel().tolist()) else: # Electrode has no channels currently mapped to it. current_channels = [] schema = {'type': 'object', 'properties': {'channels': {'type': 'string', 'pattern': r'^(\d+\s*(,\s*\d+\s*)*)?$', 'default': ','.join(map(str, current_channels))}}} @gtk_threadsafe def _dialog(): try: # Prompt user to enter a list of channel numbers (or nothing). result = schema_dialog(schema, device_name=False, parent=app.main_window_controller.view) except ValueError: pass else: # Well-formed (according to schema pattern) comma-separated # list of channels was provided. channels = sorted(set(map(int, filter(len, result['channels'] .split(','))))) hub_execute(self.name, 'set_electrode_channels', electrode_id=electrode_id, channels=channels) _dialog()
def on_execute__set_surface_alphas(self, request): ''' .. versionchanged:: 0.12 Queue redraw after setting surface alphas. ''' data = decode_content_data(request) logger.debug('[on_execute__set_surface_alphas] %s', data['surface_alphas']) for name, alpha in data['surface_alphas'].iteritems(): self.parent.canvas_slave.set_surface_alpha(name, alpha) self.parent.canvas_slave.render() gobject.idle_add(self.parent.canvas_slave.draw)
def on_execute__set_electrode_states(self, request): ''' .. versionchanged:: 2.28.3 Log error traceback to debug level. ''' data = decode_content_data(request) try: return self.set_electrode_states(data['electrode_states'], save=data.get('save', True)) except Exception: logger = _L() # use logger with method context logger.debug(str(data), exc_info=True) gtk_threadsafe(ft.partial(logger.error, str(data)))()
def on_execute__save_channel_impedances(self, request): data = decode_content_data(request) impedance_structures = data.pop('impedance_structures') output_path = data.pop('output_path') try: self.parent.save_channel_impedances(impedance_structures, output_path, **data) except Exception, error: app = get_app() if app.config.data.get('advanced_ui', False): # Launch debugger to inspect state. import pdb; pdb.set_trace() raise
def command_callback(reply): logger.info('[on_canvas_slave__set_electrode_channels] %s: %s', electrode_id, channels) # Decode content to raise error, if necessary. try: modified = decode_content_data(reply) except: logger.error('Error setting electrode channels: %s: %s', electrode_id, channels, exc_info=True) else: if modified: self.canvas_slave.canvas = None # Device channels were modified, so request device refresh. self.mqtt_client.publish('microdrop/dmf-device-ui/get-device', json.dumps(None))
def command_callback(reply): logger.info('[on_canvas_slave__set_electrode_channels] %s: %s', electrode_id, channels) # Decode content to raise error, if necessary. try: modified = decode_content_data(reply) except: logger.error('Error setting electrode channels: %s: %s', electrode_id, channels, exc_info=True) else: if modified: self.canvas_slave.canvas = None # Device channels were modified, so request device refresh. self.plugin.execute_async('wheelerlab.device_info_plugin', 'get_device')
def command_callback(reply): logger.info('[on_canvas_slave__set_electrode_channels] %s: %s', electrode_id, channels) # Decode content to raise error, if necessary. try: modified = decode_content_data(reply) except: logger.error('Error setting electrode channels: %s: %s', electrode_id, channels, exc_info=True) else: if modified: self.canvas_slave.canvas = None # Device channels were modified, so request device refresh. self.mqtt_client.publish( 'microdrop/dmf-device-ui/get-device', json.dumps(None))
def on_execute__set_video_config(self, request): data = decode_content_data(request) compare_fields = ['device_name', 'width', 'height', 'name', 'fourcc', 'framerate'] if data['video_config'] is None: i = None else: for i, row in self.parent.video_mode_slave.configs.iterrows(): if (row[compare_fields] == data['video_config'][compare_fields]).all(): break else: i = None if i is None: logger.error('Unsupported video config:\n%s', data['video_config']) logger.error('Video configs:\n%s', self.parent.video_mode_slave.configs) self.parent.video_mode_slave.config_combo.set_active(0) else: logger.error('Set video config (%d):\n%s', i + 1, data['video_config']) self.parent.video_mode_slave.config_combo.set_active(i + 1)
def on_execute__set_video_config(self, request): data = decode_content_data(request) compare_fields = [ 'device_name', 'width', 'height', 'name', 'fourcc', 'framerate' ] if data['video_config'] is None: i = None else: for i, row in self.parent.video_mode_slave.configs.iterrows(): if (row[compare_fields] == data['video_config'][compare_fields] ).all(): break else: i = None if i is None: logger.error('Unsupported video config:\n%s', data['video_config']) logger.error('Video configs:\n%s', self.parent.video_mode_slave.configs) self.parent.video_mode_slave.config_combo.set_active(0) else: logger.error('Set video config (%d):\n%s', i + 1, data['video_config']) self.parent.video_mode_slave.config_combo.set_active(i + 1)
def on_execute__set_surface_alphas(self, request): data = decode_content_data(request) logger.debug('[on_execute__set_surface_alphas] %s', data['surface_alphas']) for name, alpha in data['surface_alphas'].iteritems(): self.parent.canvas_slave.set_surface_alpha(name, alpha)
def on_execute__register_route_command(self, request): data = decode_content_data(request) logger.info('[register_route_command] %s', data) plugin_name = data.get('plugin_name', request['header']['source']) self.parent.canvas_slave.register_route_command( data['command'], group=plugin_name, title=data.get('title'))
def on_execute__add_route(self, request): data = decode_content_data(request) try: return self.parent.add_route(data['drop_route']) except: logger.error(str(data), exc_info=True)
def on_execute__set_allocation(self, request): data = decode_content_data(request) self.parent.set_allocation(data['allocation'])
def check_sockets(self): ''' Check for new messages on sockets and respond accordingly. ''' try: msg_frames = (self.command_socket .recv_multipart(zmq.NOBLOCK)) except zmq.Again: pass else: self.on_command_recv(msg_frames) try: msg_frames = (self.subscribe_socket .recv_multipart(zmq.NOBLOCK)) source, target, msg_type, msg_json = msg_frames if ((source == 'wheelerlab.device_info_plugin') and (msg_type == 'execute_reply')): msg = json.loads(msg_json) if msg['content']['command'] == 'get_device': data = decode_content_data(msg) if data is not None: self.parent.on_device_loaded(data) elif ((source == 'wheelerlab.electrode_controller_plugin') and (msg_type == 'execute_reply')): msg = json.loads(msg_json) if msg['content']['command'] in ('set_electrode_state', 'set_electrode_states'): data = decode_content_data(msg) if data is None: print msg else: #self.emit('electrode-states-updated', data) self.parent.on_electrode_states_updated(data) elif msg['content']['command'] == 'get_channel_states': data = decode_content_data(msg) if data is None: print msg else: #self.emit('electrode-states-set', data) self.parent.on_electrode_states_set(data) elif ((source == 'wheelerlab.droplet_planning_plugin') and (msg_type == 'execute_reply')): msg = json.loads(msg_json) if msg['content']['command'] in ('add_route', ): self.execute_async('wheelerlab.droplet_planning_plugin', 'get_routes') elif msg['content']['command'] in ('get_routes', ): data = decode_content_data(msg) #self.emit('routes-set', data) self.parent.on_routes_set(data) else: self.most_recent = msg_json except zmq.Again: pass except: logger.error('Error processing message from subscription ' 'socket.', exc_info=True) return True
def on_execute__set_dynamic_electrode_states(self, request): data = decode_content_data(request) return data['electrode_states']
def on_execute__set_corners(self, request): data = decode_content_data(request) if 'df_canvas_corners' in data and 'df_frame_corners' in data: for k in ('df_canvas_corners', 'df_frame_corners'): setattr(self.parent.canvas_slave, k, data[k]) self.parent.canvas_slave.update_transforms()
def on_execute__add_route(self, request): data = decode_content_data(request) try: return self.parent.add_route(data['drop_route']) except Exception: _L().error(str(data), exc_info=True)
def _on_found(zmq_response): data = decode_content_data(zmq_response) liquid_state['electrodes'] = data if i is not None and i < len(liquid_state['electrodes']): liquid_state['i'] = i
def on_execute__set_electrode_state(self, request): data = decode_content_data(request) return self.set_electrode_state(data['electrode_id'], data['state'])
def on_execute__measure_channel_impedances(self, request): data = decode_content_data(request) return self.measure_channel_impedances_monitored(**data)
def run_plugin(sio, plugin, log_level=None, namespace=None): if log_level is not None: logging.basicConfig(level=log_level) plugin.reset() def get_message(): msg_frames = plugin.subscribe_socket.recv_multipart(zmq.NOBLOCK) message_str = msg_frames[-1] try: # Decode message from first (and only expected) frame. message = json.loads(message_str) # Validate message against schema. validate(message) except jsonschema.ValidationError: logger.error('Unexpected message', exc_info=True) raise else: return message start = arrow.now() while True: try: try: message = get_message() except zmq.Again: gevent.sleep(.01) continue msg_timestamp = arrow.get(message['header']['date']) delta_time = (msg_timestamp - start).total_seconds() time_info = msg_timestamp.strftime('%H:%M:%S') if delta_time > .25: time_info += (' +%-5.1f' % delta_time) print 72 * '-' if message['header']['msg_type'] == 'execute_reply': msg_info = (time_info + ' [{header[target]}<-{header[source]}] ' '{content[command]}'.format(**message)) print msg_info data = decode_content_data(message) try: json_data = json.dumps(data, cls=PandasJsonEncoder) except: import pdb; pdb.set_trace() content = encode_content_data(json_data, mime_type= 'application/json') message['content'].update(content) elif 'content' in message: msg_info = (time_info + ' [{header[source]}->{header[target]}] ' '{content[command]}'.format(**message)) data = decode_content_data(message) try: json_data = json.dumps(data, cls=PandasJsonEncoder) except: import pdb; pdb.set_trace() content = encode_content_data(json_data, mime_type= 'application/json') message['content'].update(content) else: msg_info = (time_info + ' [{header[source]}->{header[target]}] ' '<{header[msg_type]}>'.format(**message)) print msg_info sio.emit('zmq', message, namespace=namespace) start = arrow.now() except KeyboardInterrupt: IPython.embed() except RuntimeError, exception: logger.error('Error', exc_info=True)
def check_sockets(self): ''' Check for new messages on sockets and respond accordingly. .. versionchanged:: 0.11.3 Update routes table by setting ``df_routes`` property of :attr:`parent.canvas_slave`. .. versionchanged:: 0.12 Update ``dynamic_electrode_state_shapes`` layer of :attr:`parent.canvas_slave` when dynamic electrode actuation states change. .. versionchanged:: 0.13 Update local global, electrode, and route command lists in response to ``microdrop.command_plugin`` messages. ''' try: msg_frames = (self.command_socket .recv_multipart(zmq.NOBLOCK)) except zmq.Again: pass else: self.on_command_recv(msg_frames) try: msg_frames = (self.subscribe_socket .recv_multipart(zmq.NOBLOCK)) source, target, msg_type, msg_json = msg_frames if ((source == 'microdrop.device_info_plugin') and (msg_type == 'execute_reply')): msg = json.loads(msg_json) if msg['content']['command'] == 'get_device': data = decode_content_data(msg) if data is not None: self.parent.on_device_loaded(data) elif ((source == 'microdrop.electrode_controller_plugin') and (msg_type == 'execute_reply')): msg = json.loads(msg_json) if msg['content']['command'] in ('set_electrode_state', 'set_electrode_states'): data = decode_content_data(msg) if data is None: print msg else: #self.emit('electrode-states-updated', data) self.parent.on_electrode_states_updated(data) elif msg['content']['command'] == 'get_channel_states': data = decode_content_data(msg) if data is None: print msg else: #self.emit('electrode-states-set', data) self.parent.on_electrode_states_set(data) elif ((source == 'droplet_planning_plugin') and (msg_type == 'execute_reply')): msg = json.loads(msg_json) if msg['content']['command'] in ('add_route', ): self.execute_async('droplet_planning_plugin', 'get_routes') elif msg['content']['command'] in ('get_routes', ): data = decode_content_data(msg) self.parent.canvas_slave.df_routes = data elif ((source == 'microdrop.command_plugin') and (msg_type == 'execute_reply')): msg = json.loads(msg_json) if msg['content']['command'] in ('get_commands', 'unregister_command', 'register_command'): df_commands = decode_content_data(msg).set_index('namespace') for group_i, df_i in df_commands.groupby('namespace'): register = getattr(self.parent.canvas_slave, 'register_%s_command' % group_i, None) if register is None: continue else: for j, command_ij in df_i.iterrows(): register(command_ij.command_name, title=command_ij.title, group=command_ij.plugin_name) _L().debug('registered %s command: `%s`', group_i, command_ij) else: self.most_recent = msg_json except zmq.Again: pass except: logger.error('Error processing message from subscription ' 'socket.', exc_info=True) return True