def plot_cwt_spectrogram(self, canvas: MatplotlibCanvas):
        tr = ObspyUtil.get_tracer_from_file(self.file_selector.file_path)
        ts, te = self.get_time_window()
        tr.trim(starttime=ts, endtime=te)
        tr.detrend(type="demean")
        fs = tr.stats.sampling_rate
        f_min = 1. / self.spectrum_box.win_bind.value if self.filter.min_freq == 0 else self.filter.min_freq
        f_max = self.filter.max_freq
        ObspyUtil.filter_trace(tr, self.filter.filter_value, f_min, f_max)
        nf = 40
        tt = int(self.spectrum_box.win_bind.value *
                 self.tracer_stats.Sampling_rate)
        wmin = self.spectrum_box.w1_bind.value
        wmax = self.spectrum_box.w2_bind.value
        npts = len(tr.data)
        [ba, nConv, frex,
         half_wave] = ccwt_ba_fast(npts, self.tracer_stats.Sampling_rate,
                                   f_min, f_max, wmin, wmax, tt, nf)
        cf, sc, scalogram = cwt_fast(tr.data, ba, nConv, frex, half_wave, fs)
        #scalogram = ccwt(tr.data, self.tracer_stats.Sampling_rate, f_min, f_max, wmin, wmax, tt, nf)

        scalogram = np.abs(scalogram)**2

        t = np.linspace(0, self.tracer_stats.Delta * npts, npts)
        scalogram2 = 10 * (np.log10(scalogram / np.max(scalogram)))
        x, y = np.meshgrid(t, np.linspace(f_min, f_max, scalogram2.shape[0]))

        max_cwt = np.max(scalogram2)
        min_cwt = np.min(scalogram2)
        canvas.plot(t[0:len(t) - 1],
                    cf,
                    0,
                    clear_plot=False,
                    is_twinx=True,
                    color="red",
                    linewidth=0.5)

        norm = Normalize(vmin=min_cwt, vmax=max_cwt)
        canvas.plot_contour(x,
                            y,
                            scalogram2,
                            axes_index=1,
                            clabel="Power [dB]",
                            levels=100,
                            cmap=plt.get_cmap("jet"),
                            norm=norm)
        canvas.set_xlabel(1, "Time (s)")
    def plot_mt_spectrogram(self, canvas: MatplotlibCanvas):
        win = int(self.spectrum_box.win_bind.value *
                  self.tracer_stats.Sampling_rate)
        tbp = self.spectrum_box.tw_bind.value
        ntapers = self.spectrum_box.ntapers_bind.value
        f_min = self.filter.min_freq
        f_max = self.filter.max_freq
        ts, te = self.get_time_window()

        mtspectrogram = MTspectrogram(self.file_selector.file_path, win, tbp,
                                      ntapers, f_min, f_max)
        x, y, log_spectrogram = mtspectrogram.compute_spectrogram(
            start_time=ts, end_time=te, trace_filter=self.filter.filter_value)
        canvas.plot_contour(x,
                            y,
                            log_spectrogram,
                            axes_index=1,
                            clabel="Power [dB]",
                            cmap=plt.get_cmap("jet"))
        canvas.set_xlabel(1, "Time (s)")
