def add_label(self, new_x): x1 = min(self.canvas.prev_x, new_x) x2 = max(self.canvas.prev_x, new_x) datafile = config.get_datafile() label, color = config.get_current_label() if not self.timestamp: n_rows = datafile.get_shape() a = max(int(round(x1)), 0) b = max(int(round(x2)), 0) x1 = min(a, n_rows - 1) x2 = min(b, n_rows - 1) if x1 == x2: x1 = x1 - 0.5 x2 = x2 + 0.5 else: a = get_nearest_index(x1, self.timestamp) b = get_nearest_index(x2, self.timestamp) x1 = self.timestamp[a] x2 = self.timestamp[b] if x1 == x2: span = (self.timestamp[-1] - self.timestamp[0]) / (10 * len(self.timestamp)) x1 = x1 - span x2 = x2 + span for plots in self.plotters: plots.add_rect(x1=x1, x2=x2, color=color) datafile.labels_list.append([label, (a, b)]) self.canvas.modified = True self.canvas.draw()
def set_bad_names(self): self.bad_names = [""] if config.data_config is not None: data_col = config.get_datafile().get_data_header() labels, _ = config.get_labels_info() functions = config.get_functions() self.bad_names += data_col + labels + functions
def action(self, value): data_columns = config.get_datafile().get_data_columns() if data_columns[value] in self.plot_set[self.plot_index]: self.plot_set[self.plot_index].remove(data_columns[value]) else: self.plot_set[self.plot_index].append(data_columns[value]) config.set_plot_info(self.plot_set, self.normalize)
def plot(self): datafile = config.get_datafile() plot_set, normalize = config.get_plot_info() header = list(datafile.df) n_sub = len(plot_set) grid = GridSpec(n_sub, 1, left=0.08, right=0.92, top=0.99, bottom=0.04, hspace=0.1) self.timestamp = [ mdates.date2num(date) for date in datafile.get_timestamp() ] for i in range(n_sub): norm = bool(i in normalize) draw_set = [datafile.df[header[j]] for j in plot_set[i]] subplot = self.figure.add_subplot(grid[i]) plotter = Plotter(subplot, draw_set, self.timestamp, norm) self.subplots.append(subplot) self.plotters.append(plotter) subplot.set_xticklabels([]) if i < n_sub - 1 else None subplot.legend(loc=1, prop={'size': 8}) if draw_set else None self.manage_empty() self.insert_labels() self.canvas.refresh()
def accept(self): col_list = config.get_datafile().get_data_columns() self.name = self.name_input.text() self.source = col_list[self.source_input.currentIndex()] for key in self.ret_func.keys(): self.parameters[key] = self.ret_func[key]() self.close()
def remove_label(self, event): clk = self.find_clicked_rect(event) if clk is None: return for plots in self.plotters: plots.remove_rect(clk) del config.get_datafile().labels_list[clk] self.canvas.modified = True self.canvas.draw()
def init(self): # Remove label (if there is a label under the cursor) if self.canvas.core.find_clicked_rect(self.click_event) is not None: remove_label = QAction('Remove label', self) remove_label.triggered.connect(self.remove_label) self.addAction(remove_label) self.addSeparator() # Plot content (allows to customize the plotted series) datafile = config.get_datafile() data_columns = datafile.get_data_columns() self.plot_set, self.normalize = config.get_plot_info() plot_menu = self.addMenu("Plot content") for i, col in enumerate(datafile.get_data_header()): plot_action = PlotMenuAction(col, self, i) plot_menu.addAction(plot_action) if data_columns[i] in self.plot_set[self.plot_index]: plot_action.setChecked(True) # Normalize (allows to display the series by ignoring their scale) normalize_plot = QAction("Normalize", self) normalize_plot.triggered.connect(self.normalize_plot) normalize_plot.setCheckable(True) self.addAction(normalize_plot) if self.plot_index in self.normalize: normalize_plot.setChecked(True) # Add empty plot (before or after the current) self.addSeparator() add_menu = self.addMenu("Add plot") before = QAction("Before", self) after = QAction("After", self) add_menu.addAction(before) add_menu.addAction(after) before.triggered.connect(self.add_before) after.triggered.connect(self.add_after) # Clear or remove selected plot clear = QAction("Clear plot", self) remove = QAction("Remove plot", self) clear.triggered.connect(self.clear_plot) remove.triggered.connect(self.remove_plot) self.addAction(clear) self.addAction(remove) # Reset the view of all plots to the default one self.addSeparator() reset_all = QAction("Reset all plots", self) reset_all.triggered.connect(self.reset_all) self.addAction(reset_all)
def same_index(self, new_x): if not self.core.timestamp: datafile = config.get_datafile() n_rows = datafile.get_shape() x1 = max(int(round(self.prev_x)), 0) x2 = max(int(round(new_x)), 0) x1 = min(x1, n_rows - 1) x2 = min(x2, n_rows - 1) else: a = get_nearest_index(self.prev_x, self.core.timestamp) b = get_nearest_index(new_x, self.core.timestamp) x1 = self.core.timestamp[a] x2 = self.core.timestamp[b] return x1 == x2
def insert_labels(self): datafile = config.get_datafile() for lab in datafile.labels_list: if self.timestamp: x1 = self.timestamp[lab[1][0]] x2 = self.timestamp[lab[1][1]] if x1 == x2: span = (self.timestamp[-1] - self.timestamp[0]) / (10 * len(self.timestamp)) x1 = x1 - span x2 = x2 + span else: x1 = lab[1][0] x2 = lab[1][1] if x1 == x2: x1 = x1 - 0.5 x2 = x2 + 0.5 for plot in self.plotters: plot.add_rect(x1=x1, x2=x2, color=config.get_label_color(lab[0]))
def reset_all(self): self.plot_set = [[i] for i in config.get_datafile().get_data_columns()] self.normalize = [] config.set_plot_info(self.plot_set, self.normalize)
def __init__(self, title="Function setup", parameters=None): super().__init__() self.setWindowTitle(title) ts_list = config.get_datafile().get_data_header() self.name = None self.source = None self.parameters = dict() main_layout = QVBoxLayout() main_layout.setSpacing(15) self.setLayout(main_layout) # Function details self.name_input = QLineEdit() self.name_input.setMaxLength(20) self.name_input.textChanged.connect(self.validate_form) self.source_input = QComboBox() self.source_input.addItems(ts_list) layout = QFormLayout() layout.addRow(QLabel("Name"), self.name_input) layout.addRow(QLabel("Source"), self.source_input) self.details_box = QGroupBox("Function details") self.details_box.setLayout(layout) main_layout.addWidget(self.details_box) # Function parameters self.ret_func = dict() if parameters is not None: layout = QFormLayout() for key in parameters.keys(): param = parameters[key] widget = None if param["type"] == "text": widget = QLineEdit() self.ret_func[key] = widget.text elif param["type"] == "combo": widget = QComboBox() widget.addItems(param["values"]) widget.setCurrentIndex(param["default"]) self.ret_func[key] = widget.currentText elif param["type"] == "int": widget = QSpinBox() widget.setRange(param["min"], param["max"]) widget.setValue(param["default"]) self.ret_func[key] = widget.value elif param[ "type"] == "double": # TODO: replace with QDoubleSpinBox widget = QLineEdit() widget.setValidator(QDoubleValidator()) self.ret_func[key] = widget.text layout.addRow(QLabel(key), widget) self.param_box = QGroupBox("Function parameters") self.param_box.setLayout(layout) main_layout.addWidget(self.param_box) # Buttons self.button_box = QDialogButtonBox(QDialogButtonBox.Ok | QDialogButtonBox.Cancel) self.button_box.accepted.connect(self.accept) self.button_box.rejected.connect(self.reject) self.button_box.button(QDialogButtonBox.Ok).setEnabled(False) main_layout.addWidget(self.button_box) self.show() self.setFixedWidth(max(400, self.width())) self.setFixedHeight(self.height())