def apply_settings(self): self.N_chunks_before = CONF.get('data_management', 'n_chunks_before') self.N_chunks_after = CONF.get('data_management', 'n_chunks_after') self.N_chunks = self.N_chunks_before + self.N_chunks_after + 1 self.use_disk = CONF.get('data_management', 'use_disk_buffer') self.start_new_buffer()
def apply_plugin_settings(self): """Apply configuration file's plugin settings.""" # if self._starting_up: # self._starting_up = False self.host_le.setText(str(CONF.get(self.CONF_SECTION, 'host'))) self.port_le.setText(str(CONF.get(self.CONF_SECTION, 'port'))) self.user_le.setText(str(CONF.get(self.CONF_SECTION, 'username')))
def show_grid(self): if not len(self.get_plot_containers()): return if self.grid is None: rows = self.visible_channels.get_row_count() if rows: y_scale = 1/rows else: y_scale = 1 if self.master_plot: pass # TODO else: uutc_ss = self.data_map.get_active_largest_ss() span_secs = np.diff(uutc_ss) / 1e6 order_m = 10 ** (np.floor(np.log10(span_secs))) x_scale = order_m / span_secs c = CONF.get(self.CONF_SECTION, 'grid_color') self.grid = GridLines(scale=(x_scale, y_scale), color=c, parent=self.signal_view.scene) else: self.grid.parent = None self.grid = None
def __init__(self, parent): BasePluginWidget.__init__(self, parent) # Widget configiration self.ALLOWED_AREAS = Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea self.LOCATION = Qt.RightDockWidgetArea # Presets for the main window self.title = 'Database' self.main = parent self.conn = None # Create the form layout self.win_layout = QFormLayout(self) # Create widgets and labels db_type_label = QLabel('Database type:') self.db_type_cb = QComboBox(self) self.db_type_cb.addItem('mysql') self.win_layout.addRow(db_type_label, self.db_type_cb) host_label = QLabel('Host:') self.host_le = QLineEdit(CONF.get(self.CONF_SECTION, 'host')) self.win_layout.addRow(host_label, self.host_le) port_label = QLabel('Port:') self.port_le = QLineEdit(str(CONF.get(self.CONF_SECTION, 'port'))) self.win_layout.addRow(port_label, self.port_le) user_label = QLabel('Username:'******'username')) self.win_layout.addRow(user_label, self.user_le) passwd_label = QLabel('Password:'******'Connect') self.connect_btn.clicked.connect(self.create_connection) self.win_layout.addRow(self.connect_btn) self.disconnect_btn = QPushButton('Disconnect') self.disconnect_btn.clicked.connect(self.close_connection) self.win_layout.addRow(self.disconnect_btn)
def __init__(self, parent): super(MemoryBuffer, self).__init__() QObject.__init__(self, parent) self.signal_display = self.parent().signal_display self.signal_display.data_map_changed.connect(self.update) self.rec_start = sm.ODS.recording_info['recording_start'] self.rec_end = sm.ODS.recording_info['recording_end'] # Set the internal data map - keeps buffer times (what has already # been loaded and is available) # This data map is in main process self.data_map.setup_data_map(sm.ODS.data_map._map) self.data_map.reset_data_map() self.data_map['uutc_ss'][:] = self.rec_start if len(self.signal_display.data_map): self.data_map['ch_set'] = self.signal_display.data_map['ch_set'] self.current_view_dm = self.parent().signal_display.data_map self.curr_view_times = self.current_view_dm.get_active_largest_ss() self.chunk_size = int(CONF.get('signal_display', 'init_time_scale')*1e6) self.N_chunks_before = CONF.get('data_management', 'n_chunks_before') self.N_chunks_after = CONF.get('data_management', 'n_chunks_after') self.N_chunks = self.N_chunks_before + self.N_chunks_after + 1 self.use_disk = CONF.get('data_management', 'use_disk_buffer') # ----- Buffer process ----- self.buffer_manager = SharedDataManager() self.buffer_manager.start() self.sd = self.buffer_manager.SharedData() self.sd.set_chunk_size(self.chunk_size) self.sd.set_data_map(self.data_map) self.sd.set_current_view_dm(self.current_view_dm) self.buffer_stop = None self.buffer_process = None # Shared dictionary - a dictionary because we have to reasign the # so that the proxies are aware that something has changed self.start_new_buffer()
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 update_subsample(self): antialias = CONF.get(self.CONF_SECTION, 'antialiasing') pcs = self.get_plot_containers() for pc in pcs: if antialias == 'filter': pc.N = int(self.canvas.central_widget.width) elif antialias == 'min_max': pc.N = None
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 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 connect_navigation(self): # Navigation bar self.main.signal_display.data_map_changed.connect( self.bar_widget.update_view_bar) self.ri = sm.ODS.recording_info self.bar_widget.recording_duration = self.ri['recording_duration'] self.bar_widget.recording_start = self.ri['recording_start'] self.bar_widget.recording_span = (self.ri['recording_end'] - self.ri['recording_start']) # Buffer bars if CONF.get('data_management', 'use_memory_buffer'): sm.PDS.state_changed.connect(self.bar_widget.update_buffer_bar) # self.bar_widget.plot_disconts() # Tools widget self.main.signal_display.data_map_changed.connect( self.tools_widget.update_view_times) self.main.signal_display.subview_changed.connect( self.tools_widget.update_view_times)
def open_data_source(self, path): sm.ODS, ext = extension_evaluator(path) if not sm.ODS: QMessageBox.warning(self, "Unrecognized file") return # Assign session or file path if not already set if ext == '.mefd': # Open a pop-up window to enter password passwd, ok = QInputDialog.getText(self, "MEF password", "Please type MEF password") if ok: if not sm.ODS.password_check(passwd): QMessageBox.warning(self, "Password incorrect", "The password is incorrect") return else: sm.ODS.password = passwd self.session_path = path else: return elif not self.file_path: self.file_path = path # ----- Delete previous data ----- # Delete any previous buffers if isinstance(sm.PDS, MemoryBuffer): sm.PDS.terminate_buffer() sm.PDS.terminate_monitor_thread() sm.PDS.purge_data() # Delete data from plugins to be able to open new data source for plugin in self.plugin_list: plugin.delete_plugin_data() # Delete data from signal_display self.signal_display.initialize_data_map() self.signal_display.update_signals() self.signal_display.data_array = None # ----- self.statusBar().showMessage('Loading metadata') sm.ODS.load_metadata() self.statusBar().showMessage('Loading annotatios') # Try to get annotations if getattr(self, "annotations", None) is not None: if getattr(sm.ODS, "get_annotations", None) is not None: ann_groups = sm.ODS.get_annotations() if ann_groups is not None: for ann_group in ann_groups.items(): self.annotations.add_annotation_set( ann_group[1], ann_group[0]) # Fork for buffer usage if CONF.get('data_management', 'use_memory_buffer'): sm.PDS = MemoryBuffer(self) else: sm.PDS = sm.ODS self.statusBar().showMessage('') self.source_opened = True self.add_path_to_title() self.sig_file_opened.emit()
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 connect_to_server(self): print('Connecting to ' + self.server_type, ' server: tcp://' + self.server_ip + ':' + self.server_port) sm.ODS = client_type_evaluator(self.server_type) print('Original data source', sm.ODS.name) if self.server_ip: sm.ODS.client.ip = self.server_ip if self.server_port: sm.ODS.client.port = self.server_port sm.ODS.connect() # TODO: On successful connection store the input # Bring up the directory tree dt = sm.ODS.get_directory_tree() dir_tree_dialog = DirTreeDialog() dir_tree_dialog.dir_tree_widget.add_elemtens(dt.d) if dir_tree_dialog.exec(): self.server_path = dir_tree_dialog.return_tree_widget_path() # TODO: check iit is a proper session item passwd, ok = QInputDialog.getText(self, "MEF password", "Please type MEF password") if ok: if not sm.ODS.set_file_handler(self.server_path, passwd): QMessageBox.warning(self, "Password incorrect", "The password is incorrect") return else: return # ----- Delete previous data ----- # Delete any previous buffers if isinstance(sm.PDS, MemoryBuffer): sm.PDS.terminate_buffer() sm.PDS.terminate_monitor_thread() sm.PDS.purge_data() # Delete data from plugins to be able to open new data source for plugin in self.plugin_list: plugin.delete_plugin_data() # Delete data from signal_display self.signal_display.initialize_data_map() self.signal_display.update_signals() self.signal_display.data_array = None # ----- self.statusBar().showMessage('Loading metadata') sm.ODS.load_metadata() self.statusBar().showMessage('Loading annotatios') # Try to get annotations if getattr(self, "annotations", None) is not None: if getattr(sm.ODS, "get_annotations", None) is not None: ann_groups = sm.ODS.get_annotations() for ann_group in ann_groups.items(): self.annotations.add_annotation_set( ann_group[1], ann_group[0]) # Fork for buffer usage if CONF.get('data_management', 'use_memory_buffer'): sm.PDS = MemoryBuffer(self) else: sm.PDS = sm.ODS self.source_opened = True self.add_path_to_title() self.sig_file_opened.emit() # TODO change this to source opened
def apply_settings(self): # update CONF attributes from init self.canvas.bgcolor = CONF.get(self.CONF_SECTION,'bgcolor') self.color_palette = CONF.get(self.CONF_SECTION, 'color_palette')
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)
def __init__(self, parent): super(SignalWidget, self).__init__(parent) # Useful trnascripts self.plugin = self.parent() self.sd = self.plugin.sd self.CONF_SECTION = self.parent().CONF_SECTION # Variables self.measurement_mode = False self.curr_pc = None self.sig_start = None self.sig_stop = None self.spect_type = 'spectrum' # spectrum, spectrogram # General variables self.low_lim = None self.high_lim = None # Sepctrum variables self.mean_filter = None # Setup camera self.signal_camera = SignalCamera() self.spectrum_camera = SignalCamera() self.canvas = scene.SceneCanvas(show=True, keys='interactive', parent=self, bgcolor=CONF.get( self.CONF_SECTION, 'bgcolor')) self.view_grid = self.canvas.central_widget.add_grid(margin=10) # Signal self.signal_view = self.view_grid.add_view(row=0, col=1, row_span=2, camera=self.signal_camera) axis_color = CONF.get(self.CONF_SECTION, 'axis_color') self.signal_yaxis = AxisWidget(orientation='left', axis_label='Amplitude', axis_font_size=12, tick_label_margin=5, axis_color=axis_color, tick_color=axis_color, text_color=axis_color) self.signal_yaxis.width_max = 60 self.view_grid.add_widget(self.signal_yaxis, row=0, col=0, row_span=2) self.signal_xaxis = scene.AxisWidget(orientation='bottom', axis_label='Time [s]', axis_font_size=12, tick_label_margin=5, axis_color=axis_color, tick_color=axis_color, text_color=axis_color) self.signal_xaxis.height_max = 55 self.view_grid.add_widget(self.signal_xaxis, row=2, col=1) self.signal_yaxis.link_view(self.signal_view) self.signal_xaxis.link_view(self.signal_view) # Spectrum self.spectrum_view = self.view_grid.add_view( row=3, col=1, row_span=2, camera=self.spectrum_camera) self.spectrum_yaxis = AxisWidget(orientation='left', axis_label='Amplitude', axis_font_size=12, tick_label_margin=5, axis_color=axis_color, tick_color=axis_color, text_color=axis_color) self.spectrum_yaxis.width_max = 60 self.view_grid.add_widget(self.spectrum_yaxis, row=3, col=0, row_span=2) self.spectrum_xaxis = scene.AxisWidget(orientation='bottom', axis_label='Frequency [Hz]', axis_font_size=12, axis_color=axis_color, tick_color=axis_color, text_color=axis_color) self.spectrum_xaxis.height_max = 55 self.view_grid.add_widget(self.spectrum_xaxis, row=5, col=1) self.spectrum_yaxis.link_view(self.spectrum_view) self.spectrum_xaxis.link_view(self.spectrum_view) self.signal_line = Line(parent=self.signal_view.scene, width=1) self.spectrum_line = Line(parent=self.spectrum_view.scene, width=1) self.spectrogram = Spectrogram([0], parent=self.spectrum_view.scene) # ----- Set layout ----- # Widget layout layout = QVBoxLayout() layout.setContentsMargins(0, 0, 0, 0) layout.addWidget(self.canvas.native) # Set the whole layout 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)