Example #3
0
class TimeFrequencyFrame(BaseFrame, UiTimeFrequencyFrame):
    def __init__(self):

        super(TimeFrequencyFrame, self).__init__()
        self.setupUi(self)
        self.__stations_dir = None
        self.__metadata_manager = None
        self.inventory = {}
        self._stations_info = {}
        self.tr1 = []
        self.tr2 = []
        self.canvas_plot1 = MatplotlibCanvas(self.widget_plot_up, nrows=2)
        # self.canvas_plot1.set_xlabel(1, "Time (s)")
        # self.canvas_plot1.set_ylabel(0, "Amplitude ")
        # self.canvas_plot1.set_ylabel(1, "Frequency (Hz)")
        self.canvas_plot2 = MatplotlibCanvas(self.widget_plot_down, nrows=2)
        # self.canvas_plot2.set_xlabel(1, "Time (s)")
        # self.canvas_plot2.set_ylabel(0, "Amplitude ")
        # self.canvas_plot2.set_ylabel(1, "Frequency (Hz)")
        # Binding
        self.canvas_plot1.mpl_connect('key_press_event', self.key_pressed)
        self.canvas_plot2.mpl_connect('key_press_event', self.key_pressed)
        self.root_path_bind = BindPyqtObject(self.rootPathForm,
                                             self.onChange_root_path)
        self.dataless_path_bind = BindPyqtObject(self.datalessPathForm)
        self.metadata_path_bind = BindPyqtObject(self.datalessPathForm,
                                                 self.onChange_metadata_path)
        # Add file selector to the widget
        self.file_selector = FilesView(
            self.root_path_bind.value,
            parent=self.fileSelectorWidget,
            on_change_file_callback=lambda file_path: self.onChange_file(
                file_path))
        # Binds
        self.selectDirBtn.clicked.connect(
            lambda: self.on_click_select_directory(self.root_path_bind))
        self.datalessBtn.clicked.connect(
            lambda: self.on_click_select_file(self.dataless_path_bind))
        # Action Buttons
        self.actionSettings.triggered.connect(
            lambda: self.open_parameters_settings())
        self.actionOpen_Help.triggered.connect(lambda: self.open_help())
        self.actionOpen_Spectral_Analysis.triggered.connect(
            self.time_frequency_advance)
        self.plotBtn.clicked.connect(self.plot_seismogram)
        self.stationsBtn.clicked.connect(self.stations_info)

        # help Documentation
        self.help = HelpDoc()

        # Parameters settings
        self.parameters = ParametersSettings()

        # Time Frequency Advance
        #self.time_frequency_advance = TimeFrequencyAdvance()

    def filter_error_message(self, msg):
        md = MessageDialog(self)
        md.set_info_message(msg)

    def message_dataless_not_found(self):
        if len(self.dataless_not_found) > 1:
            md = MessageDialog(self)
            md.set_info_message("Metadata not found.")
        else:
            for file in self.dataless_not_found:
                md = MessageDialog(self)
                md.set_info_message("Metadata for {} not found.".format(file))

        self.dataless_not_found.clear()

    def open_parameters_settings(self):
        self.parameters.show()

    def time_frequency_advance(self):
        self._time_frequency_advance = TimeFrequencyAdvance(self.tr1, self.tr2)
        self._time_frequency_advance.show()

    def validate_file(self):
        if not MseedUtil.is_valid_mseed(self.file_selector.file_path):
            msg = "The file {} is not a valid mseed. Please, choose a valid format". \
                format(self.file_selector.file_name)
            raise InvalidFile(msg)

    def onChange_root_path(self, value):
        """
        Fired every time the root_path is changed

        :param value: The path of the new directory.

        :return:
        """
        self.file_selector.set_new_rootPath(value)

    def onChange_file(self, file_path):
        # Called every time user select a different file
        pass

    def on_click_select_directory(self, bind: BindPyqtObject):
        if "darwin" == platform:
            dir_path = pw.QFileDialog.getExistingDirectory(
                self, 'Select Directory', bind.value)
        else:
            dir_path = pw.QFileDialog.getExistingDirectory(
                self, 'Select Directory', bind.value,
                pw.QFileDialog.DontUseNativeDialog)
        if dir_path:
            bind.value = dir_path

    def on_click_select_file(self, bind: BindPyqtObject):
        selected = pw.QFileDialog.getOpenFileName(self, "Select metadata file")
        if isinstance(selected[0], str) and os.path.isfile(selected[0]):
            bind.value = selected[0]

    def onChange_metadata_path(self, value):
        md = MessageDialog(self)
        try:
            self.__metadata_manager = MetadataManager(value)
            self.inventory = self.__metadata_manager.get_inventory()
            md.set_info_message(
                "Loaded Metadata, please check your terminal for further details"
            )
        except:
            md.set_error_message(
                "Something went wrong. Please check your metada file is a correct one"
            )

    @property
    def trace(self):
        return ObspyUtil.get_tracer_from_file(self.file_selector.file_path)

    def get_data(self):
        file = self.file_selector.file_path
        starttime = convert_qdatetime_utcdatetime(self.starttime_date)
        endtime = convert_qdatetime_utcdatetime(self.endtime_date)
        diff = endtime - starttime
        parameters = self.parameters.getParameters()
        sd = SeismogramDataAdvanced(file)

        if self.trimCB.isChecked() and diff >= 0:
            tr = sd.get_waveform_advanced(
                parameters,
                self.inventory,
                filter_error_callback=self.filter_error_message,
                start_time=starttime,
                end_time=endtime)
        else:
            tr = sd.get_waveform_advanced(
                parameters,
                self.inventory,
                filter_error_callback=self.filter_error_message)

        t = tr.times()
        return tr, t

    def get_time_window(self):

        t1 = convert_qdatetime_utcdatetime(self.starttime_date)
        t2 = convert_qdatetime_utcdatetime(self.endtime_date)

        return t1, t2

    def stations_info(self):
        obsfiles = MseedUtil.get_mseed_files(self.root_path_bind.value)
        obsfiles.sort()
        sd = []
        for file in obsfiles:
            st = SeismogramDataAdvanced(file)
            station = [
                st.stats.Network, st.stats.Station, st.stats.Location,
                st.stats.Channel, st.stats.StartTime, st.stats.EndTime,
                st.stats.Sampling_rate, st.stats.Npts
            ]
            sd.append(station)
        self._stations_info = StationsInfo(sd, check=False)
        self._stations_info.show()

    def plot_seismogram(self):
        selection = self.selectCB.currentText()

        if selection == "Seismogram 1":
            #self.validate_file()
            [self.tr1, t] = self.get_data()
            self.canvas_plot1.plot(t,
                                   self.tr1.data,
                                   0,
                                   clear_plot=True,
                                   color="black",
                                   linewidth=0.5)
            self.canvas_plot1.set_xlabel(1, "Time (s)")
            self.canvas_plot1.set_ylabel(0, "Amplitude ")
            self.canvas_plot1.set_ylabel(1, "Frequency (Hz)")
            info = "{}.{}.{}".format(self.tr1.stats.network,
                                     self.tr1.stats.station,
                                     self.tr1.stats.channel)
            self.canvas_plot1.set_plot_label(0, info)

            if self.time_frequencyChB.isChecked():
                self.time_frequency(self.tr1, selection)

        if selection == "Seismogram 2":
            #self.validate_file()
            [self.tr2, t] = self.get_data()
            self.canvas_plot2.plot(t,
                                   self.tr2.data,
                                   0,
                                   clear_plot=True,
                                   color="black",
                                   linewidth=0.5)
            self.canvas_plot2.set_xlabel(1, "Time (s)")
            self.canvas_plot2.set_ylabel(0, "Amplitude ")
            self.canvas_plot2.set_ylabel(1, "Frequency (Hz)")
            info = "{}.{}.{}".format(self.tr2.stats.network,
                                     self.tr2.stats.station,
                                     self.tr2.stats.channel)
            self.canvas_plot2.set_plot_label(0, info)

            if self.time_frequencyChB.isChecked():
                self.time_frequency(self.tr2, selection)

    @AsycTime.run_async()
    def time_frequency(self, tr, order):
        selection = self.time_frequencyCB.currentText()
        ts, te = self.get_time_window()
        diff = te - ts
        if selection == "Multitaper Spectrogram":

            win = int(self.mt_window_lengthDB.value() * tr.stats.sampling_rate)
            tbp = self.time_bandwidth_DB.value()
            ntapers = self.number_tapers_mtSB.value()
            f_min = self.freq_min_mtDB.value()
            f_max = self.freq_max_mtDB.value()
            mtspectrogram = MTspectrogram(self.file_selector.file_path, win,
                                          tbp, ntapers, f_min, f_max)

            if self.trimCB.isChecked() and diff >= 0:
                x, y, log_spectrogram = mtspectrogram.compute_spectrogram(
                    tr, start_time=ts, end_time=te)
            else:
                x, y, log_spectrogram = mtspectrogram.compute_spectrogram(tr)

            log_spectrogram = np.clip(log_spectrogram,
                                      a_min=self.minlevelCB.value(),
                                      a_max=0)
            min_log_spectrogram = self.minlevelCB.value()
            max_log_spectrogram = 0

            if order == "Seismogram 1":
                if self.typeCB.currentText() == 'contourf':

                    self.canvas_plot1.plot_contour(x,
                                                   y,
                                                   log_spectrogram,
                                                   axes_index=1,
                                                   clabel="Power [dB]",
                                                   cmap=plt.get_cmap("jet"),
                                                   vmin=min_log_spectrogram,
                                                   vmax=max_log_spectrogram)
                elif self.typeCB.currentText() == 'pcolormesh':

                    print("plotting pcolormesh")
                    self.canvas_plot1.pcolormesh(x,
                                                 y,
                                                 log_spectrogram,
                                                 axes_index=1,
                                                 clabel="Power [dB]",
                                                 cmap=plt.get_cmap("jet"),
                                                 vmin=min_log_spectrogram,
                                                 vmax=max_log_spectrogram)
                self.canvas_plot1.set_xlabel(1, "Time (s)")
                self.canvas_plot1.set_ylabel(0, "Amplitude ")
                self.canvas_plot1.set_ylabel(1, "Frequency (Hz)")

            elif order == "Seismogram 2":
                if self.typeCB.currentText() == 'contourf':

                    self.canvas_plot2.plot_contour(x,
                                                   y,
                                                   log_spectrogram,
                                                   axes_index=1,
                                                   clear_plot=True,
                                                   clabel="Power [dB]",
                                                   cmap=plt.get_cmap("jet"),
                                                   vmin=min_log_spectrogram,
                                                   vmax=max_log_spectrogram)
                elif self.typeCB.currentText() == 'pcolormesh':

                    self.canvas_plot2.pcolormesh(x,
                                                 y,
                                                 log_spectrogram,
                                                 axes_index=1,
                                                 clear_plot=True,
                                                 clabel="Power [dB]",
                                                 cmap=plt.get_cmap("jet"),
                                                 vmin=min_log_spectrogram,
                                                 vmax=max_log_spectrogram)

                self.canvas_plot2.set_xlabel(1, "Time (s)")
                self.canvas_plot2.set_ylabel(0, "Amplitude ")
                self.canvas_plot2.set_ylabel(1, "Frequency (Hz)")

        elif selection == "Wigner Spectrogram":

            win = int(self.mt_window_lengthDB.value() * tr.stats.sampling_rate)
            tbp = self.time_bandwidth_DB.value()
            ntapers = self.number_tapers_mtSB.value()
            f_min = self.freq_min_mtDB.value()
            f_max = self.freq_max_mtDB.value()
            wignerspec = WignerVille(self.file_selector.file_path, win, tbp,
                                     ntapers, f_min, f_max)

            if self.trimCB.isChecked() and diff >= 0:
                x, y, log_spectrogram = wignerspec.compute_wigner_spectrogram(
                    tr, start_time=ts, end_time=te)
            else:
                x, y, log_spectrogram = wignerspec.compute_wigner_spectrogram(
                    tr)

            if order == "Seismogram 1":
                if self.typeCB.currentText() == 'contourf':
                    self.canvas_plot1.plot_contour(x,
                                                   y,
                                                   log_spectrogram,
                                                   axes_index=1,
                                                   clear_plot=True,
                                                   clabel="Rel Power ",
                                                   cmap=plt.get_cmap("jet"))
                elif self.typeCB.currentText() == 'pcolormesh':
                    self.canvas_plot1.pcolormesh(x,
                                                 y,
                                                 log_spectrogram,
                                                 axes_index=1,
                                                 clear_plot=True,
                                                 clabel="Rel Power ",
                                                 cmap=plt.get_cmap("jet"))
                self.canvas_plot1.set_xlabel(1, "Time (s)")
                self.canvas_plot1.set_ylabel(0, "Amplitude ")
                self.canvas_plot1.set_ylabel(1, "Frequency (Hz)")

            elif order == "Seismogram 2":
                if self.typeCB.currentText() == 'contourf':
                    self.canvas_plot2.plot_contour(x,
                                                   y,
                                                   log_spectrogram,
                                                   axes_index=1,
                                                   clear_plot=True,
                                                   clabel="Power [dB]",
                                                   cmap=plt.get_cmap("jet"))
                elif self.typeCB.currentText() == 'pcolormesh':
                    self.canvas_plot2.pcolormesh(x,
                                                 y,
                                                 log_spectrogram,
                                                 axes_index=1,
                                                 clear_plot=True,
                                                 clabel="Power [dB]",
                                                 cmap=plt.get_cmap("jet"))
                self.canvas_plot2.set_xlabel(1, "Time (s)")
                self.canvas_plot2.set_ylabel(0, "Amplitude ")
                self.canvas_plot2.set_ylabel(1, "Frequency (Hz)")

        elif selection == "Continuous Wavelet Transform":

            fs = tr.stats.sampling_rate
            nf = self.atomsSB.value()
            f_min = self.freq_min_cwtDB.value()
            f_max = self.freq_max_cwtDB.value()
            wmin = self.wminSB.value()
            wmax = self.wminSB.value()
            #tt = int( self.wavelet_lenghtDB.value()*fs)
            npts = len(tr.data)
            t = np.linspace(0, tr.stats.delta * npts, npts)
            #cw = ConvolveWaveletScipy(self.file_selector.file_path)
            cw = ConvolveWaveletScipy(tr)
            wavelet = self.wavelet_typeCB.currentText()

            m = self.wavelets_param.value()
            if self.trimCB.isChecked() and diff >= 0:

                cw.setup_wavelet(ts,
                                 te,
                                 wmin=wmin,
                                 wmax=wmax,
                                 tt=int(fs / f_min),
                                 fmin=f_min,
                                 fmax=f_max,
                                 nf=nf,
                                 use_wavelet=wavelet,
                                 m=m,
                                 decimate=False)
            else:
                cw.setup_wavelet(wmin=wmin,
                                 wmax=wmax,
                                 tt=int(fs / f_min),
                                 fmin=f_min,
                                 fmax=f_max,
                                 nf=nf,
                                 use_wavelet=wavelet,
                                 m=m,
                                 decimate=False)

            scalogram2 = cw.scalogram_in_dbs()
            scalogram2 = np.clip(scalogram2,
                                 a_min=self.minlevelCB.value(),
                                 a_max=0)
            cf = cw.cf_lowpass()
            freq = np.logspace(np.log10(f_min), np.log10(f_max))
            k = wmin / (2 * np.pi * freq)
            delay = int(fs * np.mean(k))
            x, y = np.meshgrid(
                t,
                np.logspace(np.log10(f_min), np.log10(f_max),
                            scalogram2.shape[0]))
            c_f = wmin / 2 * math.pi
            f = np.linspace((f_min), (f_max), scalogram2.shape[0])
            pred = (math.sqrt(2) * c_f / f) - (math.sqrt(2) * c_f / f_max)

            pred_comp = t[len(t) - 1] - pred
            min_cwt = self.minlevelCB.value()
            max_cwt = 0

            norm = Normalize(vmin=min_cwt, vmax=max_cwt)

            tf = t[delay:len(t)]
            cf = cf[0:len(tf)]
            if order == "Seismogram 1":

                #self.canvas_plot1.plot(tf, cf, 0, clear_plot=True, is_twinx=True, color="red",
                #                       linewidth=0.5)
                if self.typeCB.currentText() == 'pcolormesh':
                    self.canvas_plot1.pcolormesh(x,
                                                 y,
                                                 scalogram2,
                                                 axes_index=1,
                                                 clear_plot=True,
                                                 clabel="Power [dB]",
                                                 cmap=plt.get_cmap("jet"),
                                                 vmin=min_cwt,
                                                 vmax=max_cwt)
                elif self.typeCB.currentText() == 'contourf':
                    self.canvas_plot1.plot_contour(x,
                                                   y,
                                                   scalogram2,
                                                   axes_index=1,
                                                   clear_plot=True,
                                                   clabel="Power [dB]",
                                                   cmap=plt.get_cmap("jet"),
                                                   vmin=min_cwt,
                                                   vmax=max_cwt)

                ax_cone = self.canvas_plot1.get_axe(1)
                ax_cone.fill_between(pred,
                                     f,
                                     0,
                                     color="black",
                                     edgecolor="red",
                                     alpha=0.3)
                ax_cone.fill_between(pred_comp,
                                     f,
                                     0,
                                     color="black",
                                     edgecolor="red",
                                     alpha=0.3)
                self.canvas_plot1.set_xlabel(1, "Time (s)")
                self.canvas_plot1.set_ylabel(0, "Amplitude ")
                self.canvas_plot1.set_ylabel(1, "Frequency (Hz)")

            if order == "Seismogram 2":

                #self.canvas_plot2.plot(tf, cf, 0, clear_plot=True, is_twinx=True, color="red",
                #                       linewidth=0.5)

                if self.typeCB.currentText() == 'pcolormesh':
                    self.canvas_plot2.pcolormesh(x,
                                                 y,
                                                 scalogram2,
                                                 axes_index=1,
                                                 clear_plot=True,
                                                 clabel="Power [dB]",
                                                 cmap=plt.get_cmap("jet"),
                                                 vmin=min_cwt,
                                                 vmax=max_cwt)
                elif self.typeCB.currentText() == 'contourf':
                    self.canvas_plot2.plot_contour(x,
                                                   y,
                                                   scalogram2,
                                                   axes_index=1,
                                                   clear_plot=True,
                                                   clabel="Power [dB]",
                                                   cmap=plt.get_cmap("jet"),
                                                   vmin=min_cwt,
                                                   vmax=max_cwt)

                ax_cone2 = self.canvas_plot2.get_axe(1)
                ax_cone2.fill_between(pred,
                                      f,
                                      0,
                                      color="black",
                                      edgecolor="red",
                                      alpha=0.3)
                ax_cone2.fill_between(pred_comp,
                                      f,
                                      0,
                                      color="black",
                                      edgecolor="red",
                                      alpha=0.3)
                self.canvas_plot2.set_xlabel(1, "Time (s)")
                self.canvas_plot2.set_ylabel(0, "Amplitude ")
                self.canvas_plot2.set_ylabel(1, "Frequency (Hz)")

        else:
            pass

    def key_pressed(self, event):
        selection = self.selectCB.currentText()

        if event.key == 'w':
            self.plot_seismogram()

        if event.key == 'q':
            if selection == "Seismogram 1":
                [tr, t] = self.get_data()
                x1, y1 = event.xdata, event.ydata
                tt = tr.stats.starttime + x1
                set_qdatetime(tt, self.starttime_date)
                self.canvas_plot1.draw_arrow(x1,
                                             0,
                                             arrow_label="st",
                                             color="purple",
                                             linestyles='--',
                                             picker=False)
            elif selection == "Seismogram 2":
                [tr, t] = self.get_data()
                x1, y1 = event.xdata, event.ydata
                tt = tr.stats.starttime + x1
                set_qdatetime(tt, self.starttime_date)
                self.canvas_plot2.draw_arrow(x1,
                                             0,
                                             arrow_label="st",
                                             color="purple",
                                             linestyles='--',
                                             picker=False)

        if event.key == 'e':

            if selection == "Seismogram 1":
                [tr, t] = self.get_data()
                x1, y1 = event.xdata, event.ydata
                tt = tr.stats.starttime + x1
                set_qdatetime(tt, self.endtime_date)
                self.canvas_plot1.draw_arrow(x1,
                                             0,
                                             arrow_label="et",
                                             color="purple",
                                             linestyles='--',
                                             picker=False)
            elif selection == "Seismogram 2":
                [tr, t] = self.get_data()
                x1, y1 = event.xdata, event.ydata
                tt = tr.stats.starttime + x1
                set_qdatetime(tt, self.endtime_date)
                self.canvas_plot2.draw_arrow(x1,
                                             0,
                                             arrow_label="et",
                                             color="purple",
                                             linestyles='--',
                                             picker=False)

    def open_help(self):
        self.help.show()
