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)")
class PlotPolarization(pw.QFrame, UiPlotPolarization ): def __init__(self, z, r, t): super(PlotPolarization, self).__init__() self.setupUi(self) self._z = z-np.mean(z) self._r = r-np.mean(r) self._t = t-np.mean(t) all_traces = [self._z, self._r, self._t] self.st = Stream(traces=all_traces) self._r_max = max(r) self._t_max = max(t) self._z_max=max(z) self.max_value=max([max(abs(z)), max(abs(t)), max(abs(r))]) self.canvas = MatplotlibCanvas(self.plotMatWidget_polarization) self.canvas2D = MatplotlibCanvas(self.plotMatWidget_polarization2, nrows=2, ncols=2, constrained_layout=True) self.canvas.figure.gca(projection='3d') self.plotBtn.clicked.connect(lambda: self.plot_particle()) def plot_particle(self): azimuth, incidence, rect, plan = flinn(self.st) self.canvas.plot_projection(self._r,self._t,self._z, axes_index=0) self.canvas.set_xlabel(0, "Radial") self.canvas.set_ylabel(0, "Transversal") #self.canvas.set_zlabel(0, "Vertical") self.canvas2D.plot(self._r, self._z, 0, clear_plot=True, linewidth=0.5) self.canvas2D.set_xlabel(0, "Radial") self.canvas2D.set_ylabel(0, "Vertical") ax1 = self.canvas2D.get_axe(0) ax1.set_xlim([-self.max_value,self.max_value]) ax1.set_ylim([-self.max_value, self.max_value]) self.canvas2D.plot(self._t, self._z, 1, clear_plot=True, linewidth=0.5) self.canvas2D.set_xlabel(1, "Transversal") self.canvas2D.set_ylabel(1, "Vertical") ax2 = self.canvas2D.get_axe(1) ax2.set_xlim([-self.max_value, self.max_value]) ax2.set_ylim([-self.max_value, self.max_value]) self.canvas2D.plot(self._r, self._t, 2, clear_plot=True, linewidth=0.5) self.canvas2D.set_xlabel(2, "Radial") self.canvas2D.set_ylabel(2, "Transversal") ax3 = self.canvas2D.get_axe(2) ax3.set_xlim([-self.max_value, self.max_value]) ax3.set_ylim([-self.max_value, self.max_value]) self.polarizationText.setPlainText(" Azimuth: {azimuth:.3f} ".format(azimuth=azimuth)) self.polarizationText.appendPlainText(" Incidence Angle: {incidence:.3f} ".format(incidence=incidence)) self.polarizationText.appendPlainText(" Rectilinearity: {rect:.3f} ".format(rect=rect)) self.polarizationText.appendPlainText(" Planarity: {plan:.3f} ".format(plan=plan))
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()
class EarthquakeLocationFrame(pw.QFrame, UiEarthquakeLocationFrame): def __init__(self, parent: pw.QWidget): super(EarthquakeLocationFrame, self).__init__(parent) self.setupUi(self) ParentWidget.set_parent(parent, self) self.__pick_output_path = PickerManager.get_default_output_path() self.__dataless_dir = None self.__nll_manager = None self.__first_polarity = None # Map self.cartopy_canvas = CartopyCanvas(self.widget_map) # Canvas for Earthquake Location Results self.residuals_canvas = MatplotlibCanvas(self.plotMatWidget_residuals) #self.residuals_canvas.figure.subplots_adjust(left = 0.03, bottom = 0.36, right=0.97, top=0.95, wspace=0.2, # hspace=0.0) # Canvas for FOCMEC Results self.focmec_canvas = FocCanvas(self.widget_focmec) self.grid_latitude_bind = BindPyqtObject(self.gridlatSB) self.grid_longitude_bind = BindPyqtObject(self.gridlonSB) self.grid_depth_bind = BindPyqtObject(self.griddepthSB) self.grid_xnode_bind = BindPyqtObject(self.xnodeSB) self.grid_ynode_bind = BindPyqtObject(self.ynodeSB) self.grid_znode_bind = BindPyqtObject(self.znodeSB) self.grid_dxsize_bind = BindPyqtObject(self.dxsizeSB) self.grid_dysize_bind = BindPyqtObject(self.dysizeSB) self.grid_dzsize_bind = BindPyqtObject(self.dzsizeSB) self.genvelBtn.clicked.connect(lambda: self.on_click_run_vel_to_grid()) self.grdtimeBtn.clicked.connect( lambda: self.on_click_run_grid_to_time()) self.runlocBtn.clicked.connect(lambda: self.on_click_run_loc()) self.plotmapBtn.clicked.connect(lambda: self.on_click_plot_map()) self.stationsBtn.clicked.connect( lambda: self.on_click_select_metadata_file()) self.firstpolarityBtn.clicked.connect(self.first_polarity) self.plotpdfBtn.clicked.connect(self.plot_pdf) @property def nll_manager(self): if not self.__nll_manager: self.__nll_manager = NllManager(self.__pick_output_path, self.__dataless_dir) return self.__nll_manager @property def firstpolarity_manager(self): if not self.__first_polarity: self.__first_polarity = FirstPolarity() return self.__first_polarity def on_click_select_metadata_file(self): selected = pw.QFileDialog.getOpenFileName( self, "Select metadata/stations coordinates file") if isinstance(selected[0], str) and os.path.isfile(selected[0]): self.stationsPath.setText(selected[0]) self.set_dataless_dir(self.stationsPath.text()) def set_dataless_dir(self, dir_path): self.__dataless_dir = dir_path self.nll_manager.set_dataless_dir(dir_path) def set_pick_output_path(self, file_path): self.__pick_output_path = file_path self.nll_manager.set_observation_file(file_path) def info_message(self, msg, detailed_message=None): md = MessageDialog(self) md.set_info_message(msg, detailed_message) def subprocess_feedback(self, err_msg: str, set_default_complete=True): """ This method is used as a subprocess feedback. It runs when a raise expect is detected. :param err_msg: The error message from the except. :param set_default_complete: If True it will set a completed successfully message. Otherwise nothing will be displayed. :return: """ if err_msg: md = MessageDialog(self) if "Error code" in err_msg: md.set_error_message( "Click in show details detail for more info.", err_msg) else: md.set_warning_message("Click in show details for more info.", err_msg) else: if set_default_complete: md = MessageDialog(self) md.set_info_message("Completed Successfully.") @parse_excepts(lambda self, msg: self.subprocess_feedback(msg)) def on_click_run_vel_to_grid(self): self.nll_manager.vel_to_grid( self.grid_latitude_bind.value, self.grid_longitude_bind.value, self.grid_depth_bind.value, self.grid_xnode_bind.value, self.grid_ynode_bind.value, self.grid_znode_bind.value, self.grid_dxsize_bind.value, self.grid_dysize_bind.value, self.grid_dzsize_bind.value, self.comboBox_gridtype.currentText(), self.comboBox_wavetype.currentText(), self.modelCB.currentText()) @parse_excepts(lambda self, msg: self.subprocess_feedback(msg)) def on_click_run_grid_to_time(self): if self.distanceSB.value() > 0: limit = self.distanceSB.value() else: limit = np.sqrt( (self.grid_xnode_bind.value * self.grid_dxsize_bind.value)**2 + (self.grid_xnode_bind.value * self.grid_dxsize_bind.value)**2) self.nll_manager.grid_to_time(self.grid_latitude_bind.value, self.grid_longitude_bind.value, self.grid_depth_bind.value, self.comboBox_grid.currentText(), self.comboBox_angles.currentText(), self.comboBox_ttwave.currentText(), limit) @parse_excepts(lambda self, msg: self.subprocess_feedback( msg, set_default_complete=False)) def on_click_run_loc(self): transform = self.transCB.currentText() std_out = self.nll_manager.run_nlloc(self.grid_latitude_bind.value, self.grid_longitude_bind.value, self.grid_depth_bind.value, transform) self.info_message("Location complete. Check details.", std_out) @parse_excepts(lambda self, msg: self.subprocess_feedback(msg)) def on_click_plot_map(self): origin = self.nll_manager.get_NLL_info() scatter_x, scatter_y, scatter_z, pdf = self.nll_manager.get_NLL_scatter( ) lat = origin.latitude lon = origin.longitude stations = self.nll_manager.stations_match() self.cartopy_canvas.plot_map(lon, lat, scatter_x, scatter_y, scatter_z, 0, resolution='high', stations=stations) # Writing Location information self.add_earthquake_info(origin) xp, yp, xs, ys = self.nll_manager.ger_NLL_residuals() self.plot_residuals(xp, yp, xs, ys) def plot_pdf(self): scatter_x, scatter_y, scatter_z, pdf = self.nll_manager.get_NLL_scatter( ) self.pdf = PDFmanger(scatter_x, scatter_y, scatter_z, pdf) self.pdf.plot_scatter() def plot_residuals(self, xp, yp, xs, ys): artist = self.residuals_canvas.plot(xp, yp, axes_index=0, linewidth=0.5) self.residuals_canvas.set_xlabel(0, "Station") self.residuals_canvas.set_ylabel(0, "P wave Res") self.residuals_canvas.set_yaxis_color(self.residuals_canvas.get_axe(0), artist.get_color(), is_left=True) self.residuals_canvas.plot(xs, ys, 0, is_twinx=True, color="red", linewidth=0.5) self.residuals_canvas.set_ylabel_twinx(0, "S wave Res") self.residuals_canvas.plot(xp, yp, axes_index=0, linewidth=0.5) def first_polarity(self): import pandas as pd path_output = os.path.join(ROOT_DIR, "earthquakeAnalisysis", "location_output", "loc", "first_polarity.fp") self.firstpolarity_manager.create_input() self.firstpolarity_manager.run_focmec() Station, Az, Dip, Motion = self.firstpolarity_manager.get_dataframe() cat, Plane_A = self.firstpolarity_manager.extract_focmec_info() #print(cat[0].focal_mechanisms[0]) strike_A = Plane_A.strike dip_A = Plane_A.dip rake_A = Plane_A.rake misfit_first_polarity = cat[0].focal_mechanisms[0].misfit azimuthal_gap = cat[0].focal_mechanisms[0].azimuthal_gap number_of_polarities = cat[0].focal_mechanisms[ 0].station_polarity_count first_polarity_results = { "First_Polarity": [ "Strike", "Dip", "Rake", "misfit_first_polarity", "azimuthal_gap", "number_of_polarities" ], "results": [ strike_A, dip_A, rake_A, misfit_first_polarity, azimuthal_gap, number_of_polarities ] } df = pd.DataFrame(first_polarity_results, columns=["First_Polarity", "results"]) df.to_csv(path_output, sep=' ', index=False) self.focmec_canvas.drawFocMec(strike_A, dip_A, rake_A, Station, Az, Dip, Motion, 0) self.add_first_polarity_info(first_polarity_results) def add_first_polarity_info(self, first_polarity_results): self.FirstPolarityInfoText.setPlainText("First Polarity Results") self.FirstPolarityInfoText.appendPlainText( "Strike: {Strike:.3f}".format( Strike=first_polarity_results["results"][0])) self.FirstPolarityInfoText.appendPlainText( "Dip: {Dip:.3f}".format(Dip=first_polarity_results["results"][1])) self.FirstPolarityInfoText.appendPlainText("Rake: {Rake:.3f}".format( Rake=first_polarity_results["results"][2])) self.FirstPolarityInfoText.appendPlainText( "Misfit: {Misfit:.3f}".format( Misfit=first_polarity_results["results"][3])) self.FirstPolarityInfoText.appendPlainText( "GAP: {GAP:.3f}".format(GAP=first_polarity_results["results"][4])) self.FirstPolarityInfoText.appendPlainText( "Number of polarities: {NP:.3f}".format( NP=first_polarity_results["results"][5])) def add_earthquake_info(self, origin: Origin): self.EarthquakeInfoText.setPlainText( " Origin time and RMS: {origin_time} {standard_error:.3f}" .format(origin_time=origin.time, standard_error=origin.quality.standard_error)) self.EarthquakeInfoText.appendPlainText( " Hypocenter Geographic Coordinates: " "Latitude {lat:.3f} " "Longitude {long:.3f} Depth {depth:.3f} " "Uncertainty {unc:.3f}".format( lat=origin.latitude, long=origin.longitude, depth=origin.depth / 1000, unc=origin.depth_errors['uncertainty'])) self.EarthquakeInfoText.appendPlainText( " Horizontal Ellipse: Max Horizontal Err {:.3f} " "Min Horizontal Err {:.3f} " "Azimuth {:.3f}".format( origin.origin_uncertainty.max_horizontal_uncertainty, origin.origin_uncertainty.min_horizontal_uncertainty, origin.origin_uncertainty.azimuth_max_horizontal_uncertainty)) self.EarthquakeInfoText.appendPlainText( " Quality Parameters: Number of Phases {:.3f} " "Azimuthal GAP {:.3f} Minimum Distance {:.3f} " "Maximum Distance {:.3f}".format(origin.quality.used_phase_count, origin.quality.azimuthal_gap, origin.quality.minimum_distance, origin.quality.maximum_distance))
class Earthquake3CFrame(pw.QFrame, UiEarthquake3CFrame): def __init__(self, parent: pw.QWidget): super(Earthquake3CFrame, self).__init__(parent) self.setupUi(self) ParentWidget.set_parent(parent, self) #Initialize parametrs for plot rotation self._z = {} self._r = {} self._t = {} self._st = {} self.inventory = {} #self.filter_3ca = FilterBox(self.toolQFrame, 1) # add filter box component. self.parameters = ParametersSettings() # 3C_Component self.canvas = MatplotlibCanvas(self.plotMatWidget_3C) self.canvas.set_new_subplot(3, ncols=1) self.canvas_pol = MatplotlibCanvas(self.Widget_polarization) self.canvas.mpl_connect('key_press_event', self.key_pressed) # binds self.root_path_bind_3C = BindPyqtObject(self.rootPathForm_3C, self.onChange_root_path_3C) self.degreeSB_bind = BindPyqtObject(self.degreeSB) self.vertical_form_bind = BindPyqtObject(self.verticalQLineEdit) self.north_form_bind = BindPyqtObject(self.northQLineEdit) self.east_form_bind = BindPyqtObject(self.eastQLineEdit) # accept drops self.vertical_form_bind.accept_dragFile( drop_event_callback=self.drop_event) self.north_form_bind.accept_dragFile( drop_event_callback=self.drop_event) self.east_form_bind.accept_dragFile( drop_event_callback=self.drop_event) # Add file selector to the widget self.file_selector = FilesView(self.root_path_bind_3C.value, parent=self.fileSelectorWidget) self.file_selector.setDragEnabled(True) self.selectDirBtn_3C.clicked.connect(self.on_click_select_directory_3C) self.rotateplotBtn.clicked.connect( lambda: self.on_click_rotate(self.canvas)) self.rot_macroBtn.clicked.connect( lambda: self.open_parameters_settings()) self.polarizationBtn.clicked.connect(self.on_click_polarization) ### self.plotpolBtn.clicked.connect(self.plot_particle_motion) self.stationsBtn.clicked.connect(self.stationsInfo) self.save_rotatedBtn.clicked.connect(self.save_rotated) ### def open_parameters_settings(self): self.parameters.show() def info_message(self, msg): md = MessageDialog(self) md.set_info_message(msg) @staticmethod def drop_event(event: pqg.QDropEvent, bind_object: BindPyqtObject): data = event.mimeData() url = data.urls()[0] bind_object.value = url.fileName() @property def north_component_file(self): return os.path.join(self.root_path_bind_3C.value, self.north_form_bind.value) @property def vertical_component_file(self): return os.path.join(self.root_path_bind_3C.value, self.vertical_form_bind.value) @property def east_component_file(self): return os.path.join(self.root_path_bind_3C.value, self.east_form_bind.value) def onChange_root_path_3C(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) # Function added for 3C Components def on_click_select_directory_3C(self): if "darwin" == platform: dir_path = pw.QFileDialog.getExistingDirectory( self, 'Select Directory', self.root_path_bind_3C.value) else: dir_path = pw.QFileDialog.getExistingDirectory( self, 'Select Directory', self.root_path_bind_3C.value, pw.QFileDialog.DontUseNativeDialog) if dir_path: self.root_path_bind_3C.value = dir_path def set_times(self, st): max_start = np.max([tr.stats.starttime for tr in st]) min_end = np.min([tr.stats.endtime for tr in st]) return min_end, max_start def on_click_rotate(self, canvas): time1 = convert_qdatetime_utcdatetime(self.dateTimeEdit_4) time2 = convert_qdatetime_utcdatetime(self.dateTimeEdit_5) angle = self.degreeSB.value() incidence_angle = self.incidenceSB.value() method = self.methodCB.currentText() parameters = self.parameters.getParameters() try: sd = PolarizationAnalyis(self.vertical_component_file, self.north_component_file, self.east_component_file) time, z, r, t, st = sd.rotate(self.inventory, time1, time2, angle, incidence_angle, method=method, parameters=parameters, trim=True) self._z = z self._r = r self._t = t self._st = st rotated_seismograms = [z, r, t] for index, data in enumerate(rotated_seismograms): self.canvas.plot(time, data, index, color="black", linewidth=0.5) info = "{}.{}.{}".format(self._st[index].stats.network, self._st[index].stats.station, self._st[index].stats.channel) ax = self.canvas.get_axe(0) ax.set_xlim(sd.t1.matplotlib_date, sd.t2.matplotlib_date) formatter = mdt.DateFormatter('%Y/%m/%d/%H:%M:%S') ax.xaxis.set_major_formatter(formatter) self.canvas.set_plot_label(index, info) canvas.set_xlabel(2, "Time (s)") except InvalidFile: self.info_message( "Invalid mseed files. Please, make sure to select all the three components (Z, N, E) " "for rotate.") except ValueError as error: self.info_message(str(error)) def on_click_polarization(self): time1 = convert_qdatetime_utcdatetime(self.dateTimeEdit_4) time2 = convert_qdatetime_utcdatetime(self.dateTimeEdit_5) sd = PolarizationAnalyis(self.vertical_component_file, self.north_component_file, self.east_component_file) try: var = sd.polarize(time1, time2, self.doubleSpinBox_winlen.value(), self.freq_minDB.value(), self.freq_maxDB.value()) artist = self.canvas_pol.plot( var['time'], var[self.comboBox_yaxis.currentText()], 0, clear_plot=True, linewidth=0.5) self.canvas_pol.set_xlabel(0, "Time [s]") self.canvas_pol.set_ylabel(0, self.comboBox_yaxis.currentText()) self.canvas_pol.set_yaxis_color(self.canvas_pol.get_axe(0), artist.get_color(), is_left=True) self.canvas_pol.plot(var['time'], var[self.comboBox_polarity.currentText()], 0, is_twinx=True, color="red", linewidth=0.5) self.canvas_pol.set_ylabel_twinx( 0, self.comboBox_polarity.currentText()) except InvalidFile: self.info_message( "Invalid mseed files. Please, make sure to select all the three components (Z, N, E) " "for polarization.") except ValueError as error: self.info_message(str(error)) def plot_particle_motion(self): self._plot_polarization = PlotPolarization(self._z, self._r, self._t) self._plot_polarization.show() def stationsInfo(self): files = [] try: if self.vertical_component_file and self.north_component_file and self.east_component_file: files = [ self.vertical_component_file, self.north_component_file, self.east_component_file ] except: pass sd = [] if len(files) == 3: for file in files: try: 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) except: pass self._stations_info = StationsInfo(sd) self._stations_info.show() def save_rotated(self): import os 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 self._st: n = len(self._st) 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") def key_pressed(self, event): if event.key == 'q': x1, y1 = event.xdata, event.ydata tt = UTCDateTime(mdt.num2date(x1)) set_qdatetime(tt, self.dateTimeEdit_4) self.canvas.draw_arrow(x1, 0, arrow_label="st", color="purple", linestyles='--', picker=False) self.canvas.draw_arrow(x1, 1, arrow_label="st", color="purple", linestyles='--', picker=False) self.canvas.draw_arrow(x1, 2, arrow_label="st", color="purple", linestyles='--', picker=False) if event.key == 'e': x1, y1 = event.xdata, event.ydata tt = UTCDateTime(mdt.num2date(x1)) set_qdatetime(tt, self.dateTimeEdit_5) self.canvas.draw_arrow(x1, 0, arrow_label="et", color="purple", linestyles='--', picker=False) self.canvas.draw_arrow(x1, 1, arrow_label="st", color="purple", linestyles='--', picker=False) self.canvas.draw_arrow(x1, 2, arrow_label="st", color="purple", linestyles='--', picker=False)
class MagnitudeCalc(pw.QFrame, UiMagnitudeFrame, metaclass=SettingsLoader): def __init__(self, origin, inventory, chop): super(MagnitudeCalc, self).__init__() self.setupUi(self) self.spectrum_Widget_Canvas = MatplotlibCanvas(self.spectrumWidget, nrows=2, ncols=1, sharex=False, constrained_layout=True) self.event = origin self.chop = chop self.inventory = inventory self.runBtn.clicked.connect(self.run_magnitudes) self.saveBtn.clicked.connect(self.save_results) self.plotBtn.clicked.connect(self.plot_comparison) self.Mw = [] self.Mw_std = [] self.Ms = [] self.Ms_std = [] self.Mb = [] self.Mb_std = [] self.ML = [] self.ML_std = [] self.Mc = [] self.Mc_std = [] self.ML = [] self.ML_std = [] self.Magnitude_Ws = [] self.Mss = [] self.Mcs = [] self.Mcs = [] self.MLs = [] def closeEvent(self, ce): self.save_values() def __load__(self): self.load_values() def moment_magnitude(self): density = self.densityDB.value() vp = self.vpDB.value() * 1000 vs = self.vsDB.value() * 1000 if self.phaseCB.currentText() == 'P-Wave': radiation_pattern = 0.52 velocity = vp k = 0.32 elif self.phaseCB.currentText() == "S-Wave": radiation_pattern = 0.63 velocity = vs k = 0.21 Mws = [] Mws_std = [] Magnitude_Ws = [] origin_time = self.event.time moments = [] source_radii = [] corner_frequencies = [] corner_freqs = [] self.spectrum_Widget_Canvas.plot([], [], 0) ax1 = self.spectrum_Widget_Canvas.get_axe(0) ax1.cla() for key in self.chop['Body waves']: magnitude_dict = self.chop['Body waves'][key] # Calculate distance coords = get_coordinates_from_metadata(self.inventory, magnitude_dict[0]) dist, _, _ = gps2dist_azimuth(coords.Latitude, coords.Longitude, self.event.latitude, self.event.longitude) pick_time = UTCDateTime(mdt.num2date(magnitude_dict[1][0])) data = np.array(magnitude_dict[2]) delta = 1 / magnitude_dict[0][6] # Calculate the spectrum. spec, freq, jackknife_errors, _, _ = mtspec(data, delta=delta, time_bandwidth=3.5, statistics=True) spec = spec[1:] freq = freq[1:] # go to amplitude and displacement spec = np.sqrt(spec) / (2 * np.pi * freq) # Plot spectrum ax1.loglog(freq, spec, '0.1', linewidth=0.5, color='black', alpha=0.5) ax1.set_ylim(spec.min() / 10.0, spec.max() * 100.0) ax1.set_xlim(freq[1], freq[len(freq) - 1]) ax1.set_ylabel('Amplitude') ax1.set_xlabel('Frequency [Hz]') ax1.grid(True, which="both", ls="-", color='grey') ax1.legend() # Finish Plot tt = pick_time - origin_time #print("Distance",dist,"Vp",vp,"Q",quality,"Density",density, "Travel Time", tt) # Q as a function of freq Qo = self.qualityDB.value() a = self.coeffDB.value() quality = (Qo) * (freq)**a try: fit = fit_spectrum(spec, freq, tt, spec.max(), 10.0, quality) except: continue if fit is None: continue Omega_0, f_c, err, _ = fit # Second Plot theoretical_spectrum = calculate_source_spectrum( freq, Omega_0, f_c, quality, tt) ax1.loglog(freq, theoretical_spectrum, color="red", alpha=0.5, lw=0.5) ax1.set_xlim(freq[1], freq[len(freq) - 1]) ax1.set_ylabel('Amplitude') ax1.set_xlabel('Frequency [Hz]') ax1.grid(True, which="both", ls="-", color='grey') corner_freqs.append(f_c) M_0 = 4.0 * np.pi * density * velocity**3 * dist * np.sqrt( Omega_0**2) / radiation_pattern Magnitude_Ws.append(2.0 / 3.0 * (np.log10(M_0) - 9.1)) r = 3 * k * vs / sum(corner_freqs) moments.append(M_0) source_radii.append(r) corner_frequencies.extend(corner_freqs) # Calculate the seismic moment via basic statistics. moments = np.array(moments) moment = moments.mean() moment_std = moments.std() corner_frequencies = np.array(corner_frequencies) corner_frequency = corner_frequencies.mean() corner_frequency_std = corner_frequencies.std() # Calculate the source radius. source_radii = np.array(source_radii) source_radius = source_radii.mean() self.source_radius = source_radius source_radius_std = source_radii.std() # Calculate the stress drop of the event based on the average moment and # source radii. stress_drop = (7 * moment) / (16 * source_radius**3) stress_drop_std = np.sqrt((stress_drop ** 2) * \ (((moment_std ** 2) / (moment ** 2)) + \ (9 * source_radius * source_radius_std ** 2))) if source_radius > 0 and source_radius_std < source_radius: print("Source radius:", source_radius, " Std:", source_radius_std) print("Stress drop:", stress_drop / 1E5, " Std:", stress_drop_std / 1E5) self.stress_drop = stress_drop self.Magnitude_Ws = Magnitude_Ws Mw = 2.0 / 3.0 * (np.log10(moment) - 9.1) Mw_std = 2.0 / 3.0 * moment_std / (moment * np.log(10)) Mws_std.append(Mw_std) Mws.append(Mw) print("Moment Magnitude", Mws, "Moment Magnitude deviation", Mws_std) label = "Mw" self.plot_histograms(Magnitude_Ws, label) self.Mw = Mw self.Mw_std = Mw_std def magnitude_surface(self): Ms = [] for key in self.chop['Surf Waves']: magnitude_dict = self.chop['Surf Waves'][key] coords = get_coordinates_from_metadata(self.inventory, magnitude_dict[0]) dist = locations2degrees(coords.Latitude, coords.Longitude, self.event.latitude, self.event.longitude) data = np.array(magnitude_dict[2]) * 1e6 # convert to nm Ms_value = np.log10(np.max(data) / (2 * np.pi)) + 1.66 * np.log10(dist) + 3.3 Ms.append(Ms_value) Ms = np.array(Ms) self.Mss = Ms Ms_mean = Ms.mean() Ms_deviation = Ms.std() print("Surface Magnitude", Ms_mean, "Variance", Ms_deviation) label = "Ms" self.plot_histograms(Ms, label) self.Ms = Ms_mean self.Ms_std = Ms_deviation def magnitude_body(self): Mb = [] path_to_atenuation_file = os.path.join(ROOT_DIR, "earthquakeAnalisysis", "magnitude_atenuation", "atenuation.txt") x, y = np.loadtxt(path_to_atenuation_file, skiprows=1, unpack=True) for key in self.chop['Body waves']: magnitude_dict = self.chop['Body waves'][key] coords = get_coordinates_from_metadata(self.inventory, magnitude_dict[0]) dist = locations2degrees(coords.Latitude, coords.Longitude, self.event.latitude, self.event.longitude) dist = np.floor(dist) if dist < 16: print( "Epicentral Distance ", dist, " is less than 16 degrees, Body-wave Magnitude couldn't be calculated" ) else: loc = np.where(x == dist)[0][0] atenuation = y[loc] data = np.array(magnitude_dict[2]) * 1e6 # convert to nm Mb_value = (np.log10(np.max(data)) / (2 * np.pi)) + atenuation Mb.append(Mb_value) Mbs = np.array(Mb) Mb_mean = Mbs.mean() Mb_deviation = Mb.std() self.Mb = Mb_mean self.Mb_std = Mb_deviation print("Body Magnitude", Mb_mean, "Variance", Mb_deviation) label = "Mb" self.Mbs = Mbs if len(Mb) > 0: self.plot_histograms(Mb, label) def magnitude_coda(self): Mc = [] # values for california a = 2.0 b = 0.0035 c = -0.87 # for key in self.chop['Coda']: magnitude_dict = self.chop['Coda'][key] coords = get_coordinates_from_metadata(self.inventory, magnitude_dict[0]) dist, _, _ = gps2dist_azimuth(coords.Latitude, coords.Longitude, self.event.latitude, self.event.longitude) dist = dist / 1000 #data = np.array(magnitude_dict[2]) pick_time = UTCDateTime(mdt.num2date(magnitude_dict[1][0])) end_time = UTCDateTime(mdt.num2date(magnitude_dict[1][-1])) t_coda = end_time - pick_time Mc_value = a * np.log10(t_coda) + b * dist + c Mc_value = Mc_value Mc.append(Mc_value) Mcs = np.array(Mc) Mc_mean = Mcs.mean() Mc_deviation = Mcs.std() print("Coda Magnitude", Mc_mean, "Variance", Mc_deviation) label = "Mc" self.plot_histograms(Mc, label) self.Mcs = Mcs self.Mc = Mc_mean self.Mc_std = Mc_deviation def magnitude_local(self): ML = [] for key in self.chop['Body waves']: magnitude_dict = self.chop['Body waves'][key] coords = get_coordinates_from_metadata(self.inventory, magnitude_dict[0]) dist, _, _ = gps2dist_azimuth(coords.Latitude, coords.Longitude, self.event.latitude, self.event.longitude) dist = dist / 1000 data = np.array( magnitude_dict[2] ) # already converted Wood Anderson (Gain in mm 2800 +-60) max_amplitude = np.max(data) * 1e3 # convert to mm --> nm ML_value = np.log10( max_amplitude) + 1.11 * np.log10(dist) + 0.00189 * dist - 2.09 ML.append(ML_value) MLs = np.array(ML) ML_mean = MLs.mean() ML_deviation = MLs.std() print("Local Magnitude", ML_mean, "Variance", ML_deviation) label = "ML" self.MLs = MLs self.plot_histograms(ML, label) self.ML = ML_mean self.ML_std = ML_deviation def run_magnitudes(self): self.spectrum_Widget_Canvas.plot([], [], 1) self.ax2 = self.spectrum_Widget_Canvas.get_axe(1) self.ax2.cla() if self.local_magnitudeRB.isChecked(): print("Calculating Local Magnitude") try: self.magnitude_local() except: pass if self.magnitudesRB.isChecked(): try: if self.body_waveCB.isChecked(): print("Calculating Body-Wave Magnitude") self.magnitude_body() except: pass try: if self.surface_waveCB.isChecked(): print("Calculating Surface-Wave Magnitude") self.magnitude_surface() except: pass try: if self.moment_magnitudeCB.isChecked(): print("Calculating Moment Magnitude") self.moment_magnitude() except: pass try: if self.coda_magnitudeCB.isChecked(): print("Coda Moment Magnitude") self.magnitude_coda() except: pass self.print_magnitudes_results() def print_magnitudes_results(self): self.magnitudesText.setPlainText(" Magnitudes Estimation Results ") try: if self.Mw: self.magnitudesText.appendPlainText( "Moment Magnitude: " " Mw {Mw:.3f} " " std {std:.3f} " "Source Radious {source:.3f} " "Stress Drop {stress:.3E} ".format( Mw=self.Mw, std=self.Mw_std, source=self.source_radius / 1000, stress=self.stress_drop)) except: pass try: if self.Ms: self.magnitudesText.appendPlainText("Surface-Wave Magnitude: " " Ms {Ms:.3f} " " std {std:.3f} ".format( Ms=self.Ms, std=self.Ms_std)) except: pass try: if self.Mb: self.magnitudesText.appendPlainText("Body-Wave Magnitude: " " Mb {Mb:.3f} " " std {std:.3f} ".format( Mb=self.Mb, std=self.Mb_std)) except: pass try: if self.Mc: self.magnitudesText.appendPlainText("Coda Magnitude: " " Mc {Mc:.3f} " " std {std:.3f} ".format( Mc=self.Mc, std=self.Mc_std)) except: pass try: if self.ML: self.magnitudesText.appendPlainText("Coda Magnitude: " " ML {ML:.3f} " " std {std:.3f} ".format( ML=self.ML, std=self.ML_std)) except: pass def save_results(self): import pandas as pd path_output = os.path.join(ROOT_DIR, "earthquakeAnalisysis", "location_output", "loc", "magnitudes_output.mag") Magnitude_results = { 'Magnitudes': [ "Mw", "Mw_std", "Ms", "Ms_std", "Mb", "Mb_std", "Mc", "Mc_std", "ML", "ML_std" ], 'results': [ self.Mw, self.Mw_std, self.Ms, self.Ms_std, self.Mb, self.Mb_std, self.Mc, self.Mc_std, self.ML, self.ML_std ] } df = pd.DataFrame(Magnitude_results, columns=['Magnitudes', 'results']) print(df) df.to_csv(path_output, sep=' ', index=False) def plot_histograms(self, magnitudes, label): self.ax2.hist(magnitudes, bins=4 * len(magnitudes), alpha=0.5, label=label) self.ax2.set_xlabel("Magnitude", size=12) self.ax2.set_ylabel("Count", size=12) self.ax2.legend(loc='upper right') def plot_comparison(self): import matplotlib.pyplot as plt from isp.Gui.Frames import MatplotlibFrame list_magnitudes = [] labels = [] if len(self.Magnitude_Ws) >= 0: list_magnitudes.append(self.Magnitude_Ws) labels.append("Mw") if len(self.Mss) >= 0: list_magnitudes.append(self.Mss) labels.append("Ms") if len(self.Mcs) >= 0: list_magnitudes.append(self.Mcs) labels.append("Mc") if len(self.MLs) >= 0: labels.append("ML") list_magnitudes.append(self.MLs) fig, ax1 = plt.subplots(figsize=(6, 6)) self.mpf = MatplotlibFrame(fig) k = 0 for magnitude in list_magnitudes: label = labels[k] x = np.arange(len(magnitude)) + 1 ax1.scatter(x, magnitude, s=15, alpha=0.5, label=label) ax1.tick_params(direction='in', labelsize=10) ax1.legend(loc='upper right') plt.ylabel('Magnitudes', fontsize=10) plt.xlabel('Counts', fontsize=10) k = k + 1 self.mpf.show()
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)")
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()
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)")
class SyntheticsAnalisysFrame(pw.QMainWindow, UiSyntheticsAnalisysFrame): def __init__(self, parent: pw.QWidget = None): super(SyntheticsAnalisysFrame, self).__init__(parent) self.setupUi(self) ParentWidget.set_parent(parent, self) self.setWindowTitle('Synthetics Analysis Frame') self.setWindowIcon(pqg.QIcon(':\icons\pen-icon.png')) #Initialize parametrs for plot rotation self._z = {} self._r = {} self._t = {} self._st = {} self.inventory = {} parameters = {} self._generator = SyntheticsGeneratorDialog(self) # 3C_Component self.focmec_canvas = FocCanvas(self.widget_fp) self.canvas = MatplotlibCanvas(self.plotMatWidget_3C) self.canvas.set_new_subplot(3, ncols=1) # Map self.cartopy_canvas = CartopyCanvas(self.map_widget) # binds self.root_path_bind_3C = BindPyqtObject(self.rootPathForm_3C, self.onChange_root_path_3C) self.vertical_form_bind = BindPyqtObject(self.verticalQLineEdit) self.north_form_bind = BindPyqtObject(self.northQLineEdit) self.east_form_bind = BindPyqtObject(self.eastQLineEdit) self.generation_params_bind = BindPyqtObject(self.paramsPathLineEdit) # accept drops self.vertical_form_bind.accept_dragFile(drop_event_callback=self.drop_event) self.north_form_bind.accept_dragFile(drop_event_callback=self.drop_event) self.east_form_bind.accept_dragFile(drop_event_callback=self.drop_event) self.generation_params_bind.accept_dragFile(drop_event_callback=self.drop_event) self.paramsPathLineEdit.textChanged.connect(self._generationParamsChanged) # Add file selector to the widget self.file_selector = FilesView(self.root_path_bind_3C.value, parent=self.fileSelectorWidget) self.file_selector.setDragEnabled(True) self.selectDirBtn_3C.clicked.connect(self.on_click_select_directory_3C) self.plotBtn.clicked.connect(self.on_click_rotate) ### self.stationsBtn.clicked.connect(self.stationsInfo) ### self.actionGenerate_synthetics.triggered.connect(lambda : self._generator.show()) def info_message(self, msg): md = MessageDialog(self) md.set_info_message(msg) def _generationParamsChanged(self): with open(self.generation_params_file, 'rb') as f: self.params = pickle.load(f) depth_est =self.params['sourcedepthinmeters'] depth_est =(float(depth_est))/1000 #self.paramsTextEdit.setPlainText(str(params)) self.paramsTextEdit.setPlainText("Earth Model: {model}".format(model=self.params['model'])) self.paramsTextEdit.appendPlainText("Event Coords: {lat} {lon} {depth}".format( lat=self.params['sourcelatitude'],lon=self.params['sourcelongitude'], depth=str(depth_est))) self.paramsTextEdit.appendPlainText("Time: {time}".format(time=self.params['origintime'])) self.paramsTextEdit.appendPlainText("Units: {units}".format(units=self.params['units'])) if 'sourcedoublecouple' in self.params: self.paramsTextEdit.appendPlainText("Source: {source}".format(source= self.params['sourcedoublecouple'])) if 'sourcemomenttensor' in self.params: self.paramsTextEdit.appendPlainText("Source: {source}".format(source= self.params['sourcemomenttensor'])) @staticmethod def drop_event(event: pqg.QDropEvent, bind_object: BindPyqtObject): data = event.mimeData() url = data.urls()[0] bind_object.value = url.fileName() @property def north_component_file(self): return os.path.join(self.root_path_bind_3C.value, self.north_form_bind.value) @property def vertical_component_file(self): return os.path.join(self.root_path_bind_3C.value, self.vertical_form_bind.value) @property def east_component_file(self): return os.path.join(self.root_path_bind_3C.value, self.east_form_bind.value) @property def generation_params_file(self): return os.path.join(self.root_path_bind_3C.value, self.generation_params_bind.value) def onChange_root_path_3C(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) # Function added for 3C Components def on_click_select_directory_3C(self): if "darwin" == platform: dir_path = pw.QFileDialog.getExistingDirectory(self, 'Select Directory', self.root_path_bind_3C.value) else: dir_path = pw.QFileDialog.getExistingDirectory(self, 'Select Directory', self.root_path_bind_3C.value, pw.QFileDialog.DontUseNativeDialog) if dir_path: self.root_path_bind_3C.value = dir_path def on_click_rotate(self, canvas): time1 = convert_qdatetime_utcdatetime(self.dateTimeEdit_4) time2 = convert_qdatetime_utcdatetime(self.dateTimeEdit_5) try: sd = SeismogramData(self.vertical_component_file) z = sd.get_waveform() sd = SeismogramData(self.north_component_file) n = sd.get_waveform() sd = SeismogramData(self.east_component_file) e = sd.get_waveform() seismograms = [z, n, e] time = z.times("matplotlib") self._st = Stream(traces=seismograms) for index, data in enumerate(seismograms): self.canvas.plot(time, data, index, color="black", linewidth=0.5) info = "{}.{}.{}".format(self._st[index].stats.network, self._st[index].stats.station, self._st[index].stats.channel) ax = self.canvas.get_axe(0) ax.set_xlim(time1.matplotlib_date, time2.matplotlib_date) formatter = mdt.DateFormatter('%Y/%m/%d/%H:%M:%S') ax.xaxis.set_major_formatter(formatter) self.canvas.set_plot_label(index, info) self.canvas.set_xlabel(2, "Time (s)") if 'sourcedoublecouple' in self.params: self.focmec_canvas.drawSynthFocMec(0, first_polarity = self.params['sourcedoublecouple'], mti = []) if 'sourcemomenttensor' in self.params: self.focmec_canvas.drawSynthFocMec(0, first_polarity= [], mti=self.params['sourcemomenttensor']) except InvalidFile: self.info_message("Invalid mseed files. Please, make sure you have generated correctly the synthetics") self.__map_coords() def stationsInfo(self): files = [] try: if self.vertical_component_file and self.north_component_file and self.east_component_file: files = [self.vertical_component_file, self.north_component_file, self.east_component_file] except: pass sd = [] if len(files)==3: for file in files: try: 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) except: pass self._stations_info = StationsInfo(sd) self._stations_info.show() def __map_coords(self): map_dict = {} sd = [] with open(self.generation_params_file, 'rb') as f: params = pickle.load(f) n = len(params["bulk"]) for j in range(n): for key in params["bulk"][j]: if key == "latitude": lat = params["bulk"][j][key] elif key == "longitude": lon = params["bulk"][j][key] #elif key == "networkcode": # net = params["bulk"][j][key] elif key == "stationcode": sta = params["bulk"][j][key] sd.append(sta) map_dict[sta] = [lon, lat] self.cartopy_canvas.plot_map(params['sourcelongitude'], params['sourcelatitude'], 0, 0, 0, 0, resolution='low', stations=map_dict)