def __init__(self, name: str, *, start: float = None, end: float = None): from gui import PALMS from logic.databases.DatabaseHandler import Database track = Database.get().tracks[Database.get().main_track_label] super().__init__((start, end)) self.setBounds([start, end]) self.track = track self.start = start self.end = end self.mid = self.start + (self.end - self.start) / 2 self.name = name self.label = pg.TextItem(name) self.label.setFont( QFont("", PALMS.config['epoch_labels_font_size'], QFont.Bold)) self.label.setAnchor((0.5, 1)) # self.label.setColor(QColor('k')) try: label_y = EpochModeConfig.get().label_to_ypos[name] except: label_y = self.track.get_yrange_between(self.start, self.end)[0] self.label.setPos(self.mid, label_y) # self.sigRegionChangeFinished.connect(self.region_moved) EpochWindow._instance = weakref.ref(self)() qInfo('Window at [{:0.2f}; {:0.2f}] '.format(self.start, self.end))
def proxy_handler(self, types): """ 修改全局代理模式 :param types: 1:白名单 2:黑名单 0:关闭 :return: """ if types == 1: self.a5.setChecked(True) self.a6.setChecked(False) self.a7.setChecked(False) elif types == 2: self.a5.setChecked(False) self.a6.setChecked(True) self.a7.setChecked(False) else: self.a5.setChecked(False) self.a6.setChecked(False) self.a7.setChecked(True) lt = ["off", "whiteList", "gfwList"] self.v2rayL.proxy(types) qInfo("{}@$ff$@Proxy mode changed to: {}".format( self.v2rayL.current_status.log, lt[types])) if self.v2rayL.current_status.current != "未连接至VPN": self.v2rayL.connect(self.v2rayL.current_status.current, False)
def region_deleted(self): if self is not None: self.label.getViewBox().removeItem(self.label) self.getViewBox().removeItem(self) Partitions.delete(self) Partitions.update_all_bounds() qInfo('Region {} [{:0.2f}; {:0.2f}] deleted'.format(self.name, self.start, self.end))
def write_annotation_config_to_csv(self, fileName=None): try: import csv options = QFileDialog.Options() options |= QFileDialog.DontUseNativeDialog fileName, _ = QFileDialog.getSaveFileName(self, 'Save File', get_project_root().as_posix(), "CSV Files(*.csv)", options=options) if fileName: with open(fileName, 'w', newline='') as stream: writer = csv.writer(stream, delimiter=',') header_items = [self.table.horizontalHeaderItem(i).text() for i in range(self.table.columnCount())] writer.writerow(header_items) for row in range(self.table.rowCount()): row_data = {} for col in range(self.table.columnCount()): col_name = self.table.horizontalHeaderItem(col).text() self.table.toolTipDuration() w = self.table.cellWidget(row, col) if col_name in ['name', 'key', 'symbol', 'symbol_colour']: row_data[col_name] = w.text() elif col_name in ['is_pinned']: row_data[col_name] = bool(w.checkState()) elif col_name in ['pinned_to']: # assert w.currentText() in pinned_to_options row_data[col_name] = w.currentText() elif col_name in ['pinned_window', 'min_distance']: row_data[col_name] = w.value() elif col_name in ['symbol_size']: row_data[col_name] = int(w.text()) row_text = [str(int(i))if isinstance(i, bool) else str(i) for i in row_data.values()] writer.writerow(row_text) qInfo('Annotation config saved to ' + fileName) except Exception as e: qWarning('Failed to save Annotation Config\r\n' + str(e))
def region_moved(self): self.start, self.end = self.getRegion() self.mid = self.start + (self.end - self.start) / 2 self.label.setPos(self.mid, self.track.get_yrange_between(self.start, self.end)[0]) Partitions.remove_zero_partitions() Partitions.update_all_bounds() qInfo('Region {} moved'.format(self.name))
def pin(self, x: float, track, pinned_to: str, pinned_window: float, allowed_region_idx: List[int]): DEBUG = False window = pinned_window # sec if len(allowed_region_idx) < 3: return None amp = track.value ts = track.get_time() fs = track.get_fs() x_ind = np.argmin(abs(ts - x)) left_x_ind, right_x_ind = int(max([x_ind - round(fs * window), 0])), int(min([x_ind + round(fs * window), amp.size])) left_x_ind, right_x_ind = int(max([allowed_region_idx[0], left_x_ind])), int(min( [allowed_region_idx[-1], right_x_ind])) # both within window and allowed region sx, sy = ts[left_x_ind:right_x_ind], amp[left_x_ind:right_x_ind] # sy = scipy.signal.medfilt(sy, round_to_odd(fs * 0.02)) # TODO: parametrize smoothing if pinned_to.lower().__contains__('peak'): ind = detect_peaks(sy, show=DEBUG) elif pinned_to.lower().__contains__('valley'): ind = detect_peaks(sy, valley=True, show=DEBUG) else: raise ValueError if ind.size > 0: closest, _, _ = find_closest(ind + left_x_ind, np.array([x_ind])) highest = np.argmax(abs(sy[ind] - np.mean(sy))) ind_to_return = highest # take highest of all peaks found return sx[ind[ind_to_return]] else: qInfo('{p} not found'.format(p=pinned_to)) return x
def set_annotation_data(self): # NB: used to set initial guesses for annotations, otherwise, one has to start annotation from scratch # one can use here simple findpeaks() type algos, or more signal-specific python algorithms # also possible to run an algo beforehand (e.g. in Matlab), store the results and load them here # NB: OPTIONAL!!! Load existing annotation if an .h5 file with the same name found in self.existing_annotation_folder (be careful with self.outputfile_prefix) existing_annotation_file = pathlib.Path(self.existing_annotations_folder, self.fullpath.stem + '.h5') if self.annotation_exists(existing_annotation_file.stem): try: self.load(existing_annotation_file) qInfo('Loading annotations from {}'.format(existing_annotation_file)) except Exception as e: Dialog().warningMessage('Loading annotations from {} failed\r\n'.format(existing_annotation_file) + str(e)) else: # # NB: 1. Find\fetch preliminary annotation data f = self._get_matfile_object(self.fullpath) offset = np.concatenate(np.array(f['/data/ppg/ts']))[0] # offset to start at time=0 as signals themselves peak = np.concatenate(np.array(f['/data/annotations/ppg/peak/timestamps'])) - offset foot = np.concatenate(np.array(f['/data/annotations/ppg/foot/timestamps'])) - offset # # NB: 2. Use inherited functions to assign annotations to the main signal # # all annotation labels should be also in the provided AnnotationConfig file # # User can use _set_annotation_from_time or _set_annotation_from_idx self._set_annotation_from_time('peak', peak) self._set_annotation_from_time('foot', foot)
def value_change(self, flag): """ 端口改变 :param flag: true时为http, false为socks :return: """ http_port = self.system_setting_ui.http_sp.value() socks_port = self.system_setting_ui.socks_sp.value() if flag: if http_port == self.v2rayL.current_status.socks: http_port = http_port + 1 if http_port < 10079 else http_port - 1 self.system_setting_ui.http_sp.setValue(http_port) self.v2rayL.current_status.http = http_port with open("/etc/v2rayL/ncurrent", "wb") as jf: pickle.dump(self.v2rayL.current_status, jf) qInfo("{}@$ff$@HTTP port is changed to {}".format( self.v2rayL.current_status.log, http_port)) else: if socks_port == self.v2rayL.current_status.http: socks_port = socks_port + 1 if socks_port < 10079 else socks_port - 1 self.system_setting_ui.socks_sp.setValue(socks_port) self.v2rayL.current_status.socks = socks_port with open("/etc/v2rayL/ncurrent", "wb") as jf: pickle.dump(self.v2rayL.current_status, jf) qInfo("{}@$ff$@SOCKS port is changed to {}".format( self.v2rayL.current_status.log, socks_port)) try: with open("/etc/v2rayL/config.json", "r") as f: ret = json.load(f) except FileNotFoundError: pass else: ret["inbounds"][1]["port"] = http_port ret["inbounds"][0]["port"] = socks_port with open("/etc/v2rayL/config.json", "w") as f: f.write(json.dumps(ret, indent=4)) # if flag: # self.v2rayL.current_status.http = http_port # with open("/etc/v2rayL/ncurrent", "wb") as jf: # # self.v2rayL.current_status.http = http_port # pickle.dump(self.v2rayL.current_status, jf) # qInfo("{}@$ff$@HTTP port is changed to {}".format(self.v2rayL.current_status.log, http_port)) # else: # self.v2rayL.current_status.socks = socks_port # with open("/etc/v2rayL/ncurrent", "wb") as jf: # pickle.dump(self.v2rayL.current_status, jf) # qInfo("{}@$ff$@SOCKS port is changed to {}".format(self.v2rayL.current_status.log, socks_port)) if self.v2rayL.current_status.current != "未连接至VPN": self.v2rayL.connect(self.v2rayL.current_status.current, True)
def informationMessage(self, msg): reply = QMessageBox.information(self, "QMessageBox.information()", msg) qInfo(msg) if reply == QMessageBox.Ok: self.informationLabel.setText("OK") else: self.informationLabel.setText("Escape") self.show()
def _save_as_csv(self, *, filename: str, save_idx: bool): from logic.operation_mode.annotation import AnnotationConfig aConf = AnnotationConfig.get() fullpath = pathlib.Path(self.output_folder, 'annotation_' + filename).as_posix() aConf.to_csv(fullpath, save_idx=save_idx) fullpath = pathlib.Path(self.output_folder, 'partition_' + filename).as_posix() Partitions.to_csv(fullpath) fullpath = pathlib.Path(self.output_folder, 'epoch_' + filename).as_posix() EpochModeConfig.to_csv(fullpath) qInfo('{} saved'.format(fullpath))
def disable_log(self): """ 启用操作日志 :return: """ qInfo("{}@$ff$@Operation log has been disabled".format(self.v2rayL.current_status.log)) self.v2rayL.current_status.log = False self.a4.setChecked(True) self.a3.setChecked(False) self.v2rayL.logging(False)
def change_check_update(self): """ 是否自动检查更新 :return: """ if self.v2rayL.current_status.check: self.v2rayL.auto_check(False) qInfo("{}@$ff$@Automatically check for version updates disabled.".format(self.v2rayL.current_status.log)) else: self.v2rayL.auto_check(True) qInfo("{}@$ff$@Automatically check for version updates enabled.".format(self.v2rayL.current_status.log))
def auto_on(self): """ 开启/关闭开机自动连接 :return: """ if self.v2rayL.current_status.on: self.v2rayL.auto_on(False) qInfo("{}@$ff$@Automatic connection when booting is disabled.".format(self.v2rayL.current_status.log)) else: self.v2rayL.auto_on(True) qInfo("{}@$ff$@Automatic connection when booting is enabled.".format(self.v2rayL.current_status.log))
def set_annotation_data(self): # NB: used to set initial guesses for annotations, otherwise, one has to start annotation from scratch # one can use here simple findpeaks() type algos, or more signal-specific python algorithms # also possible to run an algo beforehand (e.g. in Matlab), store the results and load them here # NB: OPTIONAL!!! Load existing annotation if an .h5 file with the same name found in self.existing_annotation_folder (be careful with self.outputfile_prefix) existing_annotation_file = pathlib.Path( self.existing_annotations_folder, self.fullpath.stem + '.h5') if self.annotation_exists(existing_annotation_file.stem): try: self.load(existing_annotation_file) qInfo('Loading annotations from {}'.format( existing_annotation_file)) except Exception as e: Dialog().warningMessage( 'Loading annotations from {} failed\r\n'.format( existing_annotation_file) + str(e)) else: # NB: 1. Find\fetch preliminary annotation data amp = self.tracks[self.main_track_label].value mpd = self.tracks[self.main_track_label].fs * 2 idx_peak = detect_peaks(amp, mph=np.median(amp), mpd=mpd, valley=False, show=False, kpsh=False) idx_valley = detect_peaks(amp, mph=np.median(amp), mpd=mpd, valley=True, show=False, kpsh=False) idx_upstroke = detect_peaks(np.diff(amp), mph=np.median(np.diff(amp)), mpd=mpd, valley=False, show=False, kpsh=False) idx_downstroke = detect_peaks(np.diff(amp), mph=np.median(np.diff(amp)), mpd=mpd, valley=True, show=False, kpsh=False) # NB: 2. Use inherited functions to assign annotations to the main signal # all annotation labels should be also in the provided AnnotationConfig file # User can use _set_annotation_from_time or _set_annotation_from_idx self._set_annotation_from_idx('peak', idx_peak) self._set_annotation_from_idx('valley', idx_valley) self._set_annotation_from_idx('upstroke', idx_upstroke) self._set_annotation_from_idx('downstroke', idx_downstroke)
def keyPressEvent(self, event): """ #TODO: what else can be parametrized with keypresses? """ if Mode.is_epoch_mode(): # print((event.key(), event.text())) from logic.operation_mode.epoch_mode import EpochModeConfig EpochModeConfig.get().process_keypress(event.text()) else: # save last pressed button to later decide which fiducial is to be marked self.last_keypress_event_key = (event.key(), event.text()) qInfo('Key pressed: {}'.format(event.text())) event.accept()
def change_auto_update(self): """ 是否自动更新订阅 :return: """ if self.v2rayL.current_status.auto: self.v2rayL.subscribe(False) qInfo("{}@$ff$@Automatic update subscription is disabled.".format(self.v2rayL.current_status.log)) else: if not self.v2rayL.current_status.url: shell = "notify-send -i /etc/v2rayL/images/logo.ico v2rayL 不存在订阅地址,无需开启自动更新订阅" subprocess.call([shell], shell=True) self.v2rayL.subscribe(True) qInfo("{}@$ff$@Automatic update subscription is enabled.".format(self.v2rayL.current_status.log))
def switch_mode(new_mode: Modes): """it is a callback to Modes checkboxes. defines which mode should be switched on and emits a setOperationMode signal""" from gui.viewer import Viewer old_mode = Mode.mode # if old_mode == new_mode: # switching off current mode --> browsing mode # if new_mode in [Modes.annotation, Modes.partition, Modes.epoch]: # new_mode = Modes.browse # elif not old_mode == new_mode: # pass Mode.mode = new_mode Viewer.get().setOperationMode.emit(new_mode) qInfo('Mode: ' + Mode.mode.value)
def set_annotation_data(self): # NB: used to set initial guesses for annotations, otherwise, one has to start annotation from scratch # one can use here simple findpeaks() type algos, or more signal-specific python algorigthms # also possible to run an algo beforehand (e.g. in Matlab), store the results and load them here # NB: OPTIONAL!!! Load existing annotation if an .h5 file with the same name found in self.existing_annotation_folder (be careful with self.outputfile_prefix) existing_annotation_file = pathlib.Path( self.existing_annotations_folder, self.fullpath.stem + '.h5') existing_annotation_file_with_prefix = pathlib.Path( self.existing_annotations_folder, self.outputfile_prefix + self.fullpath.stem + '.h5') existing_annotation_files = self.get_annotation_file( self.fullpath.stem) if existing_annotation_files is not None: latest_file_idx = np.argmax( [os.path.getmtime(f) for f in existing_annotation_files]) try: self.load(existing_annotation_files[latest_file_idx]) qInfo('Loading annotations from {}'.format( existing_annotation_file_with_prefix)) except Exception as e: Dialog().warningMessage( 'Loading annotations from {} failed\r\n'.format( existing_annotation_file_with_prefix) + str(e)) else: # # NB: 1. Find\fetch preliminary annotation data ecg = self.tracks[self.main_track_label].value fs = self.tracks[self.main_track_label].fs try: qrs_detector = PanTomkinsQRSDetector(ecg, fs, verbose=True, log_data=False, plot_data=False, show_plot=False) # # NB: 2. Use inherited functions to assign annotations to the main signal # # all annotation labels should be also in the provided AnnotationConfig file # # User can use _set_annotation_from_time or _set_annotation_from_idx self._set_annotation_from_idx('rpeak', qrs_detector.qrs_peaks_indices) except Exception as e: Dialog().warningMessage( 'Failed to use beat detector\r\n' 'Currently you do not have any initial annotations loaded, but\r\n' 'You can fix the issue, or implement another way in set_annotation_data()' )
def process_keypress(self, key: str): """ When in EpochMode and keyPressed is one from the epochModeConfig: assign corresponding label to that epoch and move to the next one :param key: :return: """ label = self.keys_to_labels.get(key, EpochModeConfig.NONE_LABEL) if label is not EpochModeConfig.NONE_LABEL: idx = EpochModeConfig.CURRENT_WINDOW_IDX.get() self.window_data.loc[idx, 'label'] = label self.window_data.loc[idx, 'is_modified'] = 1 EpochWindow.update_label() self.redraw_epochs() EpochWindow.move_right() qInfo('Window labeled {} '.format(label))
def delete(self, x): from gui.viewer import Viewer plot_area = Viewer.get().selectedDisplayPanel.plot_area fiducial_name = self.name fConf = AnnotationConfig.get()[fiducial_name] if fConf.annotation.x.size > 0: # closest_idx, _, _ = find_closest(fConf.annotation.x, np.array([x])) closest_idx = np.argmin(abs(x - fConf.annotation.x)) deleted_x, deleted_y = fConf.annotation.x[closest_idx], fConf.annotation.y[closest_idx] fConf.annotation.x = np.delete(fConf.annotation.x, closest_idx) fConf.annotation.y = np.delete(fConf.annotation.y, closest_idx) fConf.annotation.idx = np.delete(fConf.annotation.idx, closest_idx) Viewer.get().selectedDisplayPanel.plot_area.redraw_fiducials() plot_area.signal_annotation_added.emit(deleted_x, deleted_y, 'deleted') qInfo('{n} deleted'.format(n=fiducial_name)) else: qInfo('No {n} to be deleted'.format(n=fiducial_name))
def __init__(self, name: str, *, start: float = None, end: float = None): """ constructor when start/end are given explicitly. when created from mouse click (single point) see self.from_click """ from gui import PALMS from logic.databases.DatabaseHandler import Database track = Database.get().tracks[Database.get().main_track_label] left_bound, right_bound = Partitions.calculate_boundaries(start, end) left_bound = left_bound if left_bound is not None else track.minX right_bound = right_bound if right_bound is not None else track.maxX start = max([max([start, track.minX]), left_bound]) end = min([min([end, track.maxX]), right_bound]) super().__init__((start, end)) self.setBounds([left_bound, right_bound]) self.track = track self.start = start self.end = end self.mid = self.start + (self.end - self.start) / 2 self.name = name self.label = pg.TextItem(name) self.label.setFont(QFont("", PALMS.config['partition_labels_font_size'], QFont.Bold)) # self.label.setColor(QColor('k')) self.label.setAnchor((0.5, 1)) self.label.setPos(self.mid, self.track.get_yrange_between(self.start, self.end)[0]) Partitions.add(self) Partitions.update_all_bounds(self) # # update config with new partition name # from gui.viewer import PALMS # PALMS.config['default_partition_labels'] = list( # unique_everseen(PALMS.config['default_partition_labels'] + Partitions.unique_labels())) self.sigRegionChangeFinished.connect(self.region_moved) qInfo('Region {} [{:0.2f}; {:0.2f}] created'.format(self.name, self.start, self.end))
def which_fiducial_to_add(last_keypress_event_key): from gui.viewer import Viewer # first check if 'sticky' fiducial option is enabled for one of the fiducials sticky_fiducial = [ item.isChecked() for item in Viewer.get().annotation_menu.sticky_fiducial_menu.actions() ] if any(sticky_fiducial): idx = np.argwhere(sticky_fiducial)[0] return AnnotationConfig.get().find_idx_by_name( Viewer.get().annotation_menu.sticky_fiducial_menu.actions( )[idx[0]].text()) # if 'sticky' fiducial option is off, check what key was pressed the last default_fiducial_idx = 0 # default: first fiducial if last_keypress_event_key is not None: qInfo('Last pressed: ' + str(last_keypress_event_key[1])) for fiducial_idx, f in enumerate( AnnotationConfig.get().fiducials): if f.key.lower() == last_keypress_event_key[1].lower(): return fiducial_idx return default_fiducial_idx else: return default_fiducial_idx
def wheelEvent(self, event: QtGui.QWheelEvent): # limit wheelevents to max N events in T seconds to avoid hanging GUI because of zooming in and out non-stop PlotArea.wheelEventsCounter = PlotArea.wheelEventsCounter + 1 # print(PlotArea.wheelEventsCounter) if PlotArea.wheelEventsCounter > 3: qInfo('Zooming speed limited to optimize performance.') return super().wheelEvent(event) newRange = self.main_vb.viewRange()[0] if self.main_window.selectedView is not None: maxX = self.main_window.selectedView.panel.get_max_duration() else: return if newRange[-1] > maxX: newRange[-1] = maxX if newRange[0] < 0: newRange[0] = 0 if newRange[0] == 0: self.main_vb.setXRange(newRange[0], newRange[1], padding=0) else: self.main_vb.setXRange(newRange[0], newRange[1]) event.accept()
def initialize_epoch_mode_settings_from_csv(csv): if csv is None: EpochModeConfig() qInfo( 'Epoch mode init settings not given. Starting with default values' ) try: csv_data = pd.read_csv(csv) winLen = int(csv_data.winLen.values[0]) labels = list(csv_data.labels.values) description = list(csv_data.description.values) try: if not all(isinstance(elem, str) for elem in description): description = labels except Exception as e: description = labels keys = list(csv_data['keys'].values) for i, k in enumerate(keys): if isinstance(k, (int, np.integer)): keys[i] = str(k) default_label = csv_data.default_label.values[0] if not isinstance(default_label, str) and np.isnan(default_label): default_label = None EpochModeConfig(winLen=winLen, labels=labels, keys=keys, default_label=default_label, description=description) except Exception as e: Dialog().warningMessage( 'Epoch mode settings processing failed with\r\n' + str(e) + '\r\nInitializing with defaults') EpochModeConfig()
def current_window_downgrade_value(self): """ For current epoch assign the prev label from EpochConfig :return: """ idx = EpochModeConfig.CURRENT_WINDOW_IDX.get() n_labels = len(self.labels) this_label = self.window_data.loc[idx, 'label'] if this_label == EpochModeConfig.NONE_LABEL: this_label_idx = n_labels else: this_label_idx = self.labels.index(this_label) if this_label_idx > 0: self.window_data.loc[idx, 'label'] = self.labels[this_label_idx - 1] self.window_data.loc[idx, 'is_modified'] = 1 EpochWindow.update_label() self.redraw_epochs() # EpochWindow.move_right() qInfo('Window labeled {} '.format(self.labels[this_label_idx - 1])) else: qInfo('Window label can not be downgraded')
def __init__(self, *, winLen=10, labels: List[str] = None, keys: List[str] = None, default_label=None, description: List[str] = None): if labels is None: labels = ['low', 'good'] if keys is None: keys = list(np.arange(len(labels)).astype(str)) if description is None: description = labels if default_label is not None: if isinstance(default_label, str): if default_label not in labels: default_label = labels[0] qInfo( 'Given default_label is not in given labels. Changed to {} ' .format(default_label)) elif isinstance(default_label, int): if default_label <= len(labels): default_label = labels[default_label] else: default_label = labels[0] qInfo( 'Given default_label is not in given labels. Changed to {} ' .format(default_label)) else: default_label = EpochModeConfig.NONE_LABEL from logic.databases.DatabaseHandler import Database track = Database.get().tracks[Database.get().main_track_label] self.window_data = pd.DataFrame(columns={'start', 'end', 'label'}) self.visuals = [] self.label_to_ypos = {} self.labels_to_keys = {} self.keys_to_labels = {} self.labels_to_color = {} self.toggle_fiducials = True self.window_overlap = 0 # sec self.window_length = winLen # sec self.labels = labels self.default_label = default_label self.keys = keys self.description = description all_starts = np.arange(track.time[0], track.time[-1], self.window_length) all_ends = all_starts + self.window_length if all_ends[-1] > track.time[-1]: all_ends[-1] = track.time[-1] self.window_data['start'] = all_starts self.window_data['end'] = all_ends self.window_data['is_modified'] = 0 self.window_data['label'] = self.default_label self.test_epoch_config() # colors to be assigned to different labels, colors do not mean anything and can be counterintuitive as Good=Red, Bad=Green colors = cycle(['r', 'g', 'b', 'c', 'm', 'y', 'w']) for l, k in zip(self.labels, self.keys): self.labels_to_keys[l] = k self.keys_to_labels[k] = l self.labels_to_color[l] = next(colors) st, en, label = self.get_window_data( EpochModeConfig.CURRENT_WINDOW_IDX.get()) EpochWindow(label, start=st, end=en) self.redraw_epochs() EpochModeConfig._instance = weakref.ref(self)()
def save(self, **kwargs): # TODO: popup warning when rewriting existing files try: from gui.viewer import Viewer filename = kwargs.get('filename', self.fullpath.stem) try: filename = self.outputfile_prefix + filename except Exception as e: qInfo('Output file prefix could not be added') fullpath = pathlib.Path(self.output_folder, filename + '.h5') OVERWRITE = kwargs.get('OVERWRITE', Viewer.get().settings_menu.save_overwrite_action.isChecked()) if fullpath.is_file(): # don't overwrite files if not OVERWRITE: path, filename = os.path.split(fullpath) filename = os.path.splitext(filename)[0] newfilename = filename + '_' + strftime("%Y_%m_%d_%H_%M_%S", gmtime()) + fullpath.suffix fullpath = pathlib.Path(path, newfilename) qInfo('Existing file found. Not overwriting') else: qInfo('Existing file OVERWRITTEN!') from logic.operation_mode.annotation import AnnotationConfig aConf = AnnotationConfig.get() hf = h5py.File(fullpath, 'w') group_annotations = hf.create_group('annotations') for f_idx, f in enumerate(aConf.fiducials): group_annotations.create_group(f.name) group_annotations.create_dataset(f.name + '/ts', data=f.annotation.x) group_annotations.create_dataset(f.name + '/idx', data=f.annotation.idx) group_annotations.create_dataset(f.name + '/amp', data=f.annotation.y) group_partitions = hf.create_group('partitions') asciiList = [n.encode("ascii", "ignore") for n in Partitions.all_labels()] group_partitions.create_dataset('label', data=asciiList) group_partitions.create_dataset('start', data=Partitions.all_startpoints()) group_partitions.create_dataset('end', data=Partitions.all_endpoints()) group_epoch = hf.create_group('epoch') group_epoch.create_dataset('start', data=EpochModeConfig.get().window_data['start'].values) group_epoch.create_dataset('end', data=EpochModeConfig.get().window_data['end'].values) group_epoch.create_dataset('is_modified', data=EpochModeConfig.get().window_data['is_modified'].values) asciiList = [n.encode("ascii", "ignore") for n in EpochModeConfig.get().window_data['label'].values] group_epoch.create_dataset('label', data=asciiList) asciiList = [n.encode("ascii", "ignore") for n in EpochModeConfig.get().keys] group_epoch.create_dataset('keys', data=asciiList) asciiList = [n.encode("ascii", "ignore") for n in EpochModeConfig.get().labels] group_epoch.create_dataset('all_labels', data=asciiList) asciiList = [n.encode("ascii", "ignore") for n in EpochModeConfig.get().description] group_epoch.create_dataset('description', data=asciiList) dt = h5py.special_dtype(vlen=str) group_epoch.create_dataset('default_label', (1,), dtype=dt) group_epoch['default_label'][:] = EpochModeConfig.get().default_label group_epoch.create_dataset('NONE_LABEL', (1,), dtype=dt) group_epoch['NONE_LABEL'][:] = EpochModeConfig.get().NONE_LABEL group_meta = hf.create_group('meta') dt = h5py.special_dtype(vlen=str) group_meta.create_dataset('timestamp', (1,), dtype=dt) group_meta['timestamp'][:] = strftime("%Y_%m_%d_%H_%M_%S", gmtime()) group_meta.create_dataset('filename', (1,), dtype=dt) group_meta['filename'][:] = self.fullpath.stem group_meta.create_dataset('filepath', (1,), dtype=dt) group_meta['filepath'][:] = self.fullpath.parent.as_posix() group_meta.create_dataset('main_track_label', (1,), dtype=dt) group_meta['main_track_label'][:] = self.main_track_label if Viewer.get().settings_menu.save_tracks_action.isChecked(): group_tracks = hf.create_group('tracks') for label, track in Database.get().tracks.items(): group_tracks.create_dataset(label + '/ts', data=track.ts) group_tracks.create_dataset(label + '/amp', data=track.value) group_tracks.create_dataset(label + '/offset', data=track.offset) group_tracks.create_dataset(label + '/fs', data=track.fs) hf.close() qInfo('{} saved'.format(fullpath.as_posix())) except Exception as e: try: hf.close() except: pass self._save_as_csv(filename=self.fullpath.stem, save_idx=False) Dialog().warningMessage('Default save crashed\r\n' + e.__repr__() + '\r\nSaved using deprecated method, as CSV files.')
def activate_plugins_impl(organizer: mobase.IOrganizer, plugins: List[str], plugin_to_mod: Dict[str, str]): modlist = organizer.modList() pluginlist = organizer.pluginList() # Disable all mods modlist.setActive(modlist.allMods(), active=False) enabled_plugins = set() enabled_mods = set() try: mods = [plugin_to_mod[p] for p in plugins] # Enable mods with selected plugins modlist.setActive(mods, active=True) # Enable only selected plugins def enable_plugins(plugins_to_enable): for p in pluginlist.pluginNames(): if p in plugins_to_enable: pluginlist.setState(p, mobase.PluginState.ACTIVE) else: pluginlist.setState(p, mobase.PluginState.INACTIVE) # Enable no plugins (except mandatory) enable_plugins([]) mandatory_plugins = [ p for p in pluginlist.pluginNames() if pluginlist.state(p) == mobase.PluginState.ACTIVE ] # Enable missing masters plugins_and_masters = set(mandatory_plugins) plugins_and_masters_to_check = set(plugins) # Checking masters of plugins (and their masters, and so on) while len(plugins_and_masters_to_check) > 0: plugins_and_masters.update(plugins_and_masters_to_check) # Extract all masters of plugins in the current loop for p in plugins_and_masters_to_check.copy(): masters = pluginlist.masters(p) plugins_and_masters_to_check.update(masters) # Remove all masters that were already checked in a previous loop plugins_and_masters_to_check.difference_update(plugins_and_masters) # Missing masters found -> enable mods and do another round checking them for masters if len(plugins_and_masters_to_check) > 0: additional_mods = set( [plugin_to_mod[p] for p in plugins_and_masters_to_check]) qInfo( f"Enabling {additional_mods} containing missing masters {plugins_and_masters_to_check}" .encode('ascii', 'replace').decode('ascii')) modlist.setActive(list(additional_mods), active=True) enabled_mods.update(additional_mods) except KeyError as e: raise PrepareMergeException(e.args[0]) # Enable only target plugins and their masters # Not other plugins inside the same mod enable_plugins(plugins_and_masters) enabled_plugins.update(plugins_and_masters) enabled_plugins.difference_update(mandatory_plugins) # Place plugins at end of load order max_priority = len(pluginlist.pluginNames()) - 1 for p in plugins: pluginlist.setPriority(p, max_priority) return list(enabled_plugins), list(enabled_mods)
def __init__(self, parent=None): super(MyMainWindow, self).__init__(parent) self.init_ui() self.version = "2.1.2" # 获取api操作 self.v2rayL = V2rayL() # 开启连接线程 self.conn_start = ConnectThread() # 断开连接线程 self.disconn_start = DisConnectThread() # 更新线程 self.update_addr_start = UpdateSubsThread() self.update_subs_start = UpdateSubsThread() self.ping_start = PingThread() # 检查版本更新线程 self.check_update_start = CheckUpdateThread(version=self.version) # 更新版本线程 self.version_update_start = VersionUpdateThread() # CMD线程 self.run_cmd_start = RunCmdThread() self.run_cmd_start.start() if self.v2rayL.current_status.auto: self.config_setting_ui.switchBtn = SwitchBtn(self.config_setting_ui.label_9, True) self.config_setting_ui.switchBtn.setGeometry(0, 0, 60, 30) else: self.config_setting_ui.switchBtn = SwitchBtn(self.config_setting_ui.label_9, False) self.config_setting_ui.switchBtn.setGeometry(0, 0, 60, 30) # 自动更新订阅 if self.v2rayL.current_status.auto and self.v2rayL.current_status.url: try: self.update_subs_start.v2rayL = self.v2rayL self.update_subs_start.subs_child_ui = None self.update_subs_start.start() except: # with open("/etc/v2rayL/ncurrent", "wb") as jf: # self.v2rayL.current_status.url = set() # self.v2rayL.current_status.auto = False # pickle.dump(self.v2rayL.current_status, jf) shell = "notify-send -i /etc/v2rayL/images/logo.ico v2rayL '{}'".format("更新失败") subprocess.call([shell], shell=True) # 自动检查更新 if self.v2rayL.current_status.check: self.system_setting_ui.switchBtn = SwitchBtn(self.system_setting_ui.label_8, True) self.system_setting_ui.switchBtn.setGeometry(0, 0, 60, 30) self.check_update_start.start() else: self.system_setting_ui.switchBtn = SwitchBtn(self.system_setting_ui.label_8, False) self.system_setting_ui.switchBtn.setGeometry(0, 0, 60, 30) # 是否启用日志 if self.v2rayL.current_status.log: self.a3.setChecked(True) self.a4.setChecked(False) else: self.a4.setChecked(True) self.a3.setChecked(False) # 填充当前订阅地址 # print(self.v2rayL.current_status.url) self.config_setting_ui.lineEdit.setText(";".join([x[1] for x in self.v2rayL.current_status.url])) # 端口 self.system_setting_ui.http_sp.setValue(self.v2rayL.current_status.http) self.system_setting_ui.socks_sp.setValue(self.v2rayL.current_status.socks) # # 显示当前所有配置 self.display_all_conf() qInfo("{}@$ff$@app start.".format(self.v2rayL.current_status.log)) # self.ping_start = PingThread(tv=(self.tableView, self.v2rayL)) # 事件绑定 self.config_setting_ui.switchBtn.checkedChanged.connect(self.change_auto_update) self.system_setting_ui.switchBtn.checkedChanged.connect(self.change_check_update) # self.system_setting_ui.switchBtn1.checkedChanged.connect(self.auto_on) self.first_ui.pushButton.clicked.connect(lambda: self.update_subs(True)) # 更新订阅 self.subs_add_child_ui.pushButton.clicked.connect(self.change_subs_addr) # self.subs_add_child_ui.textEdit.returnPressed.connect(self.change_subs_addr) self.config_setting_ui.pushButton_2.clicked.connect(self.output_conf) # 导出配置文件 self.config_setting_ui.pushButton.clicked.connect(self.get_conf_from_qr) # 通过二维码导入 self.first_ui.pushButton_1.clicked.connect(self.start_ping_th) # 测试延时 self.system_setting_ui.checkupdateButton.clicked.connect(self.check_update) # 检查更新 # self.config_setting_ui.lineEdit.returnPressed.connect(self.change_subs_addr) # 更新订阅操作 self.config_setting_ui.pushButton_3.clicked.connect(self.show_subs_dialog) # 显示具体订阅操作 self.config_setting_ui.lineEdit_2.returnPressed.connect(self.get_conf_from_uri) # 解析URI获取配置 self.conn_start.sinOut.connect(self.alert) # 得到连接反馈 self.disconn_start.sinOut.connect(self.alert) # 得到断开连接反馈 self.update_addr_start.sinOut.connect(self.alert) # 得到反馈 self.update_subs_start.sinOut.connect(self.alert) # 得到反馈 self.ping_start.sinOut.connect(self.alert) # 得到反馈 self.check_update_start.sinOut.connect(self.alert) self.version_update_start.sinOut.connect(self.alert) self.system_setting_ui.http_sp.valueChanged.connect(lambda: self.value_change(True)) self.system_setting_ui.socks_sp.valueChanged.connect(lambda: self.value_change(False)) self.config_setting_ui.pushButton_ss.clicked.connect(self.show_add_ss_dialog) self.config_setting_ui.pushButton_vmess.clicked.connect(self.show_add_vmess_dialog) self.ss_add_child_ui.pushButton.clicked.connect(self.add_ss_by_input) self.vmess_add_child_ui.pushButton.clicked.connect(self.add_vmess_by_input) self.subs_child_ui.pushButton.clicked.connect(self.show_add_subs_dialog) self.a1.triggered.connect(self.show) self.a3.triggered.connect(self.enable_log) self.a4.triggered.connect(self.disable_log) # print("hahh") # 设置最小化到托盘 SystemTray(self, app)
def alert(self, tp): """ 操作反馈 """ tp, rs, ret, row = tp if rs == "@@OK@@": if tp == "conn": # QMessageBox.information(self, "连接成功", self.tr("连接成功!当前状态: " + ret)) shell = "notify-send -i /etc/v2rayL/images/logo.ico v2rayL '连接成功!当前状态: " + ret + "'" subprocess.call([shell], shell=True) qInfo("{}@$ff$@Successfully connected to: {}".format(self.v2rayL.current_status.log, ret).encode()) self.display_all_conf() elif tp == "disconn": shell = "notify-send -i /etc/v2rayL/images/logo.ico v2rayL VPN连接已断开" subprocess.call([shell], shell=True) qInfo("{}@$ff$@VPN connection disconnected.".format(self.v2rayL.current_status.log)) self.display_all_conf() elif tp == "addr": # shell = "notify-send -i /etc/v2rayL/images/logo.ico v2rayL 更新订阅地址成功" # subprocess.call([shell], shell=True) qInfo("{}@$ff$@Add a new subscription address: {}".format(self.v2rayL.current_status.log, ret)) self.v2rayL = V2rayL() self.display_all_conf() self.show_subs_dialog() self.subs_add_child_ui.lineEdit.setText("") self.subs_add_child_ui.textEdit.setPlainText("") self.add_subs_ui.hide() self.config_setting_ui.lineEdit.setText(";".join([x[1] for x in self.v2rayL.current_status.url])) elif tp == "update": shell = "notify-send -i /etc/v2rayL/images/logo.ico v2rayL 订阅更新完成" subprocess.call([shell], shell=True) if not ret[1]: qInfo("{}@$ff$@Successfully updated subscription.".format(self.v2rayL.current_status.log)) else: retinfo = "" for i in ret[1]: retinfo += "\n{}-{}-{}".format(i[0][0], i[0][1], i[1]) qInfo("{}@$ff$@{}".format(self.v2rayL.current_status.log, retinfo).encode()) # print(retinfo) self.v2rayL = V2rayL() # print(123) self.display_all_conf() self.config_setting_ui.lineEdit.setText(";".join([x[1] for x in self.v2rayL.current_status.url])) elif tp == "ping": if isinstance(ret, int): self.first_ui.time.setText(str(ret)+"ms") else: self.first_ui.time.setText(ret) elif tp == "ckud": if not row: shell = "notify-send -i /etc/v2rayL/images/logo.ico v2rayL {}".format(ret) subprocess.call([shell], shell=True) else: choice = QMessageBox.question(self, "检查更新", "最新版本: v{}" "\n更新内容:\n{}\n是否更新?".format( row.json()['tag_name'], row.json()['body']), QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes) if choice == QMessageBox.Yes: shell = "notify-send -i /etc/v2rayL/images/logo.ico v2rayL {}".format(ret) subprocess.call([shell], shell=True) self.version_update_start.url = "http://dl.thinker.ink/update.sh" qInfo("{}@$ff$@Ready to update, the latest version number is: v{}.".format( self.v2rayL.current_status.log, row.json()['tag_name'])) self.version_update_start.start() elif tp == "vrud": shell = "notify-send -i /etc/v2rayL/images/logo.ico v2rayL '{}'".format(ret) subprocess.call([shell], shell=True) qInfo("{}@$ff$@Successfully updated to the latest version.".format(self.v2rayL.current_status.log)) else: if tp == "addr": shell = "notify-send -i /etc/v2rayL/images/logo.ico v2rayL '{}'".format(ret) subprocess.call([shell], shell=True) if ret == "无法获取订阅信息,订阅站点访问失败": ret = "Failed to access subscription site, unable to get subscription information" elif ret == "解析订阅信息失败,请确认链接正确": ret = "Failed to resolve subscription information, please confirm the link is correct" else: pass qInfo("{}@$ff$@Failed to get subscriptions: {}.".format(self.v2rayL.current_status.log, ret)) elif tp == "conn": shell = "notify-send -i /etc/v2rayL/images/logo.ico v2rayL {}".format(ret) subprocess.call([shell], shell=True) self.display_all_conf() elif tp == "disconn": shell = "notify-send -i /etc/v2rayL/images/logo.ico v2rayL {}".format(ret) subprocess.call([shell], shell=True) self.display_all_conf() elif tp == "ckud": shell = "notify-send -i /etc/v2rayL/images/logo.ico v2rayL {}".format(ret) subprocess.call([shell], shell=True) elif tp == "vrud": shell = "notify-send -i /etc/v2rayL/images/logo.ico v2rayL {}".format(ret) subprocess.call([shell], shell=True) elif tp == "ping": self.first_ui.time.setText(str(ret))