Example #4
0
class FrequencyTimeFrame(pw.QWidget, UiFrequencyTime):
    def __init__(self):
        super(FrequencyTimeFrame, self).__init__()
        self.setupUi(self)
        self.solutions = []
        self.periods_now = []
        self.colors = ["white", "green", "black"]
        self._stations_info = {}
        self.parameters = ParametersSettings()
        # Binds
        self.root_path_bind = BindPyqtObject(self.rootPathForm_2, self.onChange_root_path)
        self.canvas_plot1 = MatplotlibCanvas(self.widget_plot_up, ncols=2, sharey  = True)
        top = 0.900
        bottom = 0.180
        left = 0.045
        right = 0.720
        wspace = 0.135
        self.canvas_plot1.figure.subplots_adjust(left=left, bottom=bottom, right=right, top=top, wspace=wspace, hspace=0.0)

        ax = self.canvas_plot1.get_axe(0)
        left,width = 0.2, 0.55
        bottom, height = 0.180, 0.72
        spacing = 0.02
        coords_ax = [left+width+spacing, bottom, 0.2, height]
        self.fig = ax.get_figure()
        #self.ax_seism1 = self.fig.add_axes(coords_ax, sharey = ax)
        self.ax_seism1 = self.fig.add_axes(coords_ax)
        self.ax_seism1.yaxis.tick_right()


        # Add file selector to the widget
        self.file_selector = FilesView(self.root_path_bind.value, parent=self.fileSelectorWidget_2,
                                       on_change_file_callback=lambda file_path: self.onChange_file(file_path))

        # Binds
        self.selectDirBtn_2.clicked.connect(lambda: self.on_click_select_directory(self.root_path_bind))

        # action
        self.plotBtn.clicked.connect(self.plot_seismogram)
        self.plot2Btn.clicked.connect(self.run_phase_vel)
        self.stationsBtn.clicked.connect(self.stations_info)
        self.macroBtn.clicked.connect(lambda: self.open_parameters_settings())
        # clicks
        self.canvas_plot1.on_double_click(self.on_click_matplotlib)
        self.canvas_plot1.mpl_connect('key_press_event', self.key_pressed)

    def open_parameters_settings(self):
        self.parameters.show()

    def filter_error_message(self, msg):
        md = MessageDialog(self)
        md.set_info_message(msg)

    def onChange_root_path(self, value):
        """
        Fired every time the root_path is changed

        :param value: The path of the new directory.

        :return:
        """
        self.file_selector.set_new_rootPath(value)


    def onChange_file(self, file_path):
        # Called every time user select a different file
        pass

    def on_click_select_directory(self, bind: BindPyqtObject):
        if "darwin" == platform:
            dir_path = pw.QFileDialog.getExistingDirectory(self, 'Select Directory', bind.value)
        else:
            dir_path = pw.QFileDialog.getExistingDirectory(self, 'Select Directory', bind.value,
                                                           pw.QFileDialog.DontUseNativeDialog)
        if dir_path:
            bind.value = dir_path

    def on_click_select_file(self, bind: BindPyqtObject):
        selected = pw.QFileDialog.getOpenFileName(self, "Select metadata file")
        if isinstance(selected[0], str) and os.path.isfile(selected[0]):
            bind.value = selected[0]

    def find_indices(self, lst, condition):

        return [i for i, elem in enumerate(lst) if condition(elem)]

    def find_nearest(self, a, a0):
        "Element in nd array `a` closest to the scalar value `a0`"
        idx = np.abs(a - a0).argmin()
        return a.flat[idx], idx

    def stations_info(self):
        sd = []
        st = read(self.file_selector.file_path)
        tr = st[0]
        sd.append([tr.stats.network, tr.stats.station, tr.stats.location, tr.stats.channel, tr.stats.starttime,
                       tr.stats.endtime, tr.stats.sampling_rate, tr.stats.npts])

        self._stations_info = StationsInfo(sd, check= False)
        self._stations_info.show()



    @property
    def trace(self):
        return ObspyUtil.get_tracer_from_file(self.file_selector.file_path)

    def get_data(self):
        parameters = self.parameters.getParameters()
        file = self.file_selector.file_path
        try:

            sd = SeismogramDataAdvanced(file_path = file)
            tr = sd.get_waveform_advanced(parameters, {}, filter_error_callback=self.filter_error_message)
            #tr = st[0]
            t = tr.times()

            return tr, t
        except:
            return []

    def convert_2_vel(self, tr):

        geodetic = tr.stats.mseed['geodetic']
        dist = geodetic[0]

        return dist


    #@AsycTime.run_async()
    def plot_seismogram(self):

        [tr1, t] = self.get_data()
        tr = tr1.copy()
        fs = tr1.stats.sampling_rate
        selection = self.time_frequencyCB.currentText()
        # take into acount causality

        if self.causalCB.currentText() == "Causal":
            starttime = tr.stats.starttime
            endtime = tr.stats.starttime+int(len(tr.data) / (2*fs))
            tr.trim(starttime=starttime,endtime=endtime)
            data = np.flip(tr.data)
            tr.data = data

        else:
            starttime = tr.stats.starttime +int(len(tr.data) / (2*fs))
            endtime =  tr.stats.endtime
            tr.trim(starttime=starttime, endtime=endtime)


        if selection == "Continuous Wavelet Transform":

            nf = self.atomsSB.value()
            f_min = 1 / self.period_max_cwtDB.value()
            f_max = 1/  self.period_min_cwtDB.value()
            wmin = self.wminSB.value()
            wmax = self.wminSB.value()
            npts = len(tr.data)
            t = np.linspace(0, tr.stats.delta * npts, npts)
            cw = ConvolveWaveletScipy(tr)
            wavelet=self.wavelet_typeCB.currentText()

            m = self.wavelets_param.value()

            cw.setup_wavelet(wmin=wmin, wmax=wmax, tt=int(fs/f_min), fmin=f_min, fmax=f_max, nf=nf,
                                 use_wavelet = wavelet, m = m, decimate=False)

            scalogram2 = cw.scalogram_in_dbs()
            phase, inst_freq, ins_freq_hz = cw.phase() # phase in radians
            inst_freq = ins_freq_hz
            #delay = cw.get_time_delay()
            x, y = np.meshgrid(t, np.logspace(np.log10(f_min), np.log10(f_max), scalogram2.shape[0]))
            #x = x + delay
            # chop cero division
            dist = self.convert_2_vel(tr)
            vel = (dist / (x[:, 1:] * 1000))
            min_time_idx = fs * (dist / (self.max_velDB.value() * 1000))
            min_time_idx = int(min_time_idx)
            max_time_idx = fs * (dist / (self.min_velDB.value() * 1000))
            max_time_idx = int(max_time_idx)
            period = 1 / y[:, 1:]
            scalogram2 = scalogram2[:, 1:]

            if self.ftCB.isChecked():
                min_vel, idx_min_vel = self.find_nearest(vel[0, :], self.min_velDB.value())
                max_vel, idx_max_vel = self.find_nearest(vel[0, :], self.max_velDB.value())
                self.min_vel = min_vel
                self.max_vel = max_vel
                vel = vel[:, idx_max_vel:idx_min_vel]
                period = period[:, idx_max_vel:idx_min_vel]
                scalogram2 = scalogram2[:, idx_max_vel:idx_min_vel]
                phase = phase[:, idx_max_vel:idx_min_vel]
                inst_freq = inst_freq[:, idx_max_vel:idx_min_vel]


            scalogram2 = np.clip(scalogram2, a_min=self.minlevelCB.value(), a_max=0)
            min_cwt= self.minlevelCB.value()
            max_cwt = 0

            #scalogram2 = scalogram2+0.01

            # flips
            scalogram2 = scalogram2.T
            scalogram2 = np.fliplr(scalogram2)
            scalogram2 = np.flipud(scalogram2)
            self.scalogram2 = scalogram2

            phase = phase.T
            phase = np.fliplr(phase)
            phase = np.flipud(phase)
            self.phase = phase

            inst_freq = inst_freq.T
            inst_freq = np.fliplr(inst_freq)
            inst_freq = np.flipud(inst_freq)
            self.inst_freq = inst_freq

            vel = vel.T
            vel = np.flipud(vel)
            self.vel = vel

            period = period.T
            period = np.fliplr(period)

            # extract ridge

            ridge = np.max(scalogram2, axis = 0)

            distance = self.dist_ridgDB.value()*vel.shape[0]/(max_vel-min_vel)
            height = (self.minlevelCB.value(),0)
            ridges, peaks, group_vel = self.find_ridges(scalogram2, vel, height, distance, self.numridgeSB.value())

            #print(ridges)
            #ridge_vel = []
            # for j in range(len(ridge)):
             #   value, idx = self.find_nearest(scalogram2[:,j],ridge[j])
             #    ridge_vel.append(vel[idx,j])

            self.t = dist/(1000*vel)
            self.dist = dist/1000
            # phase_vel = self.phase_vel(scalogram2, ridge, phase, inst_freq, t, dist/1000, n)
            # phase_vel = np.flipud(phase_vel)

            # Plot
            self.ax_seism1.cla()
            self.ax_seism1.plot(tr.data, tr.times() / tr.stats.sampling_rate, linewidth=0.5)
            self.ax_seism1.plot(tr.data[min_time_idx:max_time_idx],
                                tr.times()[min_time_idx:max_time_idx] / tr.stats.sampling_rate,
                                color='red', linewidth=0.5)

            self.ax_seism1.set_xlabel("Amplitude")
            self.ax_seism1.set_ylabel("Time (s)")
            self.canvas_plot1.clear()
            self.canvas_plot1.plot_contour(period, vel, scalogram2, axes_index=1, levels = 100, clabel="Power [dB]",
                        cmap=plt.get_cmap("jet"), vmin=min_cwt, vmax=max_cwt, antialiased=True, xscale = "log")

            self.canvas_plot1.set_xlabel(1, "Period (s)")
            self.canvas_plot1.set_ylabel(1, "Group Velocity (km/s)")

            # Plot ridges

            for k in range(self.numridgeSB.value()):
                self.canvas_plot1.plot(period[0,:], group_vel[k], axes_index=1, marker=".", color = self.colors[k],
                                       clear_plot=False)

            self.group_vel = group_vel
            self.periods = period[0,:]

        if selection == "Hilbert-Multiband":

            f_min = 1 / self.period_max_mtDB.value()
            f_max = 1/  self.period_min_mtDB.value()

            npts = len(tr.data)
            t = np.linspace(0, tr.stats.delta * npts, npts)
            hg = hilbert_gauss(tr, f_min, f_max, self.freq_resDB.value())
            scalogram2, phase, inst_freq, inst_freq_hz, f = hg.compute_filter_bank()
            inst_freq = inst_freq_hz
            scalogram2 = hg.envelope_db()

            x, y = np.meshgrid(t, f[0:-1])

            # chop cero division
            dist = self.convert_2_vel(tr)
            vel = (dist / (x[:, 1:] * 1000))
            min_time_idx = fs * (dist / (self.max_velDB.value() * 1000))
            min_time_idx = int(min_time_idx)
            max_time_idx = fs * (dist / (self.min_velDB.value() * 1000))
            max_time_idx = int(max_time_idx)
            period = 1 / y[:, 1:]
            scalogram2 = scalogram2[:, 1:]

            if self.ftCB.isChecked():
                min_vel, idx_min_vel = self.find_nearest(vel[0, :], self.min_velDB.value())
                max_vel, idx_max_vel = self.find_nearest(vel[0, :], self.max_velDB.value())
                self.min_vel = min_vel
                self.max_vel = max_vel
                vel = vel[:, idx_max_vel:idx_min_vel]
                period = period[:, idx_max_vel:idx_min_vel]
                scalogram2 = scalogram2[:, idx_max_vel:idx_min_vel]
                phase = phase[:, idx_max_vel:idx_min_vel]
                inst_freq = inst_freq[:, idx_max_vel:idx_min_vel]

            scalogram2 = np.clip(scalogram2, a_min=self.minlevelCB.value(), a_max=0)
            min_cwt = self.minlevelCB.value()
            max_cwt = 0

            # flips
            scalogram2 = scalogram2.T
            scalogram2 = np.fliplr(scalogram2)
            scalogram2 = np.flipud(scalogram2)
            self.scalogram2 = scalogram2

            phase = phase.T
            phase = np.fliplr(phase)
            phase = np.flipud(phase)
            self.phase = phase

            inst_freq = inst_freq.T
            inst_freq = np.fliplr(inst_freq)
            inst_freq = np.flipud(inst_freq)
            self.inst_freq = inst_freq

            vel = vel.T
            vel = np.flipud(vel)
            self.vel = vel

            period = period.T
            period = np.fliplr(period)

            # extract ridge

            ridge = np.max(scalogram2, axis=0)

            distance = self.dist_ridgDB.value() * vel.shape[0] / (max_vel - min_vel)
            height = (self.minlevelCB.value(), 0)
            ridges, peaks, group_vel = self.find_ridges(scalogram2, vel, height, distance, self.numridgeSB.value())

            # print(ridges)
            # ridge_vel = []
            # for j in range(len(ridge)):
            #   value, idx = self.find_nearest(scalogram2[:,j],ridge[j])
            #    ridge_vel.append(vel[idx,j])

            self.t = dist / (1000 * vel)
            self.dist = dist / 1000
            # phase_vel = self.phase_vel(scalogram2, ridge, phase, inst_freq, t, dist/1000, n)
            # phase_vel = np.flipud(phase_vel)

            # Plot
            self.ax_seism1.cla()
            self.ax_seism1.plot(tr.data, tr.times() / tr.stats.sampling_rate, linewidth=0.5)
            self.ax_seism1.plot(tr.data[min_time_idx:max_time_idx],
                                tr.times()[min_time_idx:max_time_idx] / tr.stats.sampling_rate,
                                color='red', linewidth=0.5)

            self.ax_seism1.set_xlabel("Amplitude")
            self.ax_seism1.set_ylabel("Time (s)")
            self.canvas_plot1.clear()
            self.canvas_plot1.plot_contour(period, vel, scalogram2, axes_index=1, levels=100, clabel="Power [dB]",
                                           cmap=plt.get_cmap("jet"), vmin=min_cwt, vmax=max_cwt, antialiased=True,
                                           xscale="log")

            self.canvas_plot1.set_xlabel(1, "Period (s)")
            self.canvas_plot1.set_ylabel(1, "Group Velocity (km/s)")

            # Plot ridges

            for k in range(self.numridgeSB.value()):
                self.canvas_plot1.plot(period[0, :], group_vel[k], axes_index=1, marker=".", color=self.colors[k],
                                       clear_plot=False)

            self.group_vel = group_vel
            self.periods = period[0, :]




    def run_phase_vel(self):

        phase_vel_array = self.phase_vel2()
        phase_vel__array = np.flipud(phase_vel_array)
        test = np.arange(-5, 5, 1)
    # Plot phase vel

        ax2 = self.canvas_plot1.get_axe(0)
        ax2.cla()
        for k in range(len(test)):
            ax2.semilogx(self.periods_now, phase_vel_array[k,:], linewidth = 0.0, marker=".")
            #self.canvas_plot1.plot_contour(self.periods_now, phase_vel_array[k,:],np.ones([1, len(self.periods_now)]),
            #                                0, "scatter", show_colorbar=False, marker = '.', xscale="log")

            #self.canvas_plot1.plot(self.periods_now, phase_vel_array[k,:], axes_index=0, marker=".", clear_plot=False,
            #                       xscale="log")

        if self.ftCB.isChecked():
          ax2.set_xlim(self.period_min_cwtDB.value(), self.period_max_cwtDB.value())
          ax2.set_ylim(self.min_vel, self.max_vel)
    #
        self.canvas_plot1.set_xlabel(0, "Period (s)")
        self.canvas_plot1.set_ylabel(0, "Phase Velocity (km/s)")

    def phase_vel2(self):
        landa = -1*np.pi/4
        phase_vel_array = np.zeros([len(np.arange(-5, 5, 1)), len(self.solutions)])
        for k in np.arange(-5, 5, 1):
            for j in range(len(self.solutions)):
                value_period, idx_period = self.find_nearest(self.periods, self.periods_now[j])
                value_group_vel, idx_group_vel = self.find_nearest(self.vel[:,0], self.solutions[j])
                to = self.t[idx_group_vel , 0]
                phase_test = self.phase[idx_group_vel, idx_period]
                inst_freq_test = self.inst_freq[idx_group_vel, idx_period]
                phase_vel_num = self.dist * inst_freq_test
                phase_vel_den = phase_test+inst_freq_test*to-(np.pi/4)-k*2*np.pi+landa
                phase_vel_array[k, j] = phase_vel_num / phase_vel_den

        return phase_vel_array

    def phase_vel(self, scalogram2, ridge, phase, inst_freq, t, dist, n):

        # extract phase_vel info

        phase_vel_array = np.zeros([n, len(ridge)])
        for k in np.arange(-5, 5, 1):
            for j in range(len(ridge)):
                value, idx = self.find_nearest(scalogram2[:, j], ridge[j])
                to = t[idx, j]
                phase_test = phase[idx, j]
                inst_freq_test = inst_freq[idx, j]
                phase_vel_num = dist * inst_freq_test
                phase_vel_den = phase_test+inst_freq_test*to-(np.pi/4)-k*2*np.pi
                phase_vel_array[k, j] = phase_vel_num / phase_vel_den

        return phase_vel_array

    def find_ridges(self, scalogram2, vel, height, distance, num_ridges):

        distance = int(distance)
        dim = scalogram2.shape[1]
        ridges = np.zeros([num_ridges, dim])
        peak = np.zeros([num_ridges, dim])
        group_vel = np.zeros([num_ridges, dim])

        for j in range(dim):

            peaks, properties = find_peaks(scalogram2[:,j], height = height, threshold=-5, distance = distance)

            for k in range(num_ridges):

                try:
                    if len(peaks)>0:
                        ridges[k, j] = peaks[k]

                        peak[k, j] =  properties['peak_heights'][k]
                        group_vel[k,j] =vel[int(peaks[k]),0]
                    else:
                        ridges[k, j] = "NaN"
                        peak[k, j] = "NaN"
                        group_vel[k, j] = "NaN"

                except:

                    ridges[k, j] = "NaN"
                    peak[k, j] = "NaN"
                    group_vel[k, j] = "NaN"


        return ridges, peak, group_vel


    def on_click_matplotlib(self, event, canvas):
        if isinstance(canvas, MatplotlibCanvas):

            x1_value, y1_value = event.xdata, event.ydata

            period, pick_vel,_ = self.find_pos(x1_value, y1_value)
            self.solutions.append(pick_vel)
            self.periods_now.append(period)
            self.canvas_plot1.plot(period, pick_vel, color = "purple", axes_index = 1, clear_plot = False, marker = "." )

    def find_pos(self, x1, y1):

        value_period, idx_periods = self.find_nearest(self.periods, x1)
        dim = self.group_vel.shape[0]
        rms = []

        for k in range(dim):
            group_vel_test = self.group_vel[k, :][idx_periods]
            err = abs(group_vel_test - y1)
            if err>0:
                rms.append(err)
            else:
                err=100
                rms.append(err)

        rms = np.array(rms)
        idx = np.argmin(rms)

        return value_period, self.group_vel[idx, idx_periods], idx

    def key_pressed(self, event):

        if event.key == 'r':
            x1_value, y1_value = event.xdata, event.ydata
            print(x1_value, y1_value)
            period, pick_vel,idx = self.find_pos(x1_value, y1_value)
            # check if is in solutions
            if period in self.periods_now and pick_vel in self.solutions:
                self.periods_now.remove(period)
                self.solutions.remove(pick_vel)
                self.canvas_plot1.plot(period, pick_vel, color=self.colors[idx], axes_index=1, clear_plot=False, marker=".")


    # if selection == "Multitaper Spectrogram":
    #
    #     win = int(self.mt_window_lengthDB.value() * tr.stats.sampling_rate)
    #     win_half = int(win / (2 * fs))
    #     tbp = self.time_bandwidth_DB.value()
    #     ntapers = self.number_tapers_mtSB.value()
    #     f_min = 1 / self.period_max_mtDB.value()
    #     f_max = 1 / self.period_min_mtDB.value()
    #     mtspectrogram = MTspectrogram(self.file_selector.file_path, win, tbp, ntapers, f_min, f_max)
    #     x, y, log_spectrogram = mtspectrogram.compute_spectrogram(tr)
    #     # x in seconds, y in freqs
    #     x = x + win_half
    #     # chop cero division
    #     dist = self.convert_2_vel(tr)
    #     vel = (dist / (x[:, 1:] * 1000))
    #     min_time_idx = fs * (dist / (self.max_velDB.value() * 1000))
    #     min_time_idx = int(min_time_idx)
    #     max_time_idx = fs * (dist / (self.min_velDB.value() * 1000))
    #     max_time_idx = int(max_time_idx)
    #     period = 1 / y[:, 1:]
    #     log_spectrogram = log_spectrogram[:, 1:]
    #
    #     if self.ftCB.isChecked():
    #         min_vel, idx_min_vel = self.find_nearest(vel[0, :], self.min_velDB.value())
    #         max_vel, idx_max_vel = self.find_nearest(vel[0, :], self.max_velDB.value())
    #         vel = vel[:, idx_max_vel:idx_min_vel]
    #         period = period[:, idx_max_vel:idx_min_vel]
    #         log_spectrogram = log_spectrogram[:, idx_max_vel:idx_min_vel]
    #
    #     log_spectrogram = np.clip(log_spectrogram, a_min=self.minlevelCB.value(), a_max=0.05)
    #     min_log_spectrogram = self.minlevelCB.value()
    #     max_log_spectrogram = 0.05
    #     log_spectrogram = log_spectrogram + 0.05
    #
    #     # flips
    #     log_spectrogram = log_spectrogram.T
    #     log_spectrogram = np.fliplr(log_spectrogram)
    #     log_spectrogram = np.flipud(log_spectrogram)
    #
    #     vel = vel.T
    #     vel = np.flipud(vel)
    #
    #     period = period.T
    #     period = np.fliplr(period)
    #
    #     # Plot
    #     self.ax_seism1.cla()
    #     self.ax_seism1.plot(tr.data, tr.times() / tr.stats.sampling_rate, linewidth=0.5)
    #     self.ax_seism1.plot(tr.data[min_time_idx:max_time_idx],
    #                         tr.times()[min_time_idx:max_time_idx] / tr.stats.sampling_rate,
    #                         color='red', linewidth=0.5)
    #
    #     self.ax_seism1.set_xlabel("Amplitude")
    #     self.ax_seism1.set_ylabel("Time (s)")
    #     self.canvas_plot1.clear()
    #     self.canvas_plot1.plot_contour(period, vel, log_spectrogram, axes_index=0, clabel="Power [dB]",
    #                                    cmap=plt.get_cmap("jet"), vmin=min_log_spectrogram, vmax=max_log_spectrogram,
    #                                    antialiased=True, xscale="log")
    #
    #     # ax = self.canvas_plot1.get_axe(0)
    #     # ax.clabel(cs, levels = levels, fmt = '%2.1', colors = 'k', fontsize = 12)
    #     self.canvas_plot1.set_xlabel(0, "Period (s)")
    #     self.canvas_plot1.set_ylabel(0, "Group Velocity (m/s)")
