def _color_change_hex(self): tmp_widget = self.sender() parent = tmp_widget.parent() name = tmp_widget.objectName() child = parent.findChild(QPushButton, name) result = tmp_widget.text() child.set_color(hex2rgba(result)) pos_change = name.split('||') self.preferences_changed[pos_change[0]][pos_change[1]] = result
def apply_plugin_settings(self): """Apply configuration file's plugin settings.""" # error no sel._starting_up atribute # if self._starting_up: # self._starting_up = False # update colors from init self.bar_widget.canvas.bgcolor = CONF.get(self.parent().CONF_SECTION, 'bgcolor') self.bar_widget.buffer_rgba = hex2rgba( CONF.get(self.parent().CONF_SECTION, 'buffer_bar_color')) self.bar_widget.buffer_carray = np.array( [self.buffer_rgba, self.buffer_rgba]) self.bar_widget.view_rgba = hex2rgba( CONF.get(self.parent().CONF_SECTION, 'view_bar_color')) self.bar_widget.view_carray = np.array( [self.view_rgba, self.view_rgba]) # update disc thresh self.bar_widget.discont_thresh = CONF.get(self.parent().CONF_SECTION, 'discontinuity_limit')
def color_code(self): pcs = self.get_plot_containers() if not len(pcs): return if self.color_coding_mode == 0: c = hex2rgba(CONF.get(self.CONF_SECTION, 'init_line_color')) for pc in pcs: pc.line_color = c pc.container.item_widget.color_select.set_color(c) self.update_labels() elif self.color_coding_mode == 1: # Channels #TODO - in prefs, color.get_colormaps() cm = color.get_colormap(self.color_palette) colors = cm[np.linspace(0, 1, len(pcs))] for pc, c in zip(pcs, colors): pc.line_color = c.rgba[0] pc.container.item_widget.color_select.set_color(c.rgba[0]) self.update_labels() # Acquire the colors based on number of channels # ???Introduce a limit??? If not the channels might be too simliar elif self.color_coding_mode == 2: # Groups ch_names = [x.orig_channel for x in pcs] g_names = [] for ch_name in ch_names: stub = ''.join([i for i in ch_name if not i.isdigit()]) g_names.append(stub) g_names = list(set(g_names)) # TODO - in prefs, color.get_colormaps() cm = color.get_colormap(self.color_palette) colors = cm[np.linspace(0, 1, len(g_names))] for pc in pcs: stub = ''.join([i for i in pc.orig_channel if not i.isdigit()]) c = colors[g_names.index(stub)] pc.line_color = c.rgba[0] pc.container.item_widget.color_select.set_color(c.rgba[0]) self.update_labels() elif self.color_coding_mode == 3: # Amplitude pass else: pass self.update_signals()
def side_flash(self, color=None): color = hex2rgba(CONF.get(self.CONF_SECTION, 'side_flash_color')) if self.discont_side == 1: # left pos = np.array([0., 0.1]) color = np.vstack([color, [0., 0., 0., 0.]]) elif self.discont_side == 2: # right pos = np.array([0.9, 1.0]) color = np.vstack([[0., 0., 0., 0.], color]) else: pos = np.array([0., 0.]) color = np.zeros([2, 4]) self.disc_marker.set_data(pos, color) return
def add_signal_container(self, orig_channel): container_items = self.visible_channels.get_container_items() mf_scale_fatcor = None scale_factors = [x.pvc.scale_factor for x in container_items] if scale_factors: # In case of half/half, let python choose :-) mf_scale_fatcor = max(scale_factors, key=scale_factors.count) # Get the max span and assign to new signals largest_ss = self.data_map.get_active_largest_ss() pc = SignalContainer(orig_channel) ci = sm.ODS.data_map['channels'] == pc.orig_channel ci_entry = sm.ODS.data_map[ci] pc.fsamp = ci_entry['fsamp'][0] pc.unit = ci_entry['unit'][0] pc.ufact = ci_entry['ufact'][0] pc.nsamp = ci_entry['nsamp'][0] pc.start_time = ci_entry['uutc_ss'][0][0] antialias = CONF.get(self.CONF_SECTION, 'antialiasing') if antialias == 'filter': pc.N = int(self.canvas.central_widget.width) elif antialias == 'min_max': pc.N = None c = hex2rgba(CONF.get(self.CONF_SECTION, 'init_line_color')) pc.line_color = np.array(c) pc.data_array_pos = [np.where(ci)[0][0]] # Scale factor if mf_scale_fatcor: pc.scale_factor = mf_scale_fatcor # Time span init_tscale = CONF.get(self.CONF_SECTION, 'init_time_scale')*1e6 if np.diff(largest_ss): pc.uutc_ss = largest_ss else: pc.uutc_ss = [pc.start_time, pc.start_time+init_tscale] return pc
def plot_disconts(self): dm = self.main.signal_display.data_map uutc = dm.get_active_largest_ss() view_span = np.diff(uutc) if not self.metadata_reload_flag: if self.previous_view_span == view_span: return self.previous_view_span = view_span if self.main.signal_display.cong_discontinuities is None: self.disc_bar.visible = False return else: self.disc_bar.visible = True # Big discontinuities that will trigger skipping cong_disconts = self.main.signal_display.cong_discontinuities large_disconts_idxs = np.diff(cong_disconts) > view_span large_disconts_idxs = large_disconts_idxs.ravel() large_disconts = cong_disconts[large_disconts_idxs] disc_color = hex2rgba( CONF.get(self.parent().CONF_SECTION, 'discontinuity_color')) pos = np.zeros(len(large_disconts) * 4) self.discont_colors = np.zeros([len(large_disconts) * 4, 4]) for i, gen_discont in enumerate(large_disconts): pos[i * 4 + 0] = self.uutc_to_pos(gen_discont[0]) pos[i * 4 + 1] = self.uutc_to_pos(gen_discont[0]) pos[i * 4 + 2] = self.uutc_to_pos(gen_discont[1]) pos[i * 4 + 3] = self.uutc_to_pos(gen_discont[1]) self.discont_colors[i * 4 + 1] = disc_color self.discont_colors[i * 4 + 2] = disc_color # Create a big linear region self.disc_bar.set_data(pos, color=self.discont_colors) return
def change_color(self, color): self.pvc.line_color = hex2rgba(color.name() + 'ff') # TODO - move this to a signal self.sd.update_signals()
def __init__(self, parent): super(BarWidget, self).__init__(parent) # Widget configuration self.setMaximumHeight(30) self.setMinimumHeight(30) # Widget layout layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) # Covenience transcripts self.main = self.parent().main self.recording_duration = None self.recording_start = None self.recording_span = None self.previous_view_span = 0 self.metadata_reload_flag = False self.discont_thresh = CONF.get(self.parent().CONF_SECTION, 'discontinuity_limit') # Camera self.camera = NavigationCamera(self) # Vispy canvas self.canvas = scene.SceneCanvas(show=True, keys='interactive', parent=self, bgcolor=CONF.get( self.parent().CONF_SECTION, 'bgcolor')) self.nav_view = self.canvas.central_widget.add_view(camera=self.camera) layout.addWidget(self.canvas.native) # ---- Linear regions for tracking ----- # Linear region for buffer pos = np.array([0, 0], dtype=np.float32) self.buffer_rgba = hex2rgba( CONF.get(self.parent().CONF_SECTION, 'buffer_bar_color')) self.buffer_carray = np.array([self.buffer_rgba, self.buffer_rgba]) self.buffer_bar = LinearRegion(pos, self.buffer_carray, parent=self.nav_view.scene) # Linear region for displayed signal pos = np.array([0, 0], dtype=np.float32) self.view_rgba = hex2rgba( CONF.get(self.parent().CONF_SECTION, 'view_bar_color')) self.view_carray = np.array([self.view_rgba, self.view_rgba]) self.view_bar = LinearRegion(pos, self.view_carray, parent=self.nav_view.scene) self.view_bar.transform = scene.transforms.STTransform(scale=(1, 1)) # Linear region for discontinuities pos = np.arange(self.nav_view.size[0]) color = np.zeros([self.nav_view.size[0], 4]) self.disc_bar = LinearRegion(pos, color, parent=self.nav_view.scene) self.disc_bar.transform = scene.transforms.STTransform(scale=(1, 1)) # TODO - nigh and day regions self.discontinuities = [] self.discont_region = [] self.discont_colors = [] self.setLayout(layout)
def __init__(self, parent): super(SignalDisplay, self).__init__(parent) # Covenience transcripts self.main = self.parent() # Widget behavior self.setAcceptDrops(True) # Plot variables self.sample_map = [] self.plot_containers = [] # TODO: Selected signal plot used for data shifting, colors, etc self.master_pc = None self.master_plot = None # TODO - to be deleted self.curr_pc = None self.rect_rel_w_pos = None self.rect_rel_h_pos = None self.resize_flag = False self.highlight_mode = False self.measurement_mode = False self.autoscale = False self.disconts_processed = False self.data_map = DataMap() self.data_source = sm.ODS self.data_array = None # Widget layout layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) # These variables are assigned in channels plugin self.hidden_channels = None self.visible_channels = None # Setup camera self.camera = SignalCamera() # Autoslide self.slide_worker_stopped = True # TODO: this should be i config self.slide_worker = TimerWorker(1) self.slide_worker_thread = QThread() self.slide_worker.moveToThread(self.slide_worker_thread) self.start_slide_worker.connect(self.slide_worker.run) self.stop_slide_worker.connect(self.slide_worker.interupt) self.slide_worker.time_passed.connect(self.autoslide) self.slide_worker_thread.start() # Vispy canvas self.canvas = scene.SceneCanvas(show=True, keys='interactive', parent=self, bgcolor=CONF.get(self.CONF_SECTION, 'bgcolor')) self.canvas.connect(self.on_key_press) self.canvas.connect(self.on_key_release) self.canvas.connect(self.on_mouse_move) self.canvas.connect(self.on_mouse_press) self.canvas.connect(self.on_mouse_release) self.canvas.connect(self.on_mouse_wheel) self.canvas.connect(self.on_resize) # Timer to let the scene redraw if key is hit self.event_time = time() self.plot_update_done = False # ??? Create two viewboxes - for labels and signals self.signal_view = self.canvas.central_widget.add_view( camera=self.camera) self.cong_discontinuities = None self.color_coding_mode = 0 self.color_palette = CONF.get(self.CONF_SECTION, 'color_palette') self.update_cam_state() # ----- Initial visuals operations----- # TODO - Add crosshair color to CONF # Measurements ch_color = CONF.get(self.CONF_SECTION, 'init_crosshair_color') self.crosshair = Crosshair(parent=self.signal_view.scene, color=hex2rgba(ch_color)) m_color = CONF.get(self.CONF_SECTION, 'init_marker_color') # TODO marker color self.marker = Markers(parent=self.signal_view.scene) self.xaxis = Axis(parent=self.signal_view.scene, tick_direction=(0., 1.), axis_width=1, tick_width=1, anchors=('center', 'top'), axis_color=m_color, tick_color=m_color, text_color=m_color) self.x_tick_spacing = 1000 self.yaxis = Axis(parent=self.signal_view.scene, tick_direction=(1., 0.), axis_width=1, tick_width=1, anchors=('left', 'center'), axis_color=m_color, tick_color=m_color, text_color=m_color) self.y_tick_spacing = 100 self.measure_line = Line(parent=self.signal_view.scene, width=3, color=m_color) # TODO - textbox self.describe_text = Text(anchor_x='left', anchor_y='bottom', parent=self.signal_view.scene, color=m_color) # Signal highlighting self.highlight_rec = Mesh(parent=self.signal_view.scene, color=np.array([0., 0., 0., 0.]), mode='triangle_fan') # Grid self.grid = None # Discontinuity self.disc_marker = LinearRegion(np.array([0, 0]), np.array([[0., 0., 0., 0.], [0., 0., 0., 0.]]), parent=self.signal_view.scene) self.signal_label_dict = {} # Main signal visal with labels w = CONF.get(self.CONF_SECTION, 'init_line_width') self.signal_visual = Multiline(width=w, parent=self.signal_view.scene) self.label_visual = Text(anchor_x='left', anchor_y='top', parent=self.signal_view.scene) # TODO - one set of x and y axes for measurements # ----- Tool bar ----- btn_layout = QHBoxLayout() for btn in self.setup_buttons(): if btn is None: continue btn.setAutoRaise(True) btn.setIconSize(QSize(20, 20)) btn_layout.addWidget(btn) # if options_button: # btn_layout.addStretch() # btn_layout.addWidget(options_button, Qt.AlignRight) # TODO - this is temporary - solve the rendering in different thread select_mode = QComboBox(self) select_mode.insertItems(0, ['Browse', 'Research']) antialias = CONF.get(self.CONF_SECTION, 'antialiasing') if antialias == 'filter': select_mode.setCurrentIndex(0) elif antialias == 'min_max': select_mode.setCurrentIndex(1) select_mode.currentIndexChanged.connect(self.switch_display_mode) btn_layout.addWidget(select_mode) # Color coding color_code = QComboBox(self) color_code.insertItems(0, ['None', 'Channel', 'Group', 'Amplitude']) color_code.currentIndexChanged.connect(self.switch_cc_mode) btn_layout.addWidget(color_code) # Metadata reload button btn_layout.setAlignment(Qt.AlignLeft) layout = create_plugin_layout(btn_layout) # ----- Set layout ----- layout.addWidget(self.canvas.native) # Set the whole layout self.setLayout(layout) # Connect signals self.main.sig_file_opened.connect(self.initialize_data_map) self.main.metadata_reloaded.connect(self.create_conglomerate_disconts) self.plots_changed.connect(self.set_plot_update) self.plots_changed.connect(self.subsample) self.plots_changed.connect(self.rescale_grid) self.input_recieved.connect(self.set_highlight_mode) self.input_recieved.connect(self.show_measure_line) self.canvas_resized.connect(self.update_subsample)
def _build_option_stack(self): ''' create editable options with visible current values, editation type is define by the option possible values :return: ''' # temporary prototype self.stack_layout_dict = {} self.options = {} # create stack with all editable sections self.stack_layout_dict = { section: QFormLayout() for section in self.sections } for section in self.sections: options = CONF.options(section=section) if 'enable' in options: options.remove('enable') self.options[section] = options for option in options: option_val = CONF.get(section, option) name_reference = section + '||' + option # boolean (true/False) setup if isinstance(option_val, bool): tmp_widget = QCheckBox('On/Off') tmp_widget.setObjectName(name_reference) if option_val: tmp_widget.setChecked(True) else: tmp_widget.setChecked(False) tmp_widget.stateChanged.connect(self._boolean_state) # one string or color setup if isinstance(option_val, str): # TODO take care of hexa strings withou alpha channel if (len(option_val) == 9) & (option_val.startswith('#')): tmp_widget = QHBoxLayout() tmp_val = PreferenceLineedit(option_val, name_reference, 9) tmp_col = ColorButton(hex2rgba(option_val)) tmp_col.setObjectName(name_reference) tmp_col.color_changed.connect(self._color_change) tmp_val.editingFinished.connect(self._color_change_hex) tmp_widget.addWidget(tmp_val) tmp_widget.addWidget(tmp_col) else: tmp_widget = PreferenceLineedit(option_val, name_reference, max_len=100) tmp_widget.editingFinished.connect(self._line_edit) # configuration of list (multiple selection) if (isinstance(option_val, tuple) | isinstance(option_val, list)): tmp_widget = QHBoxLayout() for i, val in enumerate(option_val): name_loc = name_reference + '||{}'.format(i) if isinstance(val, int): validator = QIntValidator() else: validator = None tmp_val = PreferenceLineedit(str(val), name_loc, validator=validator) tmp_val.editingFinished.connect(self._line_edit_multi) tmp_widget.addWidget(tmp_val) self.preferences_changed[section][option] = \ list(option_val) # configuration of single number if isinstance(option_val, int) & ~isinstance(option_val, bool): tmp_widget = PreferenceLineedit(str(option_val), name_reference, max_len=4, validator=QIntValidator()) tmp_widget.editingFinished.connect(self._line_edit) if option.split('/')[0] in self.sections: _, option = option.split('/') # Create nice option name first_letter = option[0] option = option.replace(first_letter, first_letter.upper(), 1) option = option.replace('_', ' ') self.stack_layout_dict[section].addRow(str(option), tmp_widget) # build whole stack for section in self.sections: tmp = QWidget() tmp.setLayout(self.stack_layout_dict[section]) self.options_editor.addWidget(tmp)