def update_plot(self): """ Replots the entire spectrum canvas with a new maximal power. """ # remove the old plot self.wCanvas.fig.clf() # retrieve new pmax value text = self.pmax_edit.text() text = text.replace(",", ".") pmax = float(text) # pmax_edit has a positive float validator if self.DEBUG: print(f"new pmax value {pmax}") # creates the ax and attaches it to the widget figure axs = pl.mk_signal_modulus_ax(self.time_unit, fig=self.wCanvas.fig) pl.plot_signal_modulus( axs, time_vector=self.tvec, signal=self.signal, modulus=self.modulus, periods=self.periods, p_max=pmax, ) # redraw COI if checkbox is checked self.draw_coi() # re-draw ridge if self._has_ridge: self.draw_ridge() # refresh the canvas self.wCanvas.draw() self.wCanvas.show()
def compute_spectrum(self, raw_signal, sinc_detrend=True, norm_amplitude=False, do_plot=True, draw_coi=False): """ Computes the Wavelet spectrum for a given *signal* for the given *periods* signal : a sequence, the time-series to be analyzed sinc_detrend : boolean, if True sinc-filter detrending will be done with the set T_cut_off parameter norm_amplitude : boolean, if True sliding window amplitude envelope estimation is performed, and normalisation with 1/envelope do_plot : boolean, set to False if no plot is desired, good for for batch processing draw_coi: boolean, set to True if cone of influence shall be drawn on the wavelet power spectrum After a successful analysis, the analyser instance updates self.wlet self.modulus with the results. """ if sinc_detrend: detrended = self.sinc_detrend(raw_signal) ana_signal = detrended else: ana_signal = raw_signal # only after potential detrending! if norm_amplitude: ana_signal = self.normalize_amplitude(ana_signal) self.ana_signal = ana_signal modulus, wlet = core.compute_spectrum(ana_signal, self.dt, self.periods) if do_plot: tvec = np.arange(len(ana_signal)) * self.dt axs = pl.mk_signal_modulus_ax(self.time_unit_label) pl.plot_signal_modulus( axs, time_vector=tvec, signal=ana_signal, modulus=modulus, periods=self.periods, p_max=self.p_max, ) fig = ppl.gcf() fig.tight_layout() self.ax_spec = axs[1] if draw_coi: coi_m = core.Morlet_COI() pl.draw_COI(axs[1], time_vector=tvec) self.wlet = wlet self.modulus = modulus self._has_spec = True
def compute_spectrum(self, raw_signal, T_c=None, window_size=None, do_plot=True, draw_coi=False): """ Computes the Wavelet spectrum for a given *raw_signal*. Parameters ---------- signal : a sequence, the time-series to be analyzed T_c : float, optional Cut off period for the sinc-filter detrending, all periods larger than that one are removed from the signal. If not given, no sinc-detending will be done. window_size : float, optional Length of the sliding window for amplitude envelope estimation in real time units, e.g. 17 minutes. If not given no amplitude normalization will be done. do_plot : boolean, set to False if no plot is desired, good for batch processing draw_coi: boolean, set to True if cone of influence shall be drawn on the wavelet power spectrum Returns ------- modulus : 2d ndarray the real Wavelet power spectrum normalized by signal variance, has shape len(periods) x len(signal). Is set to None before any analysis is done. transform : 2d ndarray the complex results of the Wavelet transform with shape len(periods) x len(signal). Is set to None before any analysis is done. After a successful analysis, the analyzer instance updates self.transform self.modulus with the results. If do_plot was set to True, the attributes self.ax_spec_signal self.ax_spec allow to access the created subplots directly. """ if T_c: detrended = self.sinc_detrend(raw_signal, T_c) ana_signal = detrended else: ana_signal = raw_signal # only after potential detrending! if window_size: ana_signal = self.normalize_amplitude(ana_signal, window_size) self.ana_signal = ana_signal modulus, transform = core.compute_spectrum(ana_signal, self.dt, self.periods) if do_plot: tvec = np.arange(len(ana_signal)) * self.dt axs = pl.mk_signal_modulus_ax(self.time_unit_label) pl.plot_signal_modulus( axs, time_vector=tvec, signal=ana_signal, modulus=modulus, periods=self.periods, p_max=self.p_max, ) fig = ppl.gcf() fig.tight_layout() # some space for a title fig.subplots_adjust(top=0.95) self.ax_spec_signal = axs[0] self.ax_spec = axs[1] if draw_coi: pl.draw_COI(axs[1], time_vector=tvec) self.transform = transform self.modulus = modulus # return also directly return modulus, transform
def initUI(self, position): self.setWindowTitle("Wavelet Spectrum - " + str(self.signal_id)) self.setGeometry(510 + position, 80 + position, 620, 750) main_widget = QWidget() self.statusBar() # Wavelet and signal plot self.wCanvas = mkWaveletCanvas() main_frame = QWidget() self.wCanvas.setParent(main_frame) ntb = NavigationToolbar(self.wCanvas, main_frame) # full toolbar # -------------plot the wavelet power spectrum--------------------------- # creates the ax and attaches it to the widget figure axs = pl.mk_signal_modulus_ax(self.time_unit, fig=self.wCanvas.fig) pl.plot_signal_modulus( axs, time_vector=self.tvec, signal=self.signal, modulus=self.modulus, periods=self.periods, p_max=self.pow_max, ) self.wCanvas.fig.subplots_adjust(bottom=0.11, right=0.95, left=0.13, top=0.95) self.wCanvas.fig.tight_layout() # --- Spectrum plotting options --- spectrum_opt_box = QGroupBox("Spectrum Plotting Options") spectrum_opt_box.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) spectrum_opt_layout = QHBoxLayout() spectrum_opt_layout.setSpacing(10) spectrum_opt_box.setLayout(spectrum_opt_layout) # uppler limit of the colormap <-> imshow(...,vmax = pmax) pmax_label = QLabel("Maximal Power:") self.pmax_edit = QLineEdit() self.pmax_edit.setStatusTip("Sets upper power limit of the spectrum") self.pmax_edit.setMaximumWidth(80) self.pmax_edit.setValidator(posfloatV) # retrieve initial power value, axs[1] is the spectrum pmin, pmax = axs[1].images[0].get_clim() self.pmax_edit.insert(f"{pmax:.0f}") RePlotButton = QPushButton("Update Plot", self) RePlotButton.setStatusTip( "Rescales the color map of the spectrum with the new max value") RePlotButton.clicked.connect(self.update_plot) self.cb_coi = QCheckBox("COI", self) self.cb_coi.setStatusTip( "Draws the cone of influence onto the spectrum") self.cb_coi.stateChanged.connect(self.draw_coi) # ridge_opt_layout.addWidget(drawRidgeButton,1,3) # not needed anymore?! spectrum_opt_layout.addWidget(pmax_label) spectrum_opt_layout.addWidget(self.pmax_edit) spectrum_opt_layout.addStretch(0) spectrum_opt_layout.addWidget(RePlotButton) spectrum_opt_layout.addStretch(0) spectrum_opt_layout.addWidget(self.cb_coi) # --- Time average -> asymptotic Fourier --- time_av_box = QGroupBox("Time Averaging") estimFourierButton = QPushButton("Estimate Fourier", self) estimFourierButton.clicked.connect(self.ini_average_spec) estimFourierButton.setStatusTip( "Shows time averaged Wavelet power spectrum") time_av_layout = QHBoxLayout() # time_av_layout.addStretch() time_av_layout.addWidget(estimFourierButton) # time_av_layout.addStretch() time_av_box.setLayout(time_av_layout) # --- Ridge detection and options -- ridge_opt_box = QGroupBox("Ridge Detection") ridge_opt_box.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) ridge_opt_layout = QGridLayout() ridge_opt_box.setLayout(ridge_opt_layout) # Start ridge detection maxRidgeButton = QPushButton("Detect Maximum Ridge", self) maxRidgeButton.setStatusTip("Finds the time-consecutive power maxima") maxRidgeButton.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) maxRidgeButton.clicked.connect(self.do_maxRidge_detection) # remove annealing, too slow.. not well implemented # annealRidgeButton = QPushButton('Set up ridge\nfrom annealing', self) # annealRidgeButton.clicked.connect(self.set_up_anneal) power_label = QLabel("Ridge Threshold:") power_label.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) power_thresh_edit = QLineEdit() power_thresh_edit.setStatusTip( "Sets the minimal power value required to be considered part of the ridge" ) power_thresh_edit.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) power_thresh_edit.setMinimumSize(60, 0) power_thresh_edit.setValidator(posfloatV) smooth_label = QLabel("Ridge Smoothing:") ridge_smooth_edit = QLineEdit() ridge_smooth_edit.setStatusTip( "Savitzky-Golay smoothing (k=3) of the ridge in time") ridge_smooth_edit.setMinimumSize(60, 0) ridge_smooth_edit.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) ridge_smooth_edit.setValidator( QIntValidator(bottom=3, top=len(self.signal))) # Plot Results plotResultsButton = QPushButton("Plot Ridge Readout", self) plotResultsButton.setStatusTip( "Shows instantaneous period, phase, power and amplitude along the ridge" ) # plotResultsButton.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) plotResultsButton.clicked.connect(self.ini_plot_readout) ridge_opt_layout.addWidget(maxRidgeButton, 0, 0, 1, 1) ridge_opt_layout.addWidget(plotResultsButton, 1, 0, 1, 1) # ridge_opt_layout.addWidget(annealRidgeButton,1,0) ridge_opt_layout.addWidget(power_label, 0, 1) ridge_opt_layout.addWidget(power_thresh_edit, 0, 2) ridge_opt_layout.addWidget(smooth_label, 1, 1) ridge_opt_layout.addWidget(ridge_smooth_edit, 1, 2) # for spacing rtool_box = QWidget() rtool_layout = QHBoxLayout() rtool_box.setLayout(rtool_layout) rtool_layout.addWidget(ridge_opt_box) rtool_layout.addStretch(0) # --- put everything together --- main_layout = QGridLayout() # main_layout.setSpacing(0) main_layout.addWidget(self.wCanvas, 0, 0, 4, 5) main_layout.addWidget(ntb, 5, 0, 1, 5) main_layout.addWidget(spectrum_opt_box, 6, 0, 1, 3) main_layout.addWidget(time_av_box, 6, 3, 1, 1) main_layout.addItem(QSpacerItem(2, 15), 6, 5) main_layout.addWidget(ridge_opt_box, 7, 0, 1, 5) # set stretching (resizing) behavior main_layout.setRowStretch(0, 1) # plot should stretch main_layout.setRowMinimumHeight( 0, 300) # plot should not get squeezed too much main_layout.setRowStretch(5, 0) # options shouldn't stretch main_layout.setRowStretch(6, 0) # options shouldn't stretch main_layout.setRowStretch(7, 0) # options shouldn't stretch # initialize line edits power_thresh_edit.textChanged[str].connect(self.qset_power_thresh) power_thresh_edit.insert("0.0") # initialize with 0 ridge_smooth_edit.textChanged[str].connect(self.qset_ridge_smooth) ridge_smooth_edit.insert("0") # initialize with 0 main_widget.setLayout(main_layout) self.setCentralWidget(main_widget) self.show()
# plot the signal/trend tvec = np.arange(len(signal)) * dt ax = pl.mk_signal_ax(time_unit='s') pl.draw_signal(ax, tvec, signal) # pl.draw_detrended(ax, tvec, signal) pl.draw_trend(ax, tvec, trend) ppl.legend(ncol=2) ppl.tight_layout() # --- compute spectrum on the original signal --- modulus, wlet = pyboat.compute_spectrum(signal, dt, periods) # plot spectrum and ridge ax_sig, ax_spec = pl.mk_signal_modulus_ax(time_unit) pl.plot_signal_modulus((ax_sig, ax_spec), tvec, signal, modulus, periods) # --- compute spectrum on the detrended signal --- modulus, wlet = pyboat.compute_spectrum(detr_signal, dt, periods) # get maximum ridge ridge_ys = pyboat.get_maxRidge_ys(modulus) # evaluate along the ridge ridge_results = pyboat.eval_ridge(ridge_ys, wlet, signal, periods, tvec) # plot spectrum and ridge ax_sig2, ax_spec2 = pl.mk_signal_modulus_ax(time_unit) pl.plot_signal_modulus((ax_sig2, ax_spec2), tvec, signal, modulus, periods) pl.draw_Wavelet_ridge(ax_spec2, ridge_results)
def do_the_loop(self): ''' Uses the explicitly parsed self.wlet_pars to control signal analysis settings. Takes general analysis Parameters self.parentDV.dt self.parentDV.time_unit and the DataFrame self.parentDV.df from the parent DataViewer. Reads additional settings from this Batch Process Window. ''' if self.export_options.isChecked(): OutPath = self.get_OutPath() if OutPath is None: return periods = np.linspace(self.wlet_pars['T_min'], self.wlet_pars['T_max'], self.wlet_pars['step_num']) # retrieve batch settings power_thresh = self.get_thresh() rsmooth = self.get_ridge_smooth() ridge_results = {} for i, signal_id in enumerate(self.parentDV.df): # log to terminal print(f"processing {signal_id}..") # sets parentDV.raw_signal and parentDV.tvec succ = self.parentDV.vector_prep(signal_id) # ui silently passes over.. if not succ: print(f"Can't process signal {signal_id}..") continue # detrend?! if self.parentDV.cb_use_detrended.isChecked(): trend = self.parentDV.calc_trend() signal = self.parentDV.raw_signal - trend else: signal = self.parentDV.raw_signal # amplitude normalization? if self.parentDV.cb_use_envelope.isChecked(): if self.debug: print('Calculating envelope with L=', self.wlet_pars['L']) signal = pyboat.normalize_with_envelope( signal, self.wlet_pars['L'], self.parentDV.dt) # compute the spectrum modulus, wlet = pyboat.compute_spectrum(signal, self.parentDV.dt, periods) # get maximum ridge ridge = pyboat.get_maxRidge_ys(modulus) # generate time vector tvec = np.arange(len(signal)) * self.parentDV.dt # evaluate along the ridge ridge_data = pyboat.eval_ridge(ridge, wlet, signal, periods, tvec, power_thresh, smoothing_wsize=rsmooth) ridge_results[signal_id] = (ridge_data) # -- Save out individual results -- if self.cb_specs.isChecked(): # plot spectrum and ridge ax_sig, ax_spec = pl.mk_signal_modulus_ax( self.parentDV.time_unit) pl.plot_signal_modulus((ax_sig, ax_spec), tvec, signal, modulus, periods, p_max=self.wlet_pars['p_max']) pl.draw_Wavelet_ridge(ax_spec, ridge_data) plt.tight_layout() fname = f'{OutPath}/{signal_id}_wspec.png' if self.debug: print(f'Plotting and saving {signal_id} to {fname}') plt.savefig(fname) plt.close() if self.cb_readout_plots.isChecked(): pl.plot_readout(ridge_data) fname = f'{OutPath}/{signal_id}_readout.png' if self.debug: print(f'Plotting and saving {signal_id} to {fname}') plt.savefig(fname) plt.close() if self.cb_readout.isChecked(): fname = f'{OutPath}/{signal_id}_readout.csv' if self.debug: print(f'Saving ridge reatout to {fname}') ridge_data.to_csv(fname, sep=',', float_format='%.3f', index=False) self.progress.setValue(i) return ridge_results
def do_the_loop(self): ''' Uses the explicitly parsed self.wlet_pars to control signal analysis settings. Takes general analysis Parameters self.parentDV.dt self.parentDV.time_unit and the DataFrame self.parentDV.df from the parent DataViewer. Reads additional settings from this Batch Process Window. ''' EmptyRidge = 0 if self.export_options.isChecked(): OutPath = self.get_OutPath() if OutPath is None: return periods = np.linspace(self.wlet_pars['T_min'], self.wlet_pars['T_max'], self.wlet_pars['step_num']) # retrieve batch settings power_thresh = self.get_thresh() rsmooth = self.get_ridge_smooth() # results get stored here ridge_results = {} df_fouriers = pd.DataFrame(index=periods) df_fouriers.index.name = 'period' for i, signal_id in enumerate(self.parentDV.df): # log to terminal print(f"processing {signal_id}..") # sets parentDV.raw_signal and parentDV.tvec succ = self.parentDV.vector_prep(signal_id) # ui silently passes over.. if not succ: print(f"Can't process signal {signal_id}..") continue # detrend?! if self.parentDV.cb_use_detrended.isChecked(): trend = self.parentDV.calc_trend() signal = self.parentDV.raw_signal - trend else: signal = self.parentDV.raw_signal # amplitude normalization? if self.parentDV.cb_use_envelope.isChecked(): if self.debug: print('Calculating envelope with L=', self.wlet_pars['L']) signal = pyboat.normalize_with_envelope( signal, self.wlet_pars['L'], self.parentDV.dt) # compute the spectrum modulus, wlet = pyboat.compute_spectrum(signal, self.parentDV.dt, periods) # get maximum ridge ridge = pyboat.get_maxRidge_ys(modulus) # generate time vector tvec = np.arange(len(signal)) * self.parentDV.dt # evaluate along the ridge ridge_data = pyboat.eval_ridge(ridge, wlet, signal, periods, tvec, power_thresh, smoothing_wsize=rsmooth) # from ridge thresholding.. if ridge_data.empty: EmptyRidge += 1 else: ridge_results[signal_id] = ridge_data # time average the spectrum, all have shape len(periods)! averaged_Wspec = np.mean(modulus, axis=1) df_fouriers[signal_id] = averaged_Wspec # -- Save out individual results -- if self.cb_specs.isChecked(): # plot spectrum and ridge ax_sig, ax_spec = pl.mk_signal_modulus_ax( self.parentDV.time_unit) pl.plot_signal_modulus((ax_sig, ax_spec), tvec, signal, modulus, periods, p_max=self.wlet_pars['p_max']) pl.draw_Wavelet_ridge(ax_spec, ridge_data) plt.tight_layout() fname = os.path.join(OutPath, f'{signal_id}_wspec.png') if self.debug: print( f'Plotting and saving spectrum {signal_id} to {fname}') plt.savefig(fname, dpi=DPI) plt.close() if self.cb_specs_noridge.isChecked(): # plot spectrum without ridge ax_sig, ax_spec = pl.mk_signal_modulus_ax( self.parentDV.time_unit) pl.plot_signal_modulus((ax_sig, ax_spec), tvec, signal, modulus, periods, p_max=self.wlet_pars['p_max']) plt.tight_layout() fname = os.path.join(OutPath, f'{signal_id}_wspecNR.png') if self.debug: print( f'Plotting and saving spectrum {signal_id} to {fname}') plt.savefig(fname, dpi=DPI) plt.close() if self.cb_readout_plots.isChecked() and not ridge_data.empty: pl.plot_readout(ridge_data) fname = os.path.join(OutPath, f'{signal_id}_readout.png') if self.debug: print(f'Plotting and saving {signal_id} to {fname}') plt.savefig(fname, dpi=DPI) plt.close() if self.cb_readout.isChecked() and not ridge_data.empty: fname = os.path.join(OutPath, f'{signal_id}_readout.csv') if self.debug: print(f'Saving ridge reatout to {fname}') ridge_data.to_csv(fname, sep=',', float_format='%.3f', index=False) self.progress.setValue(i) if EmptyRidge > 0: self.NoRidges = MessageWindow( f'{EmptyRidge} ridge readouts entirely below threshold..', 'Discarded ridges') return ridge_results, df_fouriers
def do_the_loop(self): """ Uses the explicitly parsed self.wlet_pars to control signal analysis settings. Takes general analysis Parameters self.parentDV.dt self.parentDV.time_unit and the DataFrame self.parentDV.df from the parent DataViewer. Reads additional settings from this Batch Process Window. """ EmptyRidge = 0 if self.export_options.isChecked(): OutPath = self.get_OutPath() if OutPath is None: return periods = np.linspace(self.wlet_pars["Tmin"], self.wlet_pars["Tmax"], self.wlet_pars["step_num"]) # retrieve batch settings power_thresh = self.get_thresh() rsmooth = self.get_ridge_smooth() # results get stored here ridge_results = {} df_fouriers = pd.DataFrame(index=periods) df_fouriers.index.name = "period" for i, signal_id in enumerate(self.parentDV.df): # log to terminal print(f"processing {signal_id}..") # sets parentDV.raw_signal and parentDV.tvec succ = self.parentDV.vector_prep(signal_id) # ui silently passes over.. if not succ: print(f"Warning, can't process signal {signal_id}..") continue # detrend?! if self.parentDV.cb_use_detrended.isChecked(): trend = self.parentDV.calc_trend() signal = self.parentDV.raw_signal - trend else: signal = self.parentDV.raw_signal # amplitude normalization? if self.parentDV.cb_use_envelope.isChecked(): if self.debug: print("Calculating envelope with L=", self.wlet_pars["window_size"]) signal = pyboat.normalize_with_envelope( signal, self.wlet_pars["window_size"], self.parentDV.dt) # compute the spectrum modulus, wlet = pyboat.compute_spectrum(signal, self.parentDV.dt, periods) # get maximum ridge ridge = pyboat.get_maxRidge_ys(modulus) # generate time vector tvec = np.arange(len(signal)) * self.parentDV.dt # evaluate along the ridge ridge_data = pyboat.eval_ridge( ridge, wlet, signal, periods, tvec, power_thresh, smoothing_wsize=rsmooth, ) # from ridge thresholding.. if ridge_data.empty: EmptyRidge += 1 else: ridge_results[signal_id] = ridge_data # time average the spectrum, all have shape len(periods)! averaged_Wspec = np.mean(modulus, axis=1) df_fouriers[signal_id] = averaged_Wspec # -- Save out individual results -- settings = QSettings() float_format = settings.value('float_format', '%.3f') graphics_format = settings.value('graphics_format', 'png') exbox_checked = self.export_options.isChecked() if exbox_checked and self.cb_filtered_sigs.isChecked(): signal_df = pd.DataFrame() signal_df['signal'] = signal signal_df.index = tvec signal_df.index.name = 'time' fname = os.path.join(OutPath, f"{signal_id}_filtered.csv") if self.debug: print(f"Saving filtered signal to {fname}") signal_df.to_csv(fname, sep=",", float_format=float_format, index=True, header=True) if exbox_checked and self.cb_specs.isChecked(): # plot spectrum and ridge ax_sig, ax_spec = pl.mk_signal_modulus_ax( self.parentDV.time_unit) pl.plot_signal_modulus( (ax_sig, ax_spec), tvec, signal, modulus, periods, p_max=self.wlet_pars["pow_max"], ) pl.draw_Wavelet_ridge(ax_spec, ridge_data) plt.tight_layout() fname = os.path.join(OutPath, f"{signal_id}_wspec.{graphics_format}") if self.debug: print( f"Plotting and saving spectrum {signal_id} to {fname}") plt.savefig(fname, dpi=DPI) plt.close() if exbox_checked and self.cb_specs_noridge.isChecked(): # plot spectrum without ridge ax_sig, ax_spec = pl.mk_signal_modulus_ax( self.parentDV.time_unit) pl.plot_signal_modulus( (ax_sig, ax_spec), tvec, signal, modulus, periods, p_max=self.wlet_pars["pow_max"], ) plt.tight_layout() fname = os.path.join(OutPath, f"{signal_id}_wspecNR.{graphics_format}") if self.debug: print( f"Plotting and saving spectrum {signal_id} to {fname}") plt.savefig(fname, dpi=DPI) plt.close() if exbox_checked and self.cb_readout_plots.isChecked( ) and not ridge_data.empty: pl.plot_readout(ridge_data) fname = os.path.join(OutPath, f"{signal_id}_readout.{graphics_format}") if self.debug: print(f"Plotting and saving {signal_id} to {fname}") plt.savefig(fname, dpi=DPI) plt.close() if exbox_checked and self.cb_readout.isChecked( ) and not ridge_data.empty: fname = os.path.join(OutPath, f"{signal_id}_readout.csv") if self.debug: print(f"Saving ridge readout to {fname}") ridge_data.to_csv(fname, sep=",", float_format=float_format, index=False) self.progress.setValue(i) if EmptyRidge > 0: msg = f"{EmptyRidge} ridge readouts entirely below threshold.." msgBox = QMessageBox() msgBox.setWindowTitle("Discarded Ridges") msgBox.setText(msg) msgBox.exec() return ridge_results, df_fouriers
def initUI(self, position): self.setWindowTitle('Wavelet Spectrum - ' + str(self.signal_id)) self.setGeometry(510 + position, 80 + position, 620, 750) # Wavelet and signal plot self.wCanvas = mkWaveletCanvas() main_frame = QWidget() self.wCanvas.setParent(main_frame) ntb = NavigationToolbar(self.wCanvas, main_frame) # full toolbar #-------------plot the wavelet power spectrum--------------------------- # creates the ax and attaches it to the widget figure axs = pl.mk_signal_modulus_ax(self.time_unit, fig=self.wCanvas.fig) pl.plot_signal_modulus(axs, time_vector=self.tvec, signal=self.signal, modulus=self.modulus, periods=self.periods, p_max=self.p_max) self.wCanvas.fig.subplots_adjust(bottom=0.11, right=0.95, left=0.13, top=0.95) self.wCanvas.fig.tight_layout() # --- Spectrum plotting options --- spectrum_opt_box = QGroupBox("Plotting Options") spectrum_opt_box.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) spectrum_opt_layout = QHBoxLayout() spectrum_opt_layout.setSpacing(10) spectrum_opt_box.setLayout(spectrum_opt_layout) # uppler limit of the colormap <-> imshow(...,vmax = pmax) pmax_label = QLabel("Maximal Power:") self.pmax_edit = QLineEdit() self.pmax_edit.setToolTip('Rescales the color map of the spectrum') self.pmax_edit.setMaximumWidth(60) self.pmax_edit.setValidator(posfloatV) # retrieve initial power value, axs[1] is the spectrum pmin, pmax = axs[1].images[0].get_clim() self.pmax_edit.insert(f'{pmax:.0f}') RePlotButton = QPushButton('Update Plot', self) RePlotButton.setToolTip( 'Redraws the spectrum with the new upper power limit') RePlotButton.clicked.connect(self.update_plot) self.cb_coi = QCheckBox('COI', self) self.cb_coi.setToolTip('Draws the cone of influence onto the spectrum') self.cb_coi.stateChanged.connect(self.draw_coi) # ridge_opt_layout.addWidget(drawRidgeButton,1,3) # not needed anymore?! spectrum_opt_layout.addWidget(pmax_label) spectrum_opt_layout.addWidget(self.pmax_edit) spectrum_opt_layout.addStretch(0) spectrum_opt_layout.addWidget(RePlotButton) spectrum_opt_layout.addStretch(0) spectrum_opt_layout.addWidget(self.cb_coi) # --- Ridge detection and options -- ridge_opt_box = QGroupBox("Ridge Detection") ridge_opt_box.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Maximum) ridge_opt_layout = QGridLayout() ridge_opt_box.setLayout(ridge_opt_layout) #Start ridge detection maxRidgeButton = QPushButton('Detect Maximum Ridge', self) maxRidgeButton.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) maxRidgeButton.clicked.connect(self.do_maxRidge_detection) # remove annealing, too slow.. not well implemented # annealRidgeButton = QPushButton('Set up ridge\nfrom annealing', self) # annealRidgeButton.clicked.connect(self.set_up_anneal) power_label = QLabel("Ridge Threshold:") power_label.setSizePolicy(QSizePolicy.Minimum, QSizePolicy.Fixed) power_thresh_edit = QLineEdit() power_thresh_edit.setToolTip( 'Sets the minimal power value required to be part of the ridge') power_thresh_edit.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) power_thresh_edit.setMinimumSize(50, 0) power_thresh_edit.setValidator(posfloatV) smooth_label = QLabel("Ridge Smoothing:") ridge_smooth_edit = QLineEdit() ridge_smooth_edit.setMinimumSize(50, 0) ridge_smooth_edit.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) ridge_smooth_edit.setValidator( QIntValidator(bottom=3, top=len(self.signal))) # Plot Results plotResultsButton = QPushButton('Plot Ridge Readout', self) plotResultsButton.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) plotResultsButton.clicked.connect(self.ini_plot_readout) ridge_opt_layout.addWidget(maxRidgeButton, 0, 0, 1, 1) ridge_opt_layout.addWidget(plotResultsButton, 1, 0, 1, 1) # ridge_opt_layout.addWidget(annealRidgeButton,1,0) ridge_opt_layout.addWidget(power_label, 0, 1) ridge_opt_layout.addWidget(power_thresh_edit, 0, 2) ridge_opt_layout.addWidget(smooth_label, 1, 1) ridge_opt_layout.addWidget(ridge_smooth_edit, 1, 2) # for spacing rtool_box = QWidget() rtool_layout = QHBoxLayout() rtool_box.setLayout(rtool_layout) rtool_layout.addWidget(ridge_opt_box) rtool_layout.addStretch(0) # put everything together main_layout = QVBoxLayout() main_layout.setSpacing(0) main_layout.addWidget(self.wCanvas) main_layout.addWidget(ntb) main_layout.addWidget(spectrum_opt_box) main_layout.addWidget(ridge_opt_box) self.setLayout(main_layout) # initialize line edits power_thresh_edit.textChanged[str].connect(self.qset_power_thresh) power_thresh_edit.insert('0.0') # initialize with 0 ridge_smooth_edit.textChanged[str].connect(self.qset_ridge_smooth) ridge_smooth_edit.insert('0') # initialize with 0 self.show()