Example #5
0
class ArrayAnalysisFrame(BaseFrame, UiArrayAnalysisFrame):
    def __init__(self):
        super(ArrayAnalysisFrame, self).__init__()
        self.setupUi(self)
        self.__stations_dir = None
        self.stream_frame = None
        self.__metadata_manager = None
        self.inventory = {}
        self._stations_info = {}
        self._stations_coords = {}
        self.stack = None
        self.canvas = MatplotlibCanvas(self.responseMatWidget)
        self.canvas_fk = MatplotlibCanvas(self.widget_fk, nrows=4)
        self.canvas_slow_map = MatplotlibCanvas(self.widget_slow_map)
        self.canvas_fk.on_double_click(self.on_click_matplotlib)
        self.canvas_stack = MatplotlibCanvas(self.widget_stack)
        self.cartopy_canvas = CartopyCanvas(self.widget_map)
        self.canvas.set_new_subplot(1, ncols=1)

        #Binding
        self.root_pathFK_bind = BindPyqtObject(self.rootPathFormFK)
        self.root_pathBP_bind = BindPyqtObject(self.rootPathFormBP)
        self.metadata_path_bind = BindPyqtObject(self.datalessPathForm,
                                                 self.onChange_metadata_path)
        self.metadata_path_bindBP = BindPyqtObject(self.datalessPathFormBP,
                                                   self.onChange_metadata_path)
        self.output_path_bindBP = BindPyqtObject(self.outputPathFormBP,
                                                 self.onChange_metadata_path)
        self.fmin_bind = BindPyqtObject(self.fminSB)
        self.fmax_bind = BindPyqtObject(self.fmaxSB)
        self.grid_bind = BindPyqtObject(self.gridSB)
        self.smax_bind = BindPyqtObject(self.smaxSB)

        # On select
        self.canvas_fk.register_on_select(self.on_select,
                                          rectprops=dict(alpha=0.2,
                                                         facecolor='red'))
        self.fminFK_bind = BindPyqtObject(self.fminFKSB)
        self.fmaxFK_bind = BindPyqtObject(self.fmaxFKSB)
        self.overlap_bind = BindPyqtObject(self.overlapSB)
        self.timewindow_bind = BindPyqtObject(self.timewindowSB)
        self.smaxFK_bind = BindPyqtObject(self.slowFKSB)
        self.slow_grid_bind = BindPyqtObject(self.gridFKSB)

        # Bind buttons
        self.selectDirBtnFK.clicked.connect(
            lambda: self.on_click_select_directory(self.root_pathFK_bind))
        self.datalessBtn.clicked.connect(
            lambda: self.on_click_select_metadata_file(self.metadata_path_bind
                                                       ))

        # Bind buttons BackProjection
        self.selectDirBtnBP.clicked.connect(
            lambda: self.on_click_select_directory(self.root_pathBP_bind))
        self.datalessBtnBP.clicked.connect(
            lambda: self.on_click_select_metadata_file(self.
                                                       metadata_path_bindBP))
        self.outputBtn.clicked.connect(
            lambda: self.on_click_select_directory(self.output_path_bindBP))

        #Action Buttons
        self.arfBtn.clicked.connect(lambda: self.arf())
        self.runFKBtn.clicked.connect(lambda: self.FK_plot())
        self.plotBtn.clicked.connect(lambda: self.plot_seismograms())
        self.plotBtnBP.clicked.connect(lambda: self.plot_seismograms(FK=False))
        self.actionSettings.triggered.connect(
            lambda: self.open_parameters_settings())
        self.actionProcessed_Seimograms.triggered.connect(self.write)
        self.actionStacked_Seismograms.triggered.connect(self.write_stack)
        self.stationsBtn.clicked.connect(lambda: self.stationsInfo())
        self.stationsBtnBP.clicked.connect(lambda: self.stationsInfo(FK=False))
        self.mapBtn.clicked.connect(self.stations_map)
        self.actionCreate_Stations_File.triggered.connect(
            self.stations_coordinates)
        self.actionLoad_Stations_File.triggered.connect(self.load_path)
        self.actionRunVespagram.triggered.connect(self.open_vespagram)
        self.shortcut_open = pw.QShortcut(pqg.QKeySequence('Ctrl+O'), self)
        self.shortcut_open.activated.connect(self.open_solutions)
        self.create_gridBtn.clicked.connect(self.create_grid)
        self.actionOpen_Help.triggered.connect(lambda: self.open_help())
        self.load_videoBtn.clicked.connect(self.loadvideoBP)

        # help Documentation
        self.help = HelpDoc()

        # Parameters settings
        self.__parameters = ParametersSettings()

        # Stations Coordinates
        self.__stations_coords = StationsCoords()

        # picks
        self.picks = {
            'Time': [],
            'Phase': [],
            'BackAzimuth': [],
            'Slowness': [],
            'Power': []
        }

        # video
        self.player = QMediaPlayer(None, QMediaPlayer.VideoSurface)
        self.player.setVideoOutput(self.backprojection_widget)
        self.player.stateChanged.connect(self.mediaStateChanged)
        self.player.positionChanged.connect(self.positionChanged)
        self.player.durationChanged.connect(self.durationChanged)
        self.playButton.setIcon(self.style().standardIcon(QStyle.SP_MediaPlay))
        self.playButton.clicked.connect(self.play_bp)
        self.positionSlider.sliderMoved.connect(self.setPosition)

    def mediaStateChanged(self):
        if self.player.state() == QMediaPlayer.PlayingState:
            self.playButton.setIcon(self.style().standardIcon(
                QStyle.SP_MediaPause))
        else:
            self.playButton.setIcon(self.style().standardIcon(
                QStyle.SP_MediaPlay))

    def positionChanged(self, position):
        self.positionSlider.setValue(position)

    def durationChanged(self, duration):
        self.positionSlider.setRange(0, duration)

    def setPosition(self, position):
        self.player.setPosition(position)

    def open_parameters_settings(self):
        self.__parameters.show()

    def stations_coordinates(self):
        self.__stations_coords.show()

    def open_vespagram(self):
        if self.st and self.inventory and self.t1 and self.t2:
            self.__vespagram = Vespagram(self.st, self.inventory, self.t1,
                                         self.t2)
            self.__vespagram.show()

    def on_click_select_directory(self, bind: BindPyqtObject):
        if "darwin" == platform:
            dir_path = pw.QFileDialog.getExistingDirectory(
                self, 'Select Directory', bind.value)
        else:
            dir_path = pw.QFileDialog.getExistingDirectory(
                self, 'Select Directory', bind.value,
                pw.QFileDialog.DontUseNativeDialog)
        if dir_path:
            bind.value = dir_path

    def onChange_metadata_path(self, value):

        md = MessageDialog(self)
        try:

            self.__metadata_manager = MetadataManager(value)
            self.inventory = self.__metadata_manager.get_inventory()
            print(self.inventory)
            md.set_info_message(
                "Loaded Metadata, please check your terminal for further details"
            )

        except:

            md.set_error_message(
                "Something went wrong. Please check your metada file is a correct one"
            )

    def on_click_select_metadata_file(self, bind: BindPyqtObject):
        selected = pw.QFileDialog.getOpenFileName(self, "Select metadata file")
        if isinstance(selected[0], str) and os.path.isfile(selected[0]):
            bind.value = selected[0]

    def load_path(self):
        selected_file = pw.QFileDialog.getOpenFileName(
            self, "Select Stations Coordinates file")
        self.path_file = selected_file[0]
        df = pd.read_csv(self.path_file, delim_whitespace=True)
        n = len(df)
        self.coords = np.zeros([n, 3])
        for i in range(n):
            #coords[i]=data[i]
            self.coords[i] = np.array(
                [df['Lon'][i], df['Lat'][i], df['Depth'][i]])

    def arf(self):
        try:
            if self.coords.all():

                wavenumber = array_analysis.array()
                arf = wavenumber.arf(self.coords, self.fmin_bind.value,
                                     self.fmax_bind.value,
                                     self.smax_bind.value,
                                     self.grid_bind.value)

                slim = self.smax_bind.value
                x = y = np.linspace(-1 * slim, slim, len(arf))
                self.canvas.plot_contour(x,
                                         y,
                                         arf,
                                         axes_index=0,
                                         clabel="Power [dB]",
                                         cmap=plt.get_cmap("jet"))
                self.canvas.set_xlabel(0, "Sx (s/km)")
                self.canvas.set_ylabel(0, "Sy (s/km)")
        except:
            md = MessageDialog(self)
            md.set_error_message(
                "Couldn't compute ARF, please check if you have loaded stations coords"
            )

    def stations_map(self):
        coords = {}

        if self.path_file:
            df = pd.read_csv(self.path_file, delim_whitespace=True)
            n = len(df)
            self.coords = np.zeros([n, 3])
            for i in range(n):
                coords[df['Name'][i]] = [
                    df['Lat'][i],
                    df['Lon'][i],
                ]
        #try:
            self.cartopy_canvas.plot_map(df['Lat'][0],
                                         df['Lon'][0],
                                         0,
                                         0,
                                         0,
                                         0,
                                         resolution="low",
                                         stations=coords)
        #except:
        #    pass

    def FK_plot(self):
        self.canvas_stack.set_new_subplot(nrows=1, ncols=1)
        starttime = convert_qdatetime_utcdatetime(self.starttime_date)
        endtime = convert_qdatetime_utcdatetime(self.endtime_date)
        selection = self.inventory.select(station=self.stationLE.text(),
                                          channel=self.channelLE.text())
        if self.trimCB.isChecked():
            wavenumber = array_analysis.array()
            relpower, abspower, AZ, Slowness, T = wavenumber.FK(
                self.st, selection, starttime, endtime, self.fminFK_bind.value,
                self.fmaxFK_bind.value, self.smaxFK_bind.value,
                self.slow_grid_bind.value, self.timewindow_bind.value,
                self.overlap_bind.value)
            self.canvas_fk.scatter3d(T,
                                     relpower,
                                     relpower,
                                     axes_index=0,
                                     clabel="Power [dB]")
            self.canvas_fk.scatter3d(T,
                                     abspower,
                                     relpower,
                                     axes_index=1,
                                     clabel="Power [dB]")
            self.canvas_fk.scatter3d(T,
                                     AZ,
                                     relpower,
                                     axes_index=2,
                                     clabel="Power [dB]")
            self.canvas_fk.scatter3d(T,
                                     Slowness,
                                     relpower,
                                     axes_index=3,
                                     clabel="Power [dB]")
            self.canvas_fk.set_ylabel(0, " Rel Power ")
            self.canvas_fk.set_ylabel(1, " Absolute Power ")
            self.canvas_fk.set_ylabel(2, " Back Azimuth ")
            self.canvas_fk.set_ylabel(3, " Slowness [s/km] ")
            self.canvas_fk.set_xlabel(3, " Time [s] ")
            ax = self.canvas_fk.get_axe(3)
            formatter = mdt.DateFormatter('%H:%M:%S')
            ax.xaxis.set_major_formatter(formatter)
            ax.xaxis.set_tick_params(rotation=30)
        else:
            md = MessageDialog(self)
            md.set_info_message("Please select dates and then check Trim box")

    def on_click_matplotlib(self, event, canvas):
        output_path = os.path.join(ROOT_DIR, 'arrayanalysis', 'dataframe.csv')

        if isinstance(canvas, MatplotlibCanvas):
            st = self.st.copy()
            wavenumber = array_analysis.array()
            selection = self.inventory.select(station=self.stationLE.text(),
                                              channel=self.channelLE.text())
            x1, y1 = event.xdata, event.ydata
            DT = x1
            Z, Sxpow, Sypow, coord = wavenumber.FKCoherence(
                st, selection, DT, self.fminFK_bind.value,
                self.fmaxFK_bind.value, self.smaxFK_bind.value,
                self.timewindow_bind.value, self.slow_grid_bind.value,
                self.methodSB.currentText())

            backacimuth = wavenumber.azimuth2mathangle(
                np.arctan2(Sypow, Sxpow) * 180 / np.pi)
            slowness = np.abs(Sxpow, Sypow)
            if self.methodSB.currentText() == "FK":
                clabel = "Power"
            elif self.methodSB.currentText() == "MTP.COHERENCE":
                clabel = "Magnitude Coherence"

            Sx = np.arange(-1 * self.smaxFK_bind.value, self.smaxFK_bind.value,
                           self.slow_grid_bind.value)[np.newaxis]
            nx = len(Sx[0])
            x = y = np.linspace(-1 * self.smaxFK_bind.value,
                                self.smaxFK_bind.value, nx)
            X, Y = np.meshgrid(x, y)
            self.canvas_slow_map.plot_contour(X,
                                              Y,
                                              Z,
                                              axes_index=0,
                                              clabel=clabel,
                                              cmap=plt.get_cmap("jet"))
            self.canvas_slow_map.set_xlabel(0, "Sx [s/km]")
            self.canvas_slow_map.set_ylabel(0, "Sy [s/km]")

            # Save in a dataframe the pick value
            x1 = wavenumber.gregorian2date(x1)

            self.picks['Time'].append(x1.isoformat())
            self.picks['Phase'].append(self.phaseCB.currentText())
            self.picks['BackAzimuth'].append(backacimuth[0])
            self.picks['Slowness'].append(slowness[0])
            self.picks['Power'].append(np.max(Z))
            df = pd.DataFrame(self.picks)
            df.to_csv(output_path, index=False, header=True)

            # Call Stack and Plot###
            #stream_stack, time = wavenumber.stack_stream(self.root_pathFK_bind.value, Sxpow, Sypow, coord)

            if st:
                st2 = self.st.copy()
                # Align for the maximum power and give the data of the traces
                stream_stack, self.time, self.stats = wavenumber.stack_stream(
                    st2, Sxpow, Sypow, coord)
                # stack the traces
                self.stack = wavenumber.stack(
                    stream_stack, stack_type=self.stackCB.currentText())
                self.canvas_stack.plot(self.time,
                                       self.stack,
                                       axes_index=0,
                                       linewidth=0.75)
                self.canvas_stack.set_xlabel(0, " Time [s] ")
                self.canvas_stack.set_ylabel(0, "Stack Amplitude")

    def filter_error_message(self, msg):
        md = MessageDialog(self)
        md.set_info_message(msg)

    def plot_seismograms(self, FK=True):

        if FK:
            starttime = convert_qdatetime_utcdatetime(self.starttime_date)
            endtime = convert_qdatetime_utcdatetime(self.endtime_date)
        else:
            starttime = convert_qdatetime_utcdatetime(self.starttime_date_BP)
            endtime = convert_qdatetime_utcdatetime(self.endtime_date_BP)

        diff = endtime - starttime

        if FK:
            file_path = self.root_pathFK_bind.value
        else:
            file_path = self.root_pathBP_bind.value

        obsfiles = []

        for dirpath, _, filenames in os.walk(file_path):
            for f in filenames:
                if f != ".DS_Store":
                    obsfiles.append(os.path.abspath(os.path.join(dirpath, f)))

        obsfiles.sort()
        parameters = self.__parameters.getParameters()
        all_traces = []
        trace_number = 0

        for file in obsfiles:
            sd = SeismogramDataAdvanced(file)

            if FK:
                if self.trimCB.isChecked() and diff >= 0:
                    tr = sd.get_waveform_advanced(
                        parameters,
                        self.inventory,
                        filter_error_callback=self.filter_error_message,
                        start_time=starttime,
                        end_time=endtime,
                        trace_number=trace_number)
                else:
                    tr = sd.get_waveform_advanced(
                        parameters,
                        self.inventory,
                        filter_error_callback=self.filter_error_message,
                        trace_number=trace_number)
            else:
                if self.trimCB_BP.isChecked() and diff >= 0:
                    tr = sd.get_waveform_advanced(
                        parameters,
                        self.inventory,
                        filter_error_callback=self.filter_error_message,
                        start_time=starttime,
                        end_time=endtime,
                        trace_number=trace_number)
                else:
                    tr = sd.get_waveform_advanced(
                        parameters,
                        self.inventory,
                        filter_error_callback=self.filter_error_message,
                        trace_number=trace_number)

            all_traces.append(tr)
            trace_number = trace_number + 1

        self.st = Stream(traces=all_traces)

        if FK:
            if self.selectCB.isChecked():
                self.st = self.st.select(station=self.stationLE.text(),
                                         channel=self.channelLE.text())

        else:
            if self.selectCB_BP.isChecked():
                self.st = self.st.select(network=self.stationLE_BP.text(),
                                         station=self.stationLE_BP.text(),
                                         channel=self.channelLE_BP.text())

        self.stream_frame = MatplotlibFrame(self.st, type='normal')
        self.stream_frame.show()

    def stationsInfo(self, FK=True):
        if FK:
            obsfiles = MseedUtil.get_mseed_files(self.root_pathFK_bind.value)
        else:
            obsfiles = MseedUtil.get_mseed_files(self.root_pathBP_bind.value)
        obsfiles.sort()
        sd = []
        for file in obsfiles:
            st = SeismogramDataAdvanced(file)
            station = [
                st.stats.Network, st.stats.Station, st.stats.Location,
                st.stats.Channel, st.stats.StartTime, st.stats.EndTime,
                st.stats.Sampling_rate, st.stats.Npts
            ]
            sd.append(station)
        self._stations_info = StationsInfo(sd, check=True)
        self._stations_info.show()

    def write(self):
        root_path = os.path.dirname(os.path.abspath(__file__))
        if "darwin" == platform:
            dir_path = pw.QFileDialog.getExistingDirectory(
                self, 'Select Directory', root_path)
        else:
            dir_path = pw.QFileDialog.getExistingDirectory(
                self, 'Select Directory', root_path,
                pw.QFileDialog.DontUseNativeDialog)
        if dir_path:
            n = len(self.st)
            try:
                if len(n) > 0:
                    for j in range(n):
                        tr = self.st[j]
                        t1 = tr.stats.starttime
                        id = tr.id + "." + "D" + "." + str(
                            t1.year) + "." + str(t1.julday)
                        print(tr.id, "Writing data processed")
                        path_output = os.path.join(dir_path, id)
                        tr.write(path_output, format="MSEED")
                else:
                    md = MessageDialog(self)
                    md.set_info_message("Nothing to write")
            except:
                pass

    def write_stack(self):
        if self.stack is not None and len(self.stack) > 0:
            root_path = os.path.dirname(os.path.abspath(__file__))
            if "darwin" == platform:
                dir_path = pw.QFileDialog.getExistingDirectory(
                    self, 'Select Directory', root_path)
            else:
                dir_path = pw.QFileDialog.getExistingDirectory(
                    self, 'Select Directory', root_path,
                    pw.QFileDialog.DontUseNativeDialog)
            if dir_path:
                tr = Trace(data=self.stack, header=self.stats)
                file = os.path.join(dir_path, tr.id)
                tr.write(file, format="MSEED")
        else:
            md = MessageDialog(self)
            md.set_info_message("Nothing to write")

    def __to_UTC(self, DT):

        # Convert start from Greogorian to actual date
        Time = DT
        Time = Time - int(Time)
        d = date.fromordinal(int(DT))
        date1 = d.isoformat()
        H = (Time * 24)
        H1 = int(H)  # Horas
        minutes = (H - int(H)) * 60
        minutes1 = int(minutes)
        seconds = (minutes - int(minutes)) * 60
        H1 = str(H1).zfill(2)
        minutes1 = str(minutes1).zfill(2)
        seconds = "%.2f" % seconds
        seconds = str(seconds).zfill(2)
        DATE = date1 + "T" + str(H1) + minutes1 + seconds

        t1 = UTCDateTime(DATE)
        return t1

    def on_select(self, ax_index, xmin, xmax):
        self.t1 = self.__to_UTC(xmin)
        self.t2 = self.__to_UTC(xmax)

    def open_solutions(self):
        output_path = os.path.join(ROOT_DIR, 'arrayanalysis', 'dataframe.csv')
        try:
            command = "{} {}".format('open', output_path)
            exc_cmd(command, cwd=ROOT_DIR)
        except:
            md = MessageDialog(self)
            md.set_error_message("Coundn't open solutions file")

    ### New part back-projection

    def create_grid(self):
        area_coords = [
            self.minLonBP, self.maxLonBP, self.minLatBP, self.maxLatBP
        ]
        bp = back_proj_organize(self, self.rootPathFormBP,
                                self.datalessPathFormBP, area_coords,
                                self.sxSB.value, self.sxSB.value,
                                self.depthSB.value)

        mapping = bp.create_dict()

        try:
            self.path_file = os.path.join(self.output_path_bindBP.value,
                                          "mapping.pkl")
            file_to_store = open(self.path_file, "wb")
            pickle.dump(mapping, file_to_store)
            md = MessageDialog(self)
            md.set_info_message("BackProjection grid created succesfully!!!")

        except:
            md = MessageDialog(self)
            md.set_error_message("Coundn't create a BackProjection grid")

    def run_bp(self):

        try:
            if os.path.exists(self.path_file):
                with open(self.path_file, 'rb') as handle:
                    mapping = pickle.load(handle)
        except:
            md = MessageDialog(self)
            md.set_error_message(
                "Please you need try to previously create a BackProjection grid"
            )

        power = backproj.run_back(self.st,
                                  mapping,
                                  self.time_winBP.value,
                                  self.stepBP.value,
                                  window=self.slide_winBP.value,
                                  multichannel=self.mcccCB.isChecked(),
                                  stack_process=self.methodBP.currentText())

        #plot_cum(power, mapping['area_coords'], self.cum_sumBP.value, self.st)
        plot_bp(power,
                mapping['area_coords'],
                self.cum_sumBP.value,
                self.st,
                output=self.output_path_bindBP.value)

        fname = os.path.join(self.output_path_bindBP.value, "power.pkl")

        file_to_store = open(fname, "wb")
        pickle.dump(power, file_to_store)

    def loadvideoBP(self):
        self.path_video, _ = pw.QFileDialog.getOpenFileName(
            self, "Choose your BackProjection", ".",
            "Video Files (*.mp4 *.flv *.ts *.mts *.avi)")
        if self.path_video != '':

            self.player.setVideoOutput(self.backprojection_widget)
            self.player.setMedia(
                QMediaContent(pyc.QUrl.fromLocalFile(self.path_video)))
            md = MessageDialog(self)
            md.set_info_message(
                "Video containing BackProjection succesfully loaded")
        else:
            md = MessageDialog(self)
            md.set_error_message(
                "Video containing BackProjection couldn't be loaded")

    def play_bp(self):

        if self.player.state() == QMediaPlayer.PlayingState:
            self.player.pause()
        else:
            self.player.play()

    def open_help(self):
        self.help.show()
