Пример #1
0
    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()
Пример #2
0
    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
Пример #3
0
    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
Пример #4
0
    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()
Пример #5
0
# 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)
Пример #6
0
    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
Пример #7
0
    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
Пример #8
0
    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
Пример #9
0
    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()