def update_connection_status(self): self.connection_status = "Not connected" app = get_app() connected = self.control_board.connected() if connected: try: name = self.control_board.name() version = self.control_board.hardware_version() firmware = self.control_board.software_version() n_channels = self.control_board.number_of_channels() self.connection_status = name + " v" + version + \ " (Firmware: " + str(firmware) + ")\n" + \ str(n_channels) + " channels" except: pass self.perform_calibration_menu_item.set_sensitive(connected) self.load_calibration_from_file_menu_item.set_sensitive(connected) self.edit_calibration_menu_item.set_sensitive(connected) self.reset_calibration_to_default_values_menu_item.set_sensitive( connected) self.feedback_options_controller.measure_cap_filler_menu_item. \ set_sensitive(connected) self.feedback_options_controller.measure_cap_liquid_menu_item. \ set_sensitive(connected) app.main_window_controller.label_control_board_status. \ set_text(self.connection_status)
def main(): import logging import gtk settings = gtk.settings_get_default() # Use a button ordering more consistent with Windows print 'Use a button ordering more consistent with Windows' settings.set_property('gtk-alternative-button-order', True) logging.basicConfig(format='%(asctime)s [%(levelname)s:%(name)s]: ' '%(message)s', datefmt=r'%Y-%m-%d %H:%M:%S', level=logging.INFO) initialize_core_plugins() from app import App from app_context import get_app gtk.threads_init() gtk.gdk.threads_init() gtk.gdk.threads_enter() my_app = get_app() sys.excepthook = except_handler my_app.run() gtk.gdk.threads_leave()
def main(): import logging import gtk settings = gtk.settings_get_default() # Use a button ordering more consistent with Windows print 'Use a button ordering more consistent with Windows' settings.set_property('gtk-alternative-button-order', True) logging.basicConfig(format='%(asctime)s [%(levelname)s:%(name)s]: ' '%(message)s', datefmt=r'%Y-%m-%d %H:%M:%S', level=logging.INFO) initialize_core_plugins() # XXX Import from `app` module automatically instantiates instance of `App` # class. from app import App from app_context import get_app gtk.threads_init() gtk.gdk.threads_init() my_app = get_app() sys.excepthook = except_handler my_app.run()
def on_step_options_changed(self, plugin, step_number): app = get_app() if not app.running and (app.realtime_mode and plugin == self.name and app.protocol.current_step_number == step_number): logger.debug('[PSTraceLauncher] on_step_options_changed(): %s step' '%d' % (plugin, step_number))
def get_app_value(self, key): if not hasattr(self, 'name'): raise NotImplementedError app = get_app() values_dict = app.get_data(self.name) return values_dict.get(key, self.AppFields.field_schema_mapping[key] .default)
def on_plugin_enable(self): # We need to call AppDataController's on_plugin_enable() to update the # application options data. AppDataController.on_plugin_enable(self) self.context = zmq.Context() self.reset_socks() if get_app().protocol: pgc = get_service_instance(ProtocolGridController, env='microdrop') pgc.update_grid()
def run(self): # Empty plugin form vbox # Get list of app option forms self.forms = emit_signal('get_app_form_class') self.form_views = {} self.clear_form() app = get_app() self.no_gui_names = set() for name, form in self.forms.iteritems(): # For each form, generate a pygtkhelpers formview and append the view # onto the end of the plugin vbox if form is None: schema_entries = [] else: # Only include fields that do not have show_in_gui set to False in # 'properties' dictionary schema_entries = [f for f in form.field_schema\ if f.properties.get('show_in_gui', True)] if not schema_entries: self.no_gui_names.add(name) continue gui_form = Form.of(*schema_entries) FormView.schema_type = gui_form self.form_views[name] = FormView() if name in app.core_plugins: self.core_plugins_vbox.pack_start(self.form_views[name].widget) self.frame_core_plugins.show() else: expander = gtk.Expander() expander.set_label(name) expander.set_expanded(True) expander.add(self.form_views[name].widget) self.plugin_form_vbox.pack_start(expander) for form_name, form in self.forms.iteritems(): if form_name in self.no_gui_names: continue form_view = self.form_views[form_name] values = self._get_app_values(form_name) fields = set(values.keys()).intersection(form_view.form.fields) for field in fields: value = values[field] proxy = proxy_for(getattr(form_view, field)) proxy.set_widget_value(value) form_field = form_view.form.fields[field] form_field.label_widget.set_text( re.sub(r'_', ' ', field).title()) self.dialog.show_all() response = self.dialog.run() if response == gtk.RESPONSE_OK: self.apply() elif response == gtk.RESPONSE_CANCEL: pass self.dialog.hide() return response
def on_protocol_pause(self): """ Handler called when a protocol is paused. """ app = get_app() self._kill_running_step() if self.control_board.connected() and not app.realtime_mode: # turn off all electrodes self.control_board.set_state_of_all_channels( np.zeros(self.control_board.number_of_channels()))
def on_plugin_disable(self): self.feedback_options_controller.on_plugin_disable() self.control_board_menu_item.hide() self.edit_log_calibration_menu_item.hide() self.feedback_results_controller.window.hide() self.feedback_results_controller.feedback_results_menu_item.hide() if get_app().protocol: self.on_step_run() pgc = get_service_instance(ProtocolGridController, env='microdrop') pgc.update_grid()
def on_experiment_log_created(self, log): app = get_app() data = {} if self.control_board.connected(): data["control board name"] = \ self.control_board.name() data["control board hardware version"] = \ self.control_board.hardware_version() data["control board software version"] = \ self.control_board.software_version() log.add_data(data)
def on_protocol_pause(self): """ Handler called when a protocol is paused. """ app = get_app() self._kill_running_step() if self.control_board.connected() and not app.realtime_mode: # turn off all electrodes self.control_board.set_state_of_all_channels( np.zeros(self.control_board.number_of_channels()) )
def on_protocol_run(self): """ Handler called when a protocol starts running. """ app = get_app() if self.control_board.connected() == False: logger.warning("Warning: no control board connected.") elif self.control_board.number_of_channels() <= \ app.dmf_device.max_channel(): logger.warning("Warning: currently " "connected board does not have enough channels for this " "protocol.")
def on_step_options_changed(self, plugin, step_number): logger.debug('[DmfControlBoardPlugin] on_step_options_changed():'\ '%s step #%d' % (plugin, step_number)) app = get_app() if self.feedback_options_controller: self.feedback_options_controller\ .on_step_options_changed(plugin, step_number) if app.protocol and not app.running and not app.realtime_mode and \ (plugin=='microdrop.gui.dmf_device_controller' or \ plugin==self.name) and \ app.protocol.current_step_number==step_number: self.on_step_run()
def on_protocol_run(self): """ Handler called when a protocol starts running. """ app = get_app() if self.control_board.connected() == False: logger.warning("Warning: no control board connected.") elif self.control_board.number_of_channels() <= \ app.dmf_device.max_channel(): logger.warning( "Warning: currently " "connected board does not have enough channels for this " "protocol.")
def get_step_value(self, name, step_number=None): app = get_app() if not name in self.StepFields.field_schema_mapping: raise KeyError('No field with name %s for plugin %s' % (name, self.name)) if step_number is None: step_number = app.protocol.current_step_number step = app.protocol.steps[step_number] options = step.get_data(self.name) if options is None: return None return getattr(options, name)
def run(self): app = get_app() try: if self.update() is None: logging.warning('All available plugins are already installed') return gtk.RESPONSE_CANCEL except IOError: logging.error('Could not connect to plugin repository at: %s' % ( app.get_app_value('server_url'))) return gtk.RESPONSE_CANCEL response = self.window.run() self.window.hide() return response
def on_device_impedance_update(self, impedance): app = get_app() app.main_window_controller.label_control_board_status. \ set_text(self.connection_status + ", Voltage: %.1f V" % \ impedance.V_actuation()[-1]) options = impedance.options feedback_options = impedance.options.feedback_options app_values = self.get_app_values() if impedance.V_actuation()[-1] < 5.0: logger.error( "Low voltage detected. Please check that the amplifier is on.") else: voltage = options.voltage if feedback_options.action.__class__ == RetryAction: attempt = app.protocol.current_step_attempt voltage += feedback_options.action.increase_voltage * \ attempt logger.info( '[DmfControlBoardPlugin].on_device_impedance_update():') logger.info('\tset_voltage=%.1f, measured_voltage=%.1f, ' 'error=%.1f%%' % (voltage, impedance.V_actuation()[-1], 100 * (impedance.V_actuation()[-1] - voltage) / voltage)) # check that the signal is within tolerance if abs(impedance.V_actuation()[-1]-voltage) > \ self.control_board.voltage_tolerance(): # allow maximum of 5 adjustment attempts if self.control_board.auto_adjust_amplifier_gain() and \ self.n_voltage_adjustments is not None and \ self.n_voltage_adjustments<5: logger.info('\tn_voltage_adjustments=%d' % \ self.n_voltage_adjustments) emit_signal("set_voltage", voltage, interface=IWaveformGenerator) self.check_impedance(options, self.n_voltage_adjustments + 1) else: self.n_voltage_adjustments = None logger.error("Unable to achieve the specified voltage.") if self.control_board.auto_adjust_amplifier_gain() and not \ self.amplifier_gain_initialized: self.amplifier_gain_initialized = True logger.info('Amplifier gain initialized (gain=%.1f)' % \ self.control_board.amplifier_gain())
def get_step_value(self, name, step_number=None): app = get_app() if not name in self.StepFields.field_schema_mapping: raise KeyError('No field with name %s for plugin %s' % (name, self.name)) if step_number is None: step_number = app.protocol.current_step_number step = app.protocol.steps[step_number] options = self.get_step_options(step_number) try: return getattr(options, name) except AttributeError: return getattr(options.feedback_options, name)
def get_step_options(self, step_number=None): """ Return a ODSensorOptions object for the current step in the protocol. If none exists yet, create a new one. """ step_number = self.get_step(step_number) app = get_app() step = app.protocol.steps[step_number] options = step.get_data(self.name) if options is None: # No data is registered for this plugin (for this step). options = self.get_default_options() step.set_data(self.name, options) return options
def get_actuated_area(self): app = get_app() if app.dmf_device.scale is None: raise DeviceScaleNotSet() area = 0 options = app.dmf_device_controller.get_step_options() state_of_all_channels = options.state_of_channels for id, electrode in app.dmf_device.electrodes.iteritems(): channels = app.dmf_device.electrodes[id].channels if channels: # get the state(s) of the channel(s) connected to this electrode states = state_of_all_channels[channels] if len(np.nonzero(states > 0)[0]): area += electrode.area() * app.dmf_device.scale return area
def on_flash_firmware(self, widget=None, data=None): app = get_app() try: connected = self.control_board.connected() if not connected: self.connect() hardware_version = utility.Version.fromstring( self.control_board.hardware_version()) if not connected: self.control_board.disconnect() self.control_board.flash_firmware(hardware_version) app.main_window_controller.info("Firmware updated successfully.", "Firmware update") except Exception, why: logger.error("Problem flashing firmware. " "%s" % why)
def get_step_values(self, step_number=None): app = get_app() if step_number is None: step_number = app.protocol.current_step_number step = app.protocol.steps[step_number] options = self.get_step_options(step_number) values = {} for name in self.StepFields.field_schema_mapping: try: value = getattr(options, name) except AttributeError: value = getattr(options.feedback_options, name) values[name] = value return values
def on_plugin_enable(self): """ Handler called once the plugin instance has been enabled. """ app = get_app() if not self.initialized: self.pstrace_launcher_menu_item = gtk.MenuItem('PSTrace step ' 'config...') app.main_window_controller.menu_tools.append( self.pstrace_launcher_menu_item) self.pstrace_launcher_menu_item.connect("activate", self.on_select_script) self.initialized = True self.pstrace_launcher_menu_item.show() super(PSTraceLauncher, self).on_plugin_enable()
def on_flash_firmware(self, widget=None, data=None): app = get_app() try: connected = self.control_board.connected() if not connected: self.connect() hardware_version = utility.Version.fromstring( self.control_board.hardware_version() ) if not connected: self.control_board.disconnect() self.control_board.flash_firmware(hardware_version) app.main_window_controller.info("Firmware updated successfully.", "Firmware update") except Exception, why: logger.error("Problem flashing firmware. ""%s" % why)
def on_device_impedance_update(self, impedance): app = get_app() app.main_window_controller.label_control_board_status. \ set_text(self.connection_status + ", Voltage: %.1f V" % \ impedance.V_actuation()[-1]) options = impedance.options feedback_options = impedance.options.feedback_options app_values = self.get_app_values() if impedance.V_actuation()[-1]<5.0: logger.error("Low voltage detected. Please check that the amplifier is on.") else: voltage = options.voltage if feedback_options.action.__class__ == RetryAction: attempt = app.protocol.current_step_attempt voltage += feedback_options.action.increase_voltage * \ attempt logger.info('[DmfControlBoardPlugin].on_device_impedance_update():') logger.info('\tset_voltage=%.1f, measured_voltage=%.1f, ' 'error=%.1f%%' % (voltage, impedance.V_actuation()[-1], 100*(impedance.V_actuation()[-1]-voltage)/voltage)) # check that the signal is within tolerance if abs(impedance.V_actuation()[-1]-voltage) > \ self.control_board.voltage_tolerance(): # allow maximum of 5 adjustment attempts if self.control_board.auto_adjust_amplifier_gain() and \ self.n_voltage_adjustments is not None and \ self.n_voltage_adjustments<5: logger.info('\tn_voltage_adjustments=%d' % \ self.n_voltage_adjustments) emit_signal("set_voltage", voltage, interface=IWaveformGenerator) self.check_impedance(options, self.n_voltage_adjustments+1) else: self.n_voltage_adjustments = None logger.error("Unable to achieve the specified voltage.") if self.control_board.auto_adjust_amplifier_gain() and not \ self.amplifier_gain_initialized: self.amplifier_gain_initialized = True logger.info('Amplifier gain initialized (gain=%.1f)' % \ self.control_board.amplifier_gain())
def _callback_sweep_frequency(self, options, results, state, frequencies, first_call=False): logger.debug('[DmfControlBoardPlugin] ' '_callback_sweep_frequency') app = get_app() app_values = self.get_app_values() # if this isn'g the first call, we need to retrieve the data from the # previous call if first_call == False: frequency = frequencies.pop(0) (V_hv, hv_resistor, V_fb, fb_resistor) = \ self.get_impedance_data(options) results.add_frequency_step(frequency, V_hv, hv_resistor, V_fb, fb_resistor) app.experiment_log.add_data({"SweepFrequencyResults": results}, self.name) logger.debug("V_actuation=%s" % results.V_actuation()) logger.debug("Z_device=%s" % results.Z_device()) # if there are frequencies left to sweep if len(frequencies): frequency = frequencies[0] emit_signal("set_frequency", frequency, interface=IWaveformGenerator) options.frequency = frequency self.control_board.measure_impedance_non_blocking( app_values['sampling_time_ms'], int( math.ceil(options.duration / app_values['sampling_time_ms'])), app_values['delay_between_samples_ms'], state) logger.debug('[DmfControlBoardPlugin] _callback_sweep_frequency: ' 'timeout_add(%d, _callback_sweep_frequency)' % options.duration) self.timeout_id = \ gobject.timeout_add(options.duration, self._callback_sweep_frequency, options, results, state, frequencies) else: self.step_complete() return False # stop the timeout from refiring
def _callback_sweep_frequency(self, options, results, state, frequencies, first_call=False): logger.debug('[DmfControlBoardPlugin] ' '_callback_sweep_frequency') app = get_app() app_values = self.get_app_values() # if this isn'g the first call, we need to retrieve the data from the # previous call if first_call==False: frequency = frequencies.pop(0) (V_hv, hv_resistor, V_fb, fb_resistor) = \ self.get_impedance_data(options) results.add_frequency_step(frequency, V_hv, hv_resistor, V_fb, fb_resistor) app.experiment_log.add_data( {"SweepFrequencyResults":results}, self.name) logger.debug("V_actuation=%s" % results.V_actuation()) logger.debug("Z_device=%s" % results.Z_device()) # if there are frequencies left to sweep if len(frequencies): frequency = frequencies[0] emit_signal("set_frequency", frequency, interface=IWaveformGenerator) options.frequency = frequency self.control_board.measure_impedance_non_blocking( app_values['sampling_time_ms'], int(math.ceil(options.duration/ app_values['sampling_time_ms'])), app_values['delay_between_samples_ms'], state) logger.debug('[DmfControlBoardPlugin] _callback_sweep_frequency: ' 'timeout_add(%d, _callback_sweep_frequency)' % options.duration) self.timeout_id = \ gobject.timeout_add(options.duration, self._callback_sweep_frequency, options, results, state, frequencies) else: self.step_complete() return False # stop the timeout from refiring
def _callback_retry_action_completed(self, options): logger.debug('[DmfControlBoardPlugin] ' '_callback_retry_action_completed') app = get_app() app_values = self.get_app_values() area = self.get_actuated_area() return_value = None (V_hv, hv_resistor, V_fb, fb_resistor) = \ self.get_impedance_data(options) results = FeedbackResults(options, app_values['sampling_time_ms'], app_values['delay_between_samples_ms'], V_hv, hv_resistor, V_fb, fb_resistor, area, self.control_board.calibration, app.protocol.current_step_attempt) logger.debug("V_actuation=%s" % \ results.V_actuation()) logger.debug("Z_device=%s" % results.Z_device()) app.experiment_log.add_data( {"FeedbackResults":results},self.name) if self.control_board.calibration.C_drop and \ max(results.capacitance())/area < \ options.feedback_options.action.percent_threshold/ \ 100.0*self.control_board.calibration.C_drop: logger.info('step=%d: attempt=%d, max(C)' '/A=%.1e F/mm^2. Repeat' % \ (app.protocol.current_step_number, app.protocol.current_step_attempt, max(results.capacitance())/area)) # signal that the step should be repeated return_value = 'Repeat' else: logger.info('step=%d: attempt=%d, max(C)' '/A=%.1e F/mm^2. OK' % \ (app.protocol.current_step_number, app.protocol.current_step_attempt, max(results.capacitance())/area)) self.step_complete(return_value) return False # stop the timeout from refiring
def __init__(self): app = get_app() builder = gtk.Builder() builder.add_from_file(glade_path() .joinpath("app_options_dialog.glade")) self.dialog = builder.get_object("app_options_dialog") self.frame_core_plugins = builder.get_object("frame_core_plugins") self.core_plugins_vbox = builder.get_object("core_plugins_vbox") self.plugin_form_vbox = builder.get_object("plugin_form_vbox") self.dialog.set_transient_for(app.main_window_controller.view) self.btn_ok = builder.get_object('btn_ok') self.btn_apply = builder.get_object('btn_apply') self.btn_cancel = builder.get_object('btn_cancel') self.form_views = {} self.no_gui_names = set() builder.connect_signals(self) self.builder = builder
def on_plugin_enable(self): """ Handler called once the plugin instance has been enabled. """ app = get_app() defaults = self.get_default_app_options() # update app data from config file if self.name in app.config.data: self.set_app_values(app.config.data[self.name]) data = app.get_data(self.name) for k, v in defaults.items(): if k not in data: data[k] = v app.set_data(self.name, data) if not self.name in app.config.data: app.config.data[self.name] = self.get_app_values()
def update(self): app = get_app() self.clear_plugin_list() self.controller.update() server_url = app.get_app_value('server_url') p = PluginRepository(server_url) available = set(p.available_packages(app_version={'major': 1, 'minor': 0, 'micro': 0})) installed = set([p.get_plugin_package_name() for p in self.controller.plugins]) to_install = available.difference(installed) if not to_install: return None self.list_select_view = ListSelectView(sorted(to_install), 'plugin_name') self.vbox_plugins.pack_start(self.list_select_view.widget) self.vbox_plugins.show_all() return True
def on_select_script(self, widget, data=None): """ Handler called when the user clicks on "PSTrace step config..." in the "Tools" menu. """ app = get_app() options = self.get_step_options() form = Form.of(Filepath.named('script').using(default=options.script, optional=True)) dialog = FormViewDialog() valid, response = dialog.run(form) step_options_changed = False if valid and (response['script'] and response['script'] != options.script): options.script = response['script'] step_options_changed = True if step_options_changed: emit_signal('on_step_options_changed', [self.name, app.protocol .current_step_number], interface=IPlugin)
def set_app_values(self, values_dict): if not values_dict: return if not hasattr(self, 'name'): raise NotImplementedError for k in values_dict.keys(): if k not in self.AppFields.field_schema_mapping.keys(): logger.error("Invalid key (%s) in configuration file section: " "[%s]." % (k, self.name)) # remove invalid key from config file values_dict.pop(k) elements = self.AppFields(value=values_dict) if not elements.validate(): raise ValueError('Invalid values: %s' % elements.errors) values = dict([(k, v.value) for k, v in elements.iteritems() if v.value is not None]) app = get_app() app_data = app.get_data(self.name) app_data.update(values) app.set_data(self.name, app_data) emit_signal('on_app_options_changed', [self.name], interface=IPlugin)
def _callback_retry_action_completed(self, options): logger.debug('[DmfControlBoardPlugin] ' '_callback_retry_action_completed') app = get_app() app_values = self.get_app_values() area = self.get_actuated_area() return_value = None (V_hv, hv_resistor, V_fb, fb_resistor) = \ self.get_impedance_data(options) results = FeedbackResults(options, app_values['sampling_time_ms'], app_values['delay_between_samples_ms'], V_hv, hv_resistor, V_fb, fb_resistor, area, self.control_board.calibration, app.protocol.current_step_attempt) logger.debug("V_actuation=%s" % \ results.V_actuation()) logger.debug("Z_device=%s" % results.Z_device()) app.experiment_log.add_data({"FeedbackResults": results}, self.name) if self.control_board.calibration.C_drop and \ max(results.capacitance())/area < \ options.feedback_options.action.percent_threshold/ \ 100.0*self.control_board.calibration.C_drop: logger.info('step=%d: attempt=%d, max(C)' '/A=%.1e F/mm^2. Repeat' % \ (app.protocol.current_step_number, app.protocol.current_step_attempt, max(results.capacitance())/area)) # signal that the step should be repeated return_value = 'Repeat' else: logger.info('step=%d: attempt=%d, max(C)' '/A=%.1e F/mm^2. OK' % \ (app.protocol.current_step_number, app.protocol.current_step_attempt, max(results.capacitance())/area)) self.step_complete(return_value) return False # stop the timeout from refiring
def set_step_values(self, values_dict, step_number=None): ''' Consider a scenario where most step options are simple types that are supported by `flatland` and can be listed in `StepOptions` (e.g., `Integer`, `Boolean`, etc.), but there is at least one step option that is a type not supported by `flatland`, such as a `numpy.array`. Currently, this requires custom handling for all methods related to step options, as in the case of the DMF control board. Instead, during validation of step option values, we could simply exclude options that are not listed in the `StepOptions` definition from the validation, but pass along *all* values to be saved in the protocol. This should maintain backwards compatibility while simplifying the addition of arbitrary Python data types as step options. ''' step_number = self.get_step_number(step_number) logger.debug('[StepOptionsController] set_step[%d]_values(): ' 'values_dict=%s' % (step_number, values_dict)) validate_dict = dict([(k, v) for k, v in values_dict.iteritems() if k in self.StepFields.field_schema_mapping]) validation_result = self.StepFields(value=validate_dict) if not validation_result.validate(): raise ValueError('Invalid values: %s' % validation_result.errors) values = values_dict.copy() for name, field in validation_result.iteritems(): if field.value is None: continue values[name] = field.value if values: app = get_app() step = app.protocol.steps[step_number] step.set_data(self.name, values) emit_signal('on_step_options_changed', [self.name, step_number], interface=IPlugin)
def on_step_run(self): """ Handler called whenever a step is executed. Plugins that handle this signal must emit the on_step_complete signal once they have completed the step. The protocol controller will wait until all plugins have completed the current step before proceeding. """ logger.debug('[DmfControlBoardPlugin] on_step_run()') self._kill_running_step() app = get_app() options = self.get_step_options() dmf_options = app.dmf_device_controller.get_step_options() logger.debug('[DmfControlBoardPlugin] options=%s dmf_options=%s' % \ (options, dmf_options)) feedback_options = options.feedback_options app_values = self.get_app_values() start_time = time.time() return_value = None try: if self.control_board.connected() and \ (app.realtime_mode or app.running): # initialize the amplifier gain if self.control_board.auto_adjust_amplifier_gain() and \ not self.amplifier_gain_initialized: emit_signal("set_frequency", options.frequency, interface=IWaveformGenerator) emit_signal("set_voltage", options.voltage, interface=IWaveformGenerator) self.check_impedance(options) state = dmf_options.state_of_channels max_channels = self.control_board.number_of_channels() if len(state) > max_channels: state = state[0:max_channels] elif len(state) < max_channels: state = np.concatenate( [state, np.zeros(max_channels - len(state), int)]) else: assert (len(state) == max_channels) if feedback_options.feedback_enabled: # calculate the total area of actuated electrodes area = self.get_actuated_area() if feedback_options.action.__class__ == RetryAction: attempt = app.protocol.current_step_attempt if attempt <= feedback_options.action.max_repeats: voltage = options.voltage + \ feedback_options.action.increase_voltage * \ attempt frequency = options.frequency emit_signal("set_voltage", voltage, interface=IWaveformGenerator) if frequency != self.current_frequency: emit_signal("set_frequency", frequency, interface=IWaveformGenerator) self.check_impedance(options) self.control_board.measure_impedance_non_blocking( app_values['sampling_time_ms'], int( math.ceil(options.duration / app_values['sampling_time_ms'])), app_values['delay_between_samples_ms'], state) logger.debug( '[DmfControlBoardPlugin] on_step_run: ' 'timeout_add(%d, _callback_retry_action' '_completed)' % options.duration) self.timeout_id = \ gobject.timeout_add(options.duration, self._callback_retry_action_completed, options) else: self.step_complete('Fail') return elif feedback_options.action.__class__ == \ SweepFrequencyAction: frequencies = np.logspace( np.log10(feedback_options.action.start_frequency), np.log10(feedback_options.action.end_frequency), int(feedback_options.action.n_frequency_steps) ).tolist() voltage = options.voltage results = SweepFrequencyResults( feedback_options, area, self.control_board.calibration) emit_signal("set_voltage", voltage, interface=IWaveformGenerator) test_options = deepcopy(options) self._callback_sweep_frequency(test_options, results, state, frequencies, first_call=True) return elif feedback_options.action.__class__ == SweepVoltageAction: voltages = np.linspace( feedback_options.action.start_voltage, feedback_options.action.end_voltage, feedback_options.action.n_voltage_steps).tolist() frequency = options.frequency if frequency != self.current_frequency: emit_signal("set_voltage", options.voltage, interface=IWaveformGenerator) emit_signal("set_frequency", frequency, interface=IWaveformGenerator) self.check_impedance(options) results = SweepVoltageResults( feedback_options, area, frequency, self.control_board.calibration) test_options = deepcopy(options) self._callback_sweep_voltage(test_options, results, state, voltages, first_call=True) return else: emit_signal("set_frequency", options.frequency, interface=IWaveformGenerator) emit_signal("set_voltage", options.voltage, interface=IWaveformGenerator) self.check_impedance(options) self.control_board.state_of_all_channels = state # turn off all electrodes if we're not in realtime mode and not # running a protocol elif self.control_board.connected() and \ not app.realtime_mode and not app.running: # turn off all electrodes self.control_board.set_state_of_all_channels( np.zeros(self.control_board.number_of_channels())) # if a protocol is running, wait for the specified minimum duration if app.running: logger.debug('[DmfControlBoardPlugin] on_step_run: ' 'timeout_add(%d, _callback_step_completed)' % options.duration) self.timeout_id = \ gobject.timeout_add(options.duration, self._callback_step_completed) return else: self.step_complete() except DeviceScaleNotSet: logger.error("Please set the area of one of your electrodes.")
def on_step_swapped(self, original_step_number, new_step_number): logger.debug('[DmfControlBoardPlugin] on_step_swapped():'\ 'original_step_number=%d, new_step_number=%d' % \ (original_step_number, new_step_number)) self.on_step_options_changed(self.name, get_app().protocol.current_step_number)
def on_plugin_disable(self): self.close_socks() if get_app().protocol: pgc = get_service_instance(ProtocolGridController, env='microdrop') pgc.update_grid()
def on_plugin_enable(self): if not self.initialized: self.feedback_options_controller = FeedbackOptionsController(self) self.feedback_results_controller = FeedbackResultsController(self) self.feedback_calibration_controller = \ FeedbackCalibrationController(self) self.edit_log_calibration_menu_item.connect( "activate", self.feedback_calibration_controller.on_edit_log_calibration) self.save_log_calibration_menu_item.connect( "activate", self.feedback_calibration_controller.on_save_log_calibration) self.load_log_calibration_menu_item.connect( "activate", self.feedback_calibration_controller.on_load_log_calibration) experiment_log_controller = get_service_instance_by_name( "microdrop.gui.experiment_log_controller", "microdrop") if hasattr(experiment_log_controller, 'popup'): experiment_log_controller.popup.add_item( self.edit_log_calibration_menu_item) experiment_log_controller.popup.add_item( self.save_log_calibration_menu_item) experiment_log_controller.popup.add_item( self.load_log_calibration_menu_item) app = get_app() self.control_board_menu_item = gtk.MenuItem("DMF control board") app.main_window_controller.menu_tools.append( self.control_board_menu_item) self.control_board_menu = gtk.Menu() self.control_board_menu.show() self.control_board_menu_item.set_submenu(self.control_board_menu) self.feedback_options_controller.on_plugin_enable() menu_item = gtk.MenuItem("Perform calibration") menu_item.connect( "activate", self.feedback_calibration_controller.on_perform_calibration) self.control_board_menu.append(menu_item) self.perform_calibration_menu_item = menu_item menu_item.show() menu_item = gtk.MenuItem("Load calibration from file") menu_item.connect("activate", self.feedback_calibration_controller. \ on_load_calibration_from_file) self.control_board_menu.append(menu_item) self.load_calibration_from_file_menu_item = menu_item menu_item.show() menu_item = gtk.MenuItem("Edit calibration settings") menu_item.connect("activate", self.on_edit_calibration) self.control_board_menu.append(menu_item) self.edit_calibration_menu_item = menu_item menu_item.show() menu_item = gtk.MenuItem("Reset calibration to default values") menu_item.connect("activate", self.on_reset_calibration_to_default_values) self.control_board_menu.append(menu_item) self.reset_calibration_to_default_values_menu_item = menu_item menu_item.show() self.initialized = True super(DmfControlBoardPlugin, self).on_plugin_enable() self.check_device_name_and_version() self.control_board_menu_item.show() self.edit_log_calibration_menu_item.show() self.feedback_results_controller.feedback_results_menu_item.show() if get_app().protocol: self.on_step_run() pgc = get_service_instance(ProtocolGridController, env='microdrop') pgc.update_grid()
def get_step(self, default): if default is None: return get_app().protocol.current_step_number return default
def complete_step(self, return_value=None): app = get_app() if app.running or app.realtime_mode: emit_signal('on_step_complete', [self.name, return_value])
def on_edit_calibration(self, widget=None, data=None): if not self.control_board.connected(): logging.error("A control board must be connected in order to " "edit calibration settings.") return hardware_version = utility.Version.fromstring( self.control_board.hardware_version()) schema_entries = [] settings = {} settings['amplifier_gain'] = self.control_board.amplifier_gain() schema_entries.append( Float.named('amplifier_gain').using( default=settings['amplifier_gain'], optional=True, validators=[ ValueAtLeast(minimum=0.01), ]), ) settings['auto_adjust_amplifier_gain'] = self.control_board \ .auto_adjust_amplifier_gain() schema_entries.append( Boolean.named('auto_adjust_amplifier_gain').using( default=settings['auto_adjust_amplifier_gain'], optional=True), ) settings['voltage_tolerance'] = \ self.control_board.voltage_tolerance() schema_entries.append( Float.named('voltage_tolerance').using( default=settings['voltage_tolerance'], optional=True, validators=[ ValueAtLeast(minimum=0), ]), ) if hardware_version.major == 1: settings['WAVEOUT_GAIN_1'] = self.control_board \ .eeprom_read(self.control_board.EEPROM_WAVEOUT_GAIN_1_ADDRESS) schema_entries.append( Integer.named('WAVEOUT_GAIN_1').using( default=settings['WAVEOUT_GAIN_1'], optional=True, validators=[ ValueAtLeast(minimum=0), ValueAtMost(maximum=255), ]), ) settings['VGND'] = self.control_board \ .eeprom_read(self.control_board.EEPROM_VGND_ADDRESS) schema_entries.append( Integer.named('VGND').using(default=settings['VGND'], optional=True, validators=[ ValueAtLeast(minimum=0), ValueAtMost(maximum=255), ]), ) else: settings['SWITCHING_BOARD_I2C_ADDRESS'] = self.control_board \ .eeprom_read(self.control_board.EEPROM_SWITCHING_BOARD_I2C_ADDRESS) schema_entries.append( Integer.named('SWITCHING_BOARD_I2C_ADDRESS').using( default=settings['SWITCHING_BOARD_I2C_ADDRESS'], optional=True, validators=[ ValueAtLeast(minimum=0), ValueAtMost(maximum=255), ]), ) settings['SIGNAL_GENERATOR_BOARD_I2C_ADDRESS'] = self.control_board \ .eeprom_read(self.control_board.EEPROM_SIGNAL_GENERATOR_BOARD_I2C_ADDRESS) schema_entries.append( Integer.named('SIGNAL_GENERATOR_BOARD_I2C_ADDRESS').using( default=settings['SIGNAL_GENERATOR_BOARD_I2C_ADDRESS'], optional=True, validators=[ ValueAtLeast(minimum=0), ValueAtMost(maximum=255), ]), ) for i in range(len(self.control_board.calibration.R_hv)): settings['R_hv_%d' % i] = self.control_board.calibration.R_hv[i] schema_entries.append( Float.named('R_hv_%d' % i).using(default=settings['R_hv_%d' % i], optional=True, validators=[ ValueAtLeast(minimum=0), ])) settings['C_hv_%d' % i] =\ self.control_board.calibration.C_hv[i]*1e12 schema_entries.append( Float.named('C_hv_%d' % i).using(default=settings['C_hv_%d' % i], optional=True, validators=[ ValueAtLeast(minimum=0), ])) for i in range(len(self.control_board.calibration.R_fb)): settings['R_fb_%d' % i] = self.control_board.calibration.R_fb[i] schema_entries.append( Float.named('R_fb_%d' % i).using(default=settings['R_fb_%d' % i], optional=True, validators=[ ValueAtLeast(minimum=0), ])) settings['C_fb_%d' % i] = \ self.control_board.calibration.C_fb[i]*1e12 schema_entries.append( Float.named('C_fb_%d' % i).using(default=settings['C_fb_%d' % i], optional=True, validators=[ ValueAtLeast(minimum=0), ])) form = Form.of(*schema_entries) dialog = FormViewDialog('Edit calibration settings') valid, response = dialog.run(form) if valid: for k, v in response.items(): if settings[k] != v: m = re.match('(R|C)_(hv|fb)_(\d)', k) if k == 'amplifier_gain': self.control_board.set_amplifier_gain(v) elif k == 'auto_adjust_amplifier_gain': self.control_board.set_auto_adjust_amplifier_gain(v) elif k == 'WAVEOUT_GAIN_1': self.control_board.eeprom_write( self.control_board.EEPROM_WAVEOUT_GAIN_1_ADDRESS, v) elif k == 'VGND': self.control_board.eeprom_write( self.control_board.EEPROM_VGND_ADDRESS, v) elif k == 'SWITCHING_BOARD_I2C_ADDRESS': self.control_board.eeprom_write( self.control_board. EEPROM_SWITCHING_BOARD_I2C_ADDRESS, v) elif k == 'SIGNAL_GENERATOR_BOARD_I2C_ADDRESS': self.control_board.eeprom_write( self.control_board. EEPROM_SIGNAL_GENERATOR_BOARD_I2C_ADDRESS, v) elif k == 'voltage_tolerance': self.control_board.set_voltage_tolerance(v) elif m: series_resistor = int(m.group(3)) if m.group(2) == 'hv': channel = 0 else: channel = 1 self.control_board.set_series_resistor_index( channel, series_resistor) if m.group(1) == 'R': self.control_board.set_series_resistance( channel, v) else: if v is None: v = 0 self.control_board.set_series_capacitance( channel, v / 1e12) # reconnect to update settings self.connect() if get_app().protocol: self.on_step_run()
def step_complete(self, return_value=None): app = get_app() if app.running or app.realtime_mode: emit_signal('on_step_complete', [self.name, return_value])