Example #6
0
class TimeFrequencyAdvance(pw.QFrame, UiTimeFrequencyWidget):
    def __init__(self, tr1, tr2):
        super(TimeFrequencyAdvance, self).__init__()
        self.setupUi(self)
        self.spectrum_Widget_Canvas = MatplotlibCanvas(self.spectrumWidget, nrows=2, ncols=2,
                                                      sharex=False, constrained_layout=True)

        self.spectrum_Widget_Canvas2 = MatplotlibCanvas(self.spectrumWidget2, nrows=1, ncols=1,
                                                      sharex=False, constrained_layout=True)

        self.coherence_Widget_Canvas = MatplotlibCanvas(self.coherenceWidget, nrows=2, ncols=1, sharex=False,
                                                       constrained_layout=True)
        self.cross_correlation_Widget_Canvas = MatplotlibCanvas(self.cross_correlationWidget, nrows = 3, ncols = 1)

        self.cross_spectrumWidget_Widget_Canvas = MatplotlibCanvas(self.cross_spectrumWidget,nrows = 2, ncols = 1,
                                sharex=True, constrained_layout=True)


        self.plot_spectrumBtn.clicked.connect(self.plot_spectrum)
        self.coherenceBtn.clicked.connect(self.coherence)
        self.cross_correlationsBtn.clicked.connect(self.plot_correlation)
        #self.Cross_spectrumBtn.clicked.connect(self.plot_cross_spectrogram)
        self.Cross_scalogramBtn.clicked.connect(self.plot_cross_scalogram)
        self.tr1 = tr1
        self.tr2 = tr2

    def plot_spectrum(self):
        if len(self.tr1) >0:
            [spec1, freq1, jackknife_errors] = spectrumelement(self.tr1.data, self.tr1.stats.delta, self.tr1.id)
            self.spectrum_Widget_Canvas.plot(freq1, spec1, 0)
            ax1 = self.spectrum_Widget_Canvas.get_axe(0)
            ax1.cla()
            ax1.loglog(freq1, spec1, '0.1', linewidth=0.5, color='steelblue', label=self.tr1.id)
            ax1.fill_between(freq1, jackknife_errors[:, 0], jackknife_errors[:, 1], facecolor="0.75",
                             alpha=0.5, edgecolor="0.5")
            ax1.set_ylim(spec1.min() / 10.0, spec1.max() * 100.0)
            ax1.set_xlim(freq1[1], freq1[len(freq1)-1])
            ax1.set_ylabel('Amplitude')
            ax1.set_xlabel('Frequency [Hz]')
            ax1.grid(True, which="both", ls="-", color='grey')
            ax1.legend()

            #plot the phase
            N = len(self.tr1.data)
            D = 2 ** math.ceil(math.log2(N))
            z = np.zeros(D - N)
            data = np.concatenate((self.tr1.data, z), axis=0)
            spectrum = np.fft.rfft(data, D)
            phase = np.angle(spectrum)
            ax3 = self.spectrum_Widget_Canvas.get_axe(2)
            ax3.semilogx(freq1, phase*180/math.pi, color = 'orangered', linewidth=0.5)
            ax3.set_xlim(freq1[1], freq1[len(freq1) - 1])
            ax3.grid(True, which="both", ls="-", color='grey')
            ax3.set_ylabel('Phase')
            ax3.set_xlabel('Frequency [Hz]')

        else:
            pass

        if len(self.tr2) > 0:
            [spec2, freq2, jackknife_errors] = spectrumelement(self.tr2.data, self.tr2.stats.delta, self.tr2.id)
            self.spectrum_Widget_Canvas.plot(freq2, spec2, 1)
            ax2 = self.spectrum_Widget_Canvas.get_axe(1)
            ax2.cla()
            ax2.loglog(freq2, spec2, '0.1', linewidth=0.5, color='steelblue', label=self.tr2.id)
            ax2.fill_between(freq2, jackknife_errors[:, 0], jackknife_errors[:, 1], facecolor="0.75",
                             alpha=0.5, edgecolor="0.5")
            ax2.set_ylim(spec2.min() / 10.0, spec2.max() * 100.0)
            ax2.set_xlim(freq2[1], freq2[len(freq2) - 1])
            ax2.set_ylabel('Amplitude')
            ax2.set_xlabel('Frequency [Hz]')
            ax2.grid(True, which="both", ls="-", color='grey')
            ax2.legend()

            # plot the phase
            N = len(self.tr2.data)
            D = 2 ** math.ceil(math.log2(N))
            z = np.zeros(D - N)
            data = np.concatenate((self.tr2.data, z), axis=0)
            spectrum = np.fft.rfft(data, D)
            phase = np.angle(spectrum)
            ax4 = self.spectrum_Widget_Canvas.get_axe(3)
            ax4.semilogx(freq2, phase * 180 / math.pi, color = 'orangered', linewidth=0.5)
            ax4.set_xlim(freq2[1], freq2[len(freq2) - 1])
            ax4.grid(True, which="both", ls="-", color='grey')
            ax4.set_ylabel('Phase')
            ax4.set_xlabel('Frequency [Hz]')
        else:
            pass

        # Power

        try:
            self.spectrum_Widget_Canvas2.plot(freq1, spec1, 0)
            ax5 = self.spectrum_Widget_Canvas2.get_axe(0)
            ax5.cla()
            spec1=spec1**2
            spec2=spec2**2
            ax5.loglog(freq1, spec1, '0.1', linewidth=0.5, color='steelblue', label=self.tr1.id)
            ax5.loglog(freq2, spec2, '0.1', linewidth=0.5, color='orangered', label=self.tr2.id)
            ax5.set_ylabel('Amplitude')
            ax5.set_xlabel('Frequency [Hz]')
            ax5.grid(True, which="both", ls="-", color='grey')
            ax5.legend()

        except:
            raise("Some data is missing")




    def coherence(self):
        if len(self.tr1) > 0 and len(self.tr2) > 0:
            sampling_rates = []
            fs1=self.tr1.stats.sampling_rate
            fs2=self.tr2.stats.sampling_rate
            sampling_rates.append(fs1)
            sampling_rates.append(fs2)
            max_sampling_rates = np.max(sampling_rates)
            overlap = self.cohe_overlapSB.value()
            time_window = self.time_window_coheSB.value()
            nfft = time_window*max_sampling_rates
            if fs1 != fs2:
                self.tr1.resample(max_sampling_rates)
                self.tr1.resample(max_sampling_rates)

            # Plot Amplitude
            [A,f, phase] = cohe(self.tr1.data, self.tr2.data, max_sampling_rates, nfft, overlap)

            self.coherence_Widget_Canvas.plot(f, A, 0)

            ax1 = self.coherence_Widget_Canvas.get_axe(0)
            ax1.cla()
            ax1.loglog(f, A, '0.1', linewidth=0.5, color='steelblue', label="Amplitude Coherence "+
                                                                            self.tr1.id+" "+ self.tr2.id)

            ax1.set_ylim(A.min() / 10.0, A.max() * 100.0)
            ax1.set_xlim(f[1], f[len(f) - 1])
            ax1.set_ylabel('Magnitude Coherence')
            ax1.set_xlabel('Frequency [Hz]')
            ax1.grid(True, which="both", ls="-", color='grey')
            ax1.legend()

            # Plot Phase
            ax2 = self.coherence_Widget_Canvas.get_axe(1)
            ax2.cla()
            ax2.semilogx(f, phase * 180 / math.pi, color='orangered', linewidth=0.5, label="Phase Coherence "+
                                                                            self.tr1.id+" "+ self.tr2.id)
            ax2.set_xlim(f[1], f[len(f) - 1])
            ax2.set_ylabel('Phase')
            ax2.set_xlabel('Frequency [Hz]')
            ax2.grid(True, which="both", ls="-", color='grey')
            ax2.legend()

    def plot_correlation(self):

        if len(self.tr1) > 0 and len(self.tr2) > 0:
            sampling_rates = []
            fs1=self.tr1.stats.sampling_rate
            fs2=self.tr2.stats.sampling_rate
            sampling_rates.append(fs1)
            sampling_rates.append(fs2)
            max_sampling_rates = np.max(sampling_rates)

            if fs1 != fs2:
                self.tr1.resample(max_sampling_rates)
                self.tr2.resample(max_sampling_rates)

            cc1 = correlate_maxlag(self.tr1.data, self.tr1.data, maxlag = max([len(self.tr1.data),len(self.tr2.data)]))
            cc2 = correlate_maxlag(self.tr2.data, self.tr2.data, maxlag = max([len(self.tr1.data),len(self.tr2.data)]))
            cc3 = correlate_maxlag(self.tr1.data, self.tr2.data, maxlag = max([len(self.tr1.data),len(self.tr2.data)]))
            N1 = len(cc1)
            N2 = len(cc2)
            N3 = len(cc3)
            self.cross_correlation_Widget_Canvas.plot(get_lags(cc1)/max_sampling_rates, cc1, 0,
                                                      clear_plot=True, linewidth=0.5,color='black')
            self.cross_correlation_Widget_Canvas.plot(get_lags(cc2)/max_sampling_rates, cc2, 1,
                                                      clear_plot=True, linewidth=0.5, color = 'black')
            self.cross_correlation_Widget_Canvas.plot(get_lags(cc3)/max_sampling_rates, cc3, 2,
                                                      clear_plot=True, linewidth=0.5, color = 'red')

    def plot_cross_spectrogram(self):
        if len(self.tr1) > 0 and len(self.tr2) > 0:
            csp = cross_spectrogram(self.tr1, self.tr2, win=self.time_windowSB.value(),
                                    tbp=self.time_bandwidthSB.value(), ntapers = self.num_tapersSB.value())

            [coherence_cross, freq, t] = csp.compute_coherence_crosspectrogram()
            f_min = 0
            f_max = 0.5*(1/max(freq))
            f_max=50
            x, y = np.meshgrid(t, np.linspace(f_min, f_max, coherence_cross.shape[0]))

            self.cross_spectrumWidget_Widget_Canvas.plot_contour(x, y, coherence_cross, axes_index=0,
                     clabel="Coherence", cmap=plt.get_cmap("jet"), vmin=0,vmax=1)
            self.cross_spectrumWidget_Widget_Canvas.set_xlabel(0, "Time (s)")
            self.cross_spectrumWidget_Widget_Canvas.set_ylabel(0, "Frequency (Hz)")


    def plot_cross_scalogram(self):

        base_line = self.base_lineDB.value()
        colour = self.colourCB.currentText()

        if len(self.tr1) > 0 and len(self.tr2) > 0:
            #
            fs1 = self.tr1.stats.sampling_rate
            fs2 = self.tr2.stats.sampling_rate
            fs = max(fs1, fs2)
            if fs1 < fs:
                self.tr1.resample(fs)
            elif fs2 < fs:
                self.tr2.resample(fs)
            all_traces = [self.tr1, self.tr2]
            st = Stream(traces=all_traces)
            maxstart = np.max([tr.stats.starttime for tr in st])
            minend = np.min([tr.stats.endtime for tr in st])
            st.trim(maxstart, minend)
            tr1 = st[0]
            tr2 = st[1]
            tr1.detrend(type='demean')
            tr1.taper(max_percentage=0.05)
            tr2.detrend(type='demean')
            tr2.taper(max_percentage=0.05)

            npts =len(tr1.data)
            t = np.linspace(0,  npts/fs, npts)
            f_max = fs/2
            nf = 40
            wmin=wmax=self.num_cyclesSB.value()
            f_min = self.freq_min_waveletSB.value()
            tt = int(fs / f_min)
            [ba, nConv, frex, half_wave] = ccwt_ba_fast(npts, fs, f_min, f_max, wmin, wmax, tt, nf)

            cf, sc, scalogram1 = cwt_fast(tr1.data, ba, nConv, frex, half_wave, fs)

            cf, sc, scalogram2 = cwt_fast(tr2.data, ba, nConv, frex, half_wave, fs)

            crossCFS = scalogram1 * np.conj(scalogram2)

            cross_scalogram = np.abs(crossCFS)**2
            cross_scalogram = 10*np.log(cross_scalogram/np.max(cross_scalogram))
            cross_scalogram = np.clip(cross_scalogram, a_min=base_line, a_max=0)
            min_cwt = base_line
            max_cwt = 0


            x, y = np.meshgrid(t, np.logspace(np.log10(f_min), np.log10(f_max), cross_scalogram.shape[0]))
            c_f = wmin / 2 * math.pi
            f = np.linspace((f_min), (f_max), cross_scalogram.shape[0])
            pred = (math.sqrt(2) * c_f / f) - (math.sqrt(2) * c_f / f_max)

            pred_comp = t[len(t) - 1] - pred


            #Plot Seismograms

            self.cross_spectrumWidget_Widget_Canvas.plot(tr1.times(), self.tr1.data, 0, color="black",
                    linewidth=0.5,alpha = 0.75)

            self.cross_spectrumWidget_Widget_Canvas.plot(tr2.times(), tr2.data, 0, clear_plot=False, is_twinx=True,
                                                         color="orangered", linewidth=0.5, alpha=0.75)
            info = tr1.id + " " + tr2.id
            self.cross_spectrumWidget_Widget_Canvas.set_plot_label(0, info)
            self.cross_spectrumWidget_Widget_Canvas.set_ylabel(0, "Amplitude")
            #info = "{}.{}.{}".format(tr1.stats.network, tr1.stats.station, tr1.stats.channel)
            #self.cross_spectrumWidget_Widget_Canvas.set_plot_label(0, info)
            #info = "{}.{}.{}".format(tr2.stats.network, tr2.stats.station, tr1.stats.channel)
            #self.cross_spectrumWidget_Widget_Canvas.set_plot_label(0, info)


            # Plot Cross Scalogram
            self.cross_spectrumWidget_Widget_Canvas.plot_contour(x, y, cross_scalogram, axes_index=1, clabel="Cross Power [dB]",
                                           cmap=plt.get_cmap(colour))
            # Plot Cone
            ax_cone = self.cross_spectrumWidget_Widget_Canvas.get_axe(1)
            ax_cone.fill_between(pred, f, 0, color="black", edgecolor="red", alpha=0.3)
            ax_cone.fill_between(pred_comp, f, 0, color="black", edgecolor="red", alpha=0.3)
            self.cross_spectrumWidget_Widget_Canvas.set_xlabel(1, "Time (s)")
            self.cross_spectrumWidget_Widget_Canvas.set_ylabel(1, "Frequency (Hz)")
