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 TimeFrequencyFrame(BaseFrame, UiTimeFrequencyFrame): def __init__(self, ): super(TimeFrequencyFrame, self).__init__() self.setupUi(self) self.dayplot_frame = None # Bind buttons self.selectDirBtn.clicked.connect(self.on_click_select_directory) self.dayPlotBtn.clicked.connect(self.on_click_dayplot) # Bind qt objects self.root_path_bind = BindPyqtObject(self.rootPathForm, self.onChange_root_path) self.event_info = EventInfoBox(self.mainToolsWidget, None) self.event_info.set_buttons_visibility(False) # 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)) self.time_analysis_widget = TimeAnalysisWidget( self.canvasWidget, parent_name="time_analysis_0") self.time_analysis_widget2 = TimeAnalysisWidget( self.canvasWidget, parent_name="time_analysis_1") self.time_analysis_windows = [ self.time_analysis_widget, self.time_analysis_widget2 ] for taw in self.time_analysis_windows: taw.register_file_selector(self.file_selector) taw.set_event_info(self.event_info) self.actionPlotEnvelope.toggled.connect(self.on_envelop_toggle) 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_envelop_toggle(self, checked: bool): for taw in self.time_analysis_windows: taw.is_envelop_checked = checked 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 on_click_select_directory(self): if "darwin" == platform: dir_path = pw.QFileDialog.getExistingDirectory( self, 'Select Directory', self.root_path_bind.value) else: dir_path = pw.QFileDialog.getExistingDirectory( self, 'Select Directory', self.root_path_bind.value, pw.QFileDialog.DontUseNativeDialog) if dir_path: self.root_path_bind.value = dir_path def plot_day_view(self): st = read(self.file_selector.file_path) self.dayplot_frame = MatplotlibFrame(st, type='dayplot') self.dayplot_frame.show() def on_click_dayplot(self): try: self.validate_file() self.plot_day_view() except InvalidFile as e: md = MessageDialog(self) md.set_info_message(e.message)
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 MTIFrame(BaseFrame, UiMomentTensor): def __init__(self): super(MTIFrame, self).__init__() self.setupUi(self) #super(MTIFrame, self).__init__() self.setupUi(self) self.__stations_dir = None self.__metadata_manager = None self.inventory = {} self._stations_info = {} self.stream = None # Binding self.root_path_bind = BindPyqtObject(self.rootPathForm) #self.dataless_path_bind = BindPyqtObject(self.datalessPathForm) self.metadata_path_bind = BindPyqtObject(self.datalessPathForm, self.onChange_metadata_path) self.earth_path_bind = BindPyqtObject(self.earth_modelPathForm) # Binds self.selectDirBtn.clicked.connect( lambda: self.on_click_select_directory(self.root_path_bind)) self.datalessBtn.clicked.connect( lambda: self.on_click_select_metadata_file(self.metadata_path_bind )) self.earthmodelBtn.clicked.connect( lambda: self.on_click_select_file(self.earth_path_bind)) # Action Buttons self.actionSettings.triggered.connect( lambda: self.open_parameters_settings()) self.plotBtn.clicked.connect(self.plot_seismograms) self.actionSettings.triggered.connect( lambda: self.open_parameters_settings()) self.actionWrite.triggered.connect(self.write) self.actionEarth_Model.triggered.connect( lambda: self.open_earth_model()) self.actionFrom_File.triggered.connect( lambda: self.load_event_from_isolapath()) self.actionOpen_Help.triggered.connect(lambda: self.open_help()) self.stationsBtn.clicked.connect(self.stationsInfo) self.run_inversionBtn.clicked.connect(lambda: self.run_inversion()) self.stations_mapBtn.clicked.connect(lambda: self.plot_map_stations()) self.plot_solutionBtn.clicked.connect(lambda: self.plot_solution()) #self.earthmodelBtn.clicked.connect(self.read_earth_model) # Parameters settings self.parameters = ParametersSettings() self.earth_model = CrustalModelParametersFrame() # help Documentation self.help = HelpDoc() def open_parameters_settings(self): self.parameters.show() def open_earth_model(self): self.earth_model.show() 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)) 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 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): file_path = pw.QFileDialog.getOpenFileName(self, 'Select Directory', bind.value) file_path = file_path[0] if file_path: bind.value = file_path 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 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 read_earth_model(self): # model = self.earth_model.getParametersWithFormat() # print(model) def plot_seismograms(self): parameters = self.get_inversion_parameters() lat = float(parameters['latitude']) lon = float(parameters['longitude']) starttime = convert_qdatetime_utcdatetime(self.starttime_date) endtime = convert_qdatetime_utcdatetime(self.endtime_date) diff = endtime - starttime parameters = self.parameters.getParameters() all_traces = [] obsfiles = MseedUtil.get_mseed_files(self.root_path_bind.value) obsfiles.sort() for file in obsfiles: 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) all_traces.append(tr) self.st = Stream(traces=all_traces) self.stream_frame = MatplotlibFrame(self.st, type='normal') self.stream_frame.show() if self.st: min_dist = self.min_distCB.value() max_dist = self.max_distCB.value() mt = MTIManager(self.st, self.inventory, lat, lon, min_dist, max_dist) [self.stream, self.deltas, self.stations_isola_path] = mt.get_stations_index() def stationsInfo(self): file_path = self.root_path_bind.value 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=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 not dir_path: return n = len(self.st) for j in range(n): tr = self.st[j] print(tr.id, "Writing data processed") path_output = os.path.join(dir_path, tr.id) tr.write(path_output, format="MSEED") ##In progress## def load_event_from_isolapath(self): root_path = os.path.dirname(os.path.abspath(__file__)) file_path = pw.QFileDialog.getOpenFileName(self, 'Select Directory', root_path) file = file_path[0] frame = pd.read_csv(file, sep='\s+', header=None) time = frame.iloc[3][0] year = time[0:4] mm = time[4:6] dd = time[6:8] hour = frame.iloc[4][0] minute = frame.iloc[5][0] sec = frame.iloc[6][0] sec = float(sec) dec = sec - int(sec) dec = int(sec) time = UTCDateTime(int(year), int(mm), int(dd), int(hour), int(minute), int(sec), dec) event = { 'lat': frame.iloc[0][0], 'lon': frame.iloc[0][1], 'depth': frame.iloc[1][0], 'mag': frame.iloc[2][0], 'time': time, 'istitution': frame.iloc[7][0] } return event @AsycTime.run_async() def run_inversion(self): parameters = self.get_inversion_parameters() try: stations_map = self._stations_info.get_stations_map() except: md = MessageDialog(self) md.set_info_message("Press Stations info and check your selection") if len(self.stream) and len(stations_map) > 0: isola = ISOLA(self.stream, self.deltas, location_unc=parameters['location_unc'], depth_unc=parameters['depth_unc'], time_unc=parameters['time_unc'], deviatoric=parameters['deviatoric'], threads=8, circle_shape=parameters['circle_shape'], use_precalculated_Green=parameters['GFs']) # isola.set_event_info(parameters['latitude'], parameters['longitude'], parameters['depth'], parameters['magnitude'], parameters['origin_time']) # print(isola.event) # # if self.stations_isola_path: isola.read_network_coordinates(self.stations_isola_path) isola.set_use_components(stations_map) #print(isola.stations) isola.read_crust(self.earth_path_bind.value) isola.set_parameters(parameters['freq_max'], parameters['freq_min']) self.infoTx.setPlainText("Calculated GFs") if not isola.calculate_or_verify_Green(): exit() self.infoTx.appendPlainText("Filtered and trim") isola.trim_filter_data() try: if parameters['covariance']: self.infoTx.appendPlainText( "Calculating Covariance Matrix") isola.covariance_matrix(crosscovariance=True, save_non_inverted=True, save_covariance_function=True) except: md = MessageDialog(self) md.set_error_message( "No Possible calculate covariance matrix, " "please try increasing the noise time window") # self.infoTx.appendPlainText("decimate and shift") isola.decimate_shift() self.infoTx.appendPlainText("Run inversion") isola.run_inversion() self.infoTx.appendPlainText("Finished Inversion") isola.find_best_grid_point() isola.print_solution() isola.print_fault_planes() self.infoTx.appendPlainText("Plotting Solutions") if len(isola.grid) > len(isola.depths): isola.plot_maps() self.infoTx.appendPlainText("plot_maps") if len(isola.depths) > 1: isola.plot_slices() self.infoTx.appendPlainText("plot_slices") if len(isola.grid) > len(isola.depths) and len( isola.depths) > 1: isola.plot_maps_sum() self.infoTx.appendPlainText("plot_maps_sum") try: isola.plot_MT() self.infoTx.appendPlainText("plot_MT") isola.plot_uncertainty(n=400) self.infoTx.appendPlainText("plot_uncertainty") #plot_MT_uncertainty_centroid() isola.plot_seismo('seismo.png') isola.plot_seismo('seismo_sharey.png', sharey=True) self.infoTx.appendPlainText("plot_seismo") if self.covarianceCB.isChecked(): isola.plot_seismo('plot_seismo.png', cholesky=True) self.infoTx.appendPlainText("plot_seismo_cova") isola.plot_noise() self.infoTx.appendPlainText("plot_noise") isola.plot_spectra() self.infoTx.appendPlainText("plot_spectra") isola.plot_stations() self.infoTx.appendPlainText("plot_stations") except: print("Couldn't Plot") try: if self.covarianceCB.isChecked(): isola.plot_covariance_matrix(colorbar=True) #isola.plot_3D() except: pass try: isola.html_log( h1='ISP Moment Tensor inversion', plot_MT='centroid.png', plot_uncertainty='uncertainty.png', plot_stations='stations.png', plot_seismo_cova='seismo_cova.png', plot_seismo_sharey='seismo_sharey.png', plot_spectra='spectra.png', plot_noise='noise.png', plot_covariance_matrix='covariance_matrix.png', plot_maps='map.png', plot_slices='slice.png', plot_maps_sum='map_sum.png') except: self.infoTx.appendPlainText("Couldn't load url") try: isola.html_log(h1='ISP Moment Tensor inversion', plot_MT='centroid.png', plot_uncertainty='uncertainty.png', plot_stations='stations.png', plot_seismo_sharey='seismo_sharey.png', plot_maps='map.png', plot_slices='slice.png') except: self.infoTx.appendPlainText("Couldn't load url") self.infoTx.appendPlainText( "Moment Tensor Inversion Successfully done !!!, please plot last solution" ) else: pass def plot_solution(self): path = os.path.join(ROOT_DIR, 'mti/output/index.html') url = pyc.QUrl.fromLocalFile(path) self.widget.load(url) def get_inversion_parameters(self): parameters = { 'latitude': self.latDB.value(), 'longitude': self.lonDB.value(), 'depth': self.depthDB.value(), 'origin_time': convert_qdatetime_utcdatetime(self.origin_time), 'location_unc': self.location_uncDB.value(), 'time_unc': self.timeDB.value(), 'magnitude': self.magnitudeDB.value(), 'depth_unc': self.depth_uncDB.value(), 'freq_min': self.freq_min_DB.value(), 'freq_max': self.freq_max_DB.value(), 'deviatoric': self.deviatoricCB.isChecked(), 'circle_shape': self.circle_shapeCB.isChecked(), 'GFs': self.gfCB.isChecked(), 'covariance': self.covarianceCB.isChecked() } return parameters def plot_map_stations(self): md = MessageDialog(self) md.hide() try: stations = [] obsfiles = MseedUtil.get_mseed_files(self.root_path_bind.value) obsfiles.sort() try: if len(self.stream) > 0: stations = ObspyUtil.get_stations_from_stream(self.stream) except: pass map_dict = {} sd = [] for file in obsfiles: if len(stations) == 0: st = SeismogramDataAdvanced(file) name = st.stats.Network + "." + st.stats.Station sd.append(name) st_coordinates = self.__metadata_manager.extract_coordinates( self.inventory, file) map_dict[name] = [ st_coordinates.Latitude, st_coordinates.Longitude ] else: st = SeismogramDataAdvanced(file) if st.stats.Station in stations: name = st.stats.Network + "." + st.stats.Station sd.append(name) st_coordinates = self.__metadata_manager.extract_coordinates( self.inventory, file) map_dict[name] = [ st_coordinates.Latitude, st_coordinates.Longitude ] else: pass self.map_stations = StationsMap(map_dict) self.map_stations.plot_stations_map(latitude=self.latDB.value(), longitude=self.lonDB.value()) md.set_info_message("Station Map OK !!! ") except: md.set_error_message( " Please check you have process and plot seismograms and opened stations info," "Please additionally check that your metada fits with your mseed files" ) md.show() def open_help(self): self.help.show()
class PDFmanger: def __init__(self, scatter_x, scatter_y, scatter_z, pdf): """ Plot stations map fro dictionary (key = stations name, coordinates) :param """ self.x = scatter_x self.y = scatter_y self.z = scatter_z self.pdf = pdf def plot_scatter(self): from isp.Gui.Frames import MatplotlibFrame print("Plotting PDF") pdf = np.array(self.pdf) / np.max(self.pdf) left, width = 0.06, 0.65 bottom, height = 0.1, 0.65 spacing = 0.02 rect_scatter = [left, bottom, width, height] rect_scatterlon = [left, bottom + height + spacing, width, 0.2] rect_scatterlat = [left + width + spacing, bottom, 0.2, height] fig = plt.figure(figsize=(10, 8)) self.mpf = MatplotlibFrame(fig) ax_scatter = plt.axes(rect_scatter) ax_scatter.tick_params(direction='in', top=True, right=True, labelsize=10) plt.scatter(self.x, self.y, s=10, c=pdf, alpha=0.5, marker=".", cmap=plt.cm.jet) plt.xlabel("Longitude", fontsize=10) plt.ylabel("Latitude", fontsize=10) ax_scatx = plt.axes(rect_scatterlon) ax_scatx.tick_params(direction='in', labelbottom=False, labelsize=10) plt.scatter(self.x, self.z, s=10, c=pdf, alpha=0.5, marker=".", cmap=plt.cm.jet) plt.ylabel("Depth (km)", fontsize=10) plt.gca().invert_yaxis() ax_scatx = plt.axes(rect_scatterlat) ax_scatx.tick_params(direction='in', labelleft=False, labelsize=10) ax_scaty = plt.axes(rect_scatterlat) ax_scaty.tick_params(direction='in') ax_scaty.tick_params(which='major', labelsize=10) plt.scatter(self.z, self.y, s=10, c=pdf, alpha=0.5, marker=".", cmap=plt.cm.jet) ax_scaty = plt.axes(rect_scatterlat) ax_scaty.tick_params(direction='in', labelsize=10) plt.xlabel("Depth (km)", fontsize=10) cax = plt.axes([0.95, 0.1, 0.02, 0.8]) plt.colorbar(cax=cax) self.mpf.show()
progname = os.path.basename(sys.argv[0]) progversion = "0.1" qApp = QtWidgets.QApplication(sys.argv) def on_select(ax_index, xmin, xmax): mpf.canvas.plot(xmax, 2, ax_index, clear_plot=False, marker="o") mpf.canvas.draw() def on_click(event, canvas): print(event, canvas) def on_dlb_click(event, canvas): print(event, canvas) mpf = MatplotlibFrame(None) mpf.canvas.set_new_subplot(2, 1) mpf.canvas.on_double_click(on_dlb_click) mpf.canvas.register_on_select(on_select) mpf.canvas.plot([1, 2, 3], [1, 2, 3], 0) mpf.canvas.plot([1, 2, 3], [1, 2, 3], 1) mpf.setWindowTitle("%s" % progname) mpf.show() sys.exit(qApp.exec_())
class StationsMap: def __init__(self, stations_dict): """ Plot stations map fro dictionary (key = stations name, coordinates) :param """ self.__stations_dict = stations_dict def plot_stations_map(self, **kwargs): from matplotlib.transforms import offset_copy import cartopy.crs as ccrs from cartopy.mpl.gridliner import LONGITUDE_FORMATTER, LATITUDE_FORMATTER from owslib.wms import WebMapService from matplotlib.patheffects import Stroke import cartopy.feature as cfeature import shapely.geometry as sgeom from matplotlib import pyplot as plt from isp import ROOT_DIR import os os.environ["CARTOPY_USER_BACKGROUNDS"] = os.path.join(ROOT_DIR, "maps") # MAP_SERVICE_URL = 'https://gis.ngdc.noaa.gov/arcgis/services/gebco08_hillshade/MapServer/WMSServer' MAP_SERVICE_URL = 'https://www.gebco.net/data_and_products/gebco_web_services/2020/mapserv?' # MAP_SERVICE_URL = 'https://gis.ngdc.noaa.gov/arcgis/services/etopo1/MapServer/WMSServer' geodetic = ccrs.Geodetic(globe=ccrs.Globe(datum='WGS84')) #layer = 'GEBCO_08 Hillshade' layer ='GEBCO_2020_Grid' #layer = 'shaded_relief' epi_lat = kwargs.pop('latitude') epi_lon = kwargs.pop('longitude') name_stations = [] lat = [] lon = [] for name, coords in self.__stations_dict.items(): name_stations.append(name) lat.append(float(coords[0])) lon.append(float(coords[1])) # proj = ccrs.PlateCarree() fig, ax = plt.subplots(1, 1, subplot_kw=dict(projection=proj), figsize=(16, 12)) self.mpf = MatplotlibFrame(fig) xmin = min(lon)-4 xmax = max(lon)+4 ymin = min(lat)-4 ymax = max(lat)+4 extent = [xmin, xmax, ymin, ymax] ax.set_extent(extent, crs=ccrs.PlateCarree()) try: wms = WebMapService(MAP_SERVICE_URL) ax.add_wms(wms, layer) except: ax.background_img(name='ne_shaded', resolution="high") #geodetic_transform = ccrs.Geodetic()._as_mpl_transform(ax) geodetic_transform = ccrs.PlateCarree()._as_mpl_transform(ax) text_transform = offset_copy(geodetic_transform, units='dots', x=-25) ax.scatter(lon, lat, s=12, marker="^", color='red', alpha=0.7, transform=ccrs.PlateCarree()) ax.plot(epi_lon, epi_lat, color='black', marker='*', markersize=8) N=len(name_stations) for n in range(N): lon1=lon[n] lat1 = lat[n] name = name_stations[n] ax.text(lon1, lat1, name, verticalalignment='center', horizontalalignment='right', transform=text_transform, bbox=dict(facecolor='sandybrown', alpha=0.5, boxstyle='round')) # Create an inset GeoAxes showing the Global location #sub_ax = self.mpf.canvas.figure.add_axes([0.70, 0.75, 0.28, 0.28], # projection=ccrs.PlateCarree()) sub_ax = self.mpf.canvas.figure.add_axes([0.70, 0.73, 0.28, 0.28], projection=ccrs.PlateCarree()) sub_ax.set_extent([-179.9, 180, -89.9, 90], geodetic) # Make a nice border around the inset axes. effect = Stroke(linewidth=4, foreground='wheat', alpha=0.5) sub_ax.outline_patch.set_path_effects([effect]) # Add the land, coastlines and the extent . sub_ax.add_feature(cfeature.LAND) sub_ax.coastlines() extent_box = sgeom.box(extent[0], extent[2], extent[1], extent[3]) sub_ax.add_geometries([extent_box], ccrs.PlateCarree(), facecolor='none', edgecolor='blue', linewidth=1.0) gl = ax.gridlines(crs=ccrs.PlateCarree(), draw_labels=True, linewidth=0.2, color='gray', alpha=0.2, linestyle='-') gl.top_labels = False gl.left_labels = False gl.xlines = False gl.ylines = False gl.xformatter = LONGITUDE_FORMATTER gl.yformatter = LATITUDE_FORMATTER #plt.savefig("/Users/robertocabieces/Documents/ISPshare/isp/mti/output/stations.png", bbox_inches='tight') self.mpf.show()
class PlotToolsManager: def __init__(self, id): """ Manage Plot signal analysis in Earthquake Frame. :param obs_file_path: The file path of pick observations. """ self.__id = id def plot_spectrum(self, freq, spec, jackknife_errors): import matplotlib.pyplot as plt from isp.Gui.Frames import MatplotlibFrame fig, ax1 = plt.subplots(figsize=(6, 6)) self.mpf = MatplotlibFrame(fig) ax1.loglog(freq, spec, linewidth=1.0, color='steelblue', label=self.__id) ax1.frequencies = freq ax1.spectrum = spec ax1.fill_between(freq, jackknife_errors[:, 0], jackknife_errors[:, 1], facecolor="0.75", alpha=0.5, edgecolor="0.5") ax1.set_ylim(spec.min() / 10.0, spec.max() * 100.0) plt.ylabel('Amplitude') plt.xlabel('Frequency [Hz]') plt.grid(True, which="both", ls="-", color='grey') plt.legend() self.mpf.show() def plot_spectrum_all(self, all_items): import matplotlib.pyplot as plt from isp.Gui.Frames import MatplotlibFrame fig, ax1 = plt.subplots(figsize=(6, 6)) self.mpf = MatplotlibFrame(fig) for key, seismogram in all_items: data = seismogram[2] delta = 1 / seismogram[0][6] sta = seismogram[0][1] [spec, freq, jackknife_errors] = spectrumelement(data, delta, sta) info = "{}.{}.{}".format(seismogram[0][0], seismogram[0][1], seismogram[0][3]) ax1.loglog(freq, spec, linewidth=1.0, alpha = 0.5, label=info) ax1.frequencies = freq ax1.spectrum = spec ax1.set_ylim(spec.min() / 10.0, spec.max() * 100.0) # ax1.set_xlim(freq[0], 1/(2*delta)) plt.ylabel('Amplitude') plt.xlabel('Frequency [Hz]') plt.grid(True, which="both", ls="-", color='grey') plt.legend() self.mpf.show() def find_nearest(self,array, value): idx, val = min(enumerate(array), key=lambda x: abs(x[1] - value)) return idx, val # def __compute_spectrogram(self, tr): # npts = len(tr) # t = np.linspace(0, (tr.stats.delta * npts), npts - self.win) # mt_spectrum = self.MTspectrum(tr.data, self.win, tr.stats.delta, self.tbp, self.ntapers, self.f_min, self.f_max) # log_spectrogram = 10. * np.log(mt_spectrum / np.max(mt_spectrum)) # x, y = np.meshgrid(t, np.linspace(self.f_min, self.f_max, log_spectrogram.shape[0])) # return x, y, log_spectrogram def MTspectrum_plot(self, data, win, dt, tbp, ntapers, linf, lsup): if (win % 2) == 0: nfft = win / 2 + 1 else: nfft = (win + 1) / 2 lim = len(data) - win S = np.zeros([int(nfft), int(lim)]) data2 = np.zeros(2 ** math.ceil(math.log2(win))) for n in range(lim): data1 = data[n:win + n] data1 = data1 - np.mean(data1) data2[0:win] = data1 spec, freq = mtspec(data2, delta=dt, time_bandwidth=tbp, number_of_tapers=ntapers) spec = spec[0:int(nfft)] S[:, n] = spec value1, freq1 = self.find_nearest(freq, linf) value2, freq2 = self.find_nearest(freq, lsup) S = S[value1:value2] return S def compute_spectrogram_plot(self, data, win, delta, tbp, ntapers, f_min, f_max, t): npts = len(data) x = np.linspace(0, (delta * npts), npts - win) t = t[0:len(x)] mt_spectrum = self.MTspectrum_plot(data, win, delta, tbp, ntapers, f_min, f_max) log_spectrogram = 10. * np.log(mt_spectrum / np.max(mt_spectrum)) x, y = np.meshgrid(t, np.linspace(f_min, f_max, log_spectrogram.shape[0])) return x, y, log_spectrogram