Example #7
0
class Vespagram(pw.QFrame, UiVespagram):
    def __init__(self, st, inv, t1, t2):
        super(Vespagram, self).__init__()
        self.setupUi(self)
        """
        Vespagram, computed a fixed slowness or backazimuth

        :param params required to initialize the class:
            
        
        """

        self.st = st
        self.inv = inv
        self.t1 = t1
        self.t2 = t2
        self.canvas_vespagram = MatplotlibCanvas(self.widget_vespagram,
                                                 nrows=2)
        self.run_vespaBtn.clicked.connect(self.run_vespa)
        self.plotBtn.clicked.connect(self.plot_vespa)

    def closeEvent(self, ce):
        self.save_values()

    def __load__(self):
        self.load_values()

    #@AsycTime.run_async()
    def run_vespa(self):

        vespa = vespagram_util(self.st,
                               self.freq_min_DB.value(),
                               self.freq_max_DB.value(),
                               self.win_len_DB.value(),
                               self.slownessDB.value(),
                               self.backazimuthCB.value(),
                               self.inv,
                               self.t1,
                               self.t2,
                               self.overlapSB.value(),
                               selection=self.selectionCB.currentText(),
                               method="FK")

        self.x, self.y, self.log_vespa_spectrogram = vespa.vespa_deg()
        md = MessageDialog(self)
        md.set_info_message("Vespagram Estimated !!!")

    def plot_vespa(self):

        if self.selectionCB.currentText() == "Slowness":
            self.__plot_vespa_slow()
        else:
            self.__plot_vespa_az()

    def __plot_vespa_slow(self):
        base_line = self.base_lineDB.value()
        colour = self.colourCB.currentText()
        #vespagram = np.clip(self.log_vespa_spectrogram, a_min=base_line, a_max=0)
        vespagram = np.clip(self.log_vespa_spectrogram, a_min=0, a_max=1)
        self.canvas_vespagram.plot_contour(self.x,
                                           self.y,
                                           vespagram,
                                           axes_index=0,
                                           clabel="Rel. Power",
                                           cmap=plt.get_cmap(colour))
        self.canvas_vespagram.set_xlabel(0, "Time (s)")
        self.canvas_vespagram.set_ylabel(0, "Azimuth")

    def __plot_vespa_az(self):
        base_line = self.base_lineDB.value()
        colour = self.colourCB.currentText()
        #vespagram = np.clip(self.log_vespa_spectrogram, a_min=base_line, a_max=0)
        vespagram = np.clip(self.log_vespa_spectrogram, a_min=0, a_max=1)
        self.canvas_vespagram.plot_contour(self.x,
                                           self.y,
                                           vespagram,
                                           axes_index=1,
                                           clabel="Rel Power",
                                           cmap=plt.get_cmap(colour))
        self.canvas_vespagram.set_xlabel(1, "Time (s)")
        self.canvas_vespagram.set_ylabel(1, "Slowness (s/km)")