def test_adjoint_time_frequency_phase_misfit_source_plot(tmpdir): """ Tests the plot for a time-frequency misfit adjoint source. """ obs, syn = obspy.read(os.path.join(data_dir, "adj_src_test.mseed")).traces import matplotlib.pyplot as plt plt.figure(figsize=(15, 10)) ad_src_tf_phase_misfit.adsrc_tf_phase_misfit(obs.times(), obs.data, syn.data, 20.0, 100.0, plot=True) # High tolerance as fonts are for some reason shifted on some systems. # This should still be safe as a differnce in the actual tf difference # or the waveforms would induce changes all over the plot which would # make the rms error much larger. images_are_identical("tf_adjoint_source", str(tmpdir), tol=30)
def test_adjoint_time_frequency_phase_misfit_source(self): """ Tests the adjoint source calculation for the time frequency phase misfit after Fichtner et. al. (2008). """ # Load the matlab output. ad_src_matlab = os.path.join( self.data_dir, "matlab_tf_phase_misfit_adjoint_source_reference_solution.mat") ad_src_matlab = loadmat(ad_src_matlab)["ad_src"].transpose()[0] # Generate some data. t, u = utils.get_dispersed_wavetrain() _, u0 = utils.get_dispersed_wavetrain(a=3.91, b=0.87, c=0.8, body_wave_factor=0.015, body_wave_freq_scale=1.0 / 2.2) adjoint_src = ad_src_tf_phase_misfit.adsrc_tf_phase_misfit( t, u, u0, 2, 10, 0.0) ad_src = adjoint_src["adjoint_source"] # Assert the misfit. self.assertAlmostEqual(adjoint_src["misfit"], 0.271417, 5) # Some testing tolerance is needed mainly due to the phase being hard # to define for small amplitudes. tolerance = np.abs(ad_src).max() * 1.2E-3 np.testing.assert_allclose(ad_src, ad_src_matlab, 1E-7, tolerance)
def test_adjoint_time_frequency_phase_misfit_source(): """ Tests the adjoint source calculation for the time frequency phase misfit after Fichtner et. al. (2008). XXX: Adjust the test. """ # Load the matlab output. ad_src_matlab = os.path.join( data_dir, "matlab_tf_phase_misfit_adjoint_source_reference_solution.mat") ad_src_matlab = loadmat(ad_src_matlab)["ad_src"].transpose()[0] # Generate some data. t, u = utils.get_dispersed_wavetrain() _, u0 = utils.get_dispersed_wavetrain( a=3.91, b=0.87, c=0.8, body_wave_factor=0.015, body_wave_freq_scale=1.0 / 2.2) adjoint_src = ad_src_tf_phase_misfit.adsrc_tf_phase_misfit( t, u, u0, 2, 10, 0.0) ad_src = adjoint_src["adjoint_source"] # Assert the misfit. np.testing.assert_almost_equal(adjoint_src["misfit"], 0.271417, 5) # Some testing tolerance is needed mainly due to the phase being hard # to define for small amplitudes. tolerance = np.abs(ad_src).max() * 1.2E-3 np.testing.assert_allclose(ad_src, ad_src_matlab, 1E-7, tolerance)
def adjoint_src_for_window( data, synth, starttime, endtime, weight, process_parameters, output_window_manager, output_adjoint_source_manager, write_data=True, ): if write_data: output_window_manager.write_window( data.id, starttime, endtime, weight, "cosine", "TimeFrequencyPhaseMisfitFichtner2008" ) # Decimal percentage of cosine taper (ranging from 0 to 1). Set to the # fraction of the minimum period to the window length. taper_percentage = np.min([1.0, 1.0 / process_parameters["lowpass"] / (endtime - starttime)]) # data data_trimmed = data.copy() data_trimmed.trim(starttime, endtime) data_trimmed.taper(type="cosine", max_percentage=0.5 * taper_percentage) data_trimmed.trim(synth.stats.starttime, synth.stats.endtime, pad=True, fill_value=0.0) # synthetics synth_trimmed = synth.copy() synth_trimmed.trim(starttime, endtime) synth_trimmed.taper(type="cosine", max_percentage=0.5 * taper_percentage) synth_trimmed.trim(synth.stats.starttime, synth.stats.endtime, pad=True, fill_value=0.0) # make time axis t = np.linspace(0, synth.stats.npts * synth.stats.delta, synth.stats.npts) # clear axes of misfit plot ------------------------------------------ # set data and synthetics, compute actual misfit --------------------- t = np.require(t, dtype="float64", requirements="C") data_d = np.require(data_trimmed.data, dtype="float64", requirements="C") synth_d = np.require(synth_trimmed.data, dtype="float64", requirements="C") # compute misfit and adjoint source adsrc = adsrc_tf_phase_misfit( t, data_d, synth_d, 1.0 / process_parameters["lowpass"], 1.0 / process_parameters["highpass"], axis=None, colorbar_axis=None, ) # write adjoint source to file --------------------------------------- if write_data: output_adjoint_source_manager.write_adjoint_src(adsrc["adjoint_source"], data.id, starttime, endtime) return adsrc
def test_adjoint_time_frequency_phase_misfit_source_plot(tmpdir): """ Tests the plot for a time-frequency misfit adjoint source. """ obs, syn = obspy.read(os.path.join(data_dir, "adj_src_test.mseed")).traces import matplotlib.pyplot as plt plt.figure(figsize=(15, 10)) ad_src_tf_phase_misfit.adsrc_tf_phase_misfit(obs.times(), obs.data, syn.data, 20.0, 100.0, plot=True) # High tolerance as fonts are for some reason shifted on some systems. # This should still be safe as a differnce in the actual tf difference # or the waveforms would induce changes all over the plot which would # make the rms error much larger. images_are_identical("tf_adjoint_source", str(tmpdir), tol=30)
def test_time_frequency_adjoint_source(): """ Test the time frequency misfit and adjoint source. """ obs, syn = obspy.read(os.path.join(data_dir, "adj_src_test.mseed")).traces ret_val = ad_src_tf_phase_misfit.adsrc_tf_phase_misfit(obs.times(), obs.data, syn.data, 20.0, 100.0) assert round(ret_val["misfit_value"], 4) == 0.7147 assert not ret_val["details"]["messages"] adj_src_baseline = np.load(os.path.join(data_dir, "adjoint_source_baseline.npy")) np.testing.assert_allclose( actual=ret_val["adjoint_source"], desired=adj_src_baseline, atol=1e-5 * abs(adj_src_baseline).max(), rtol=1e-5 )
def test_time_frequency_adjoint_source(): """ Test the time frequency misfit and adjoint source. """ obs, syn = obspy.read(os.path.join(data_dir, "adj_src_test.mseed")).traces ret_val = ad_src_tf_phase_misfit.adsrc_tf_phase_misfit( obs.times(), obs.data, syn.data, 20.0, 100.0) assert round(ret_val["misfit_value"], 4) == 0.7147 assert not ret_val["details"]["messages"] adj_src_baseline = np.load( os.path.join(data_dir, "adjoint_source_baseline.npy")) np.testing.assert_allclose(actual=ret_val["adjoint_source"], desired=adj_src_baseline, atol=1E-5 * abs(adj_src_baseline).max(), rtol=1E-5)
def _onWindowSelected(self, window_start, window_width, axis, plot_only=False): """ Function called upon window selection. :param plot_only: If True, do not write anything to disk, but only plot. """ # Initialisation ----------------------------------------------------- # Minimum window length is 50 samples. delta = self.data["synthetics"][0].stats.delta if window_width < 50 * delta: plt.draw() return data = self.data["data"].select(component=axis.seismic_component)[0] synth = self.data["synthetics"].select( channel=axis.seismic_component)[0] if not data: plt.draw() return trace = data time_range = trace.stats.endtime - trace.stats.starttime plot_range = axis.get_xlim()[1] - axis.get_xlim()[0] starttime = trace.stats.starttime + (window_start / plot_range) * \ time_range endtime = starttime + window_width / plot_range * time_range if plot_only is not True: self.window_manager.write_window( trace.id, starttime, endtime, self.weight, "cosine", "TimeFrequencyPhaseMisfitFichtner2008") self.plot_window(component=trace.id[-1], starttime=starttime, endtime=endtime, window_weight=self.weight) # window data and synthetics ----------------------------------------- # Decimal percentage of cosine taper (ranging from 0 to 1). Set to the # fraction of the minimum period to the window length. taper_percentage = np.min( [1.0, 1.0 / self. process_parameters["lowpass"] / window_width]) # data data_trimmed = data.copy() data_trimmed.trim(starttime, endtime) data_trimmed.taper(type='cosine', max_percentage=0.5 * taper_percentage) data_trimmed.trim(synth.stats.starttime, synth.stats.endtime, pad=True, fill_value=0.0) # synthetics synth_trimmed = synth.copy() synth_trimmed.trim(starttime, endtime) synth_trimmed.taper(type='cosine', max_percentage=0.5 * taper_percentage) synth_trimmed.trim(synth.stats.starttime, synth.stats.endtime, pad=True, fill_value=0.0) # make time axis t = np.linspace(0, synth.stats.npts * synth.stats.delta, synth.stats.npts) # clear axes of misfit plot ------------------------------------------ self.misfit_axis.cla() self.colorbar_axis.cla() try: self.misfit_axis.twin_axis.cla() self.misfit_axis.twin_axis.set_xticks([]) self.misfit_axis.twin_axis.set_yticks([]) except: pass # set data and synthetics, compute actual misfit --------------------- t = np.require(t, dtype="float64", requirements="C") data_d = np.require(data_trimmed.data, dtype="float64", requirements="C") synth_d = np.require(synth_trimmed.data, dtype="float64", requirements="C") # compute misfit and adjoint source adsrc = adsrc_tf_phase_misfit( t, data_d, synth_d, 1.0 / self.process_parameters["lowpass"], 1.0 / self.process_parameters["highpass"], axis=self.misfit_axis, colorbar_axis=self.colorbar_axis) # plot misfit distribution ------------------------------------------- # Format all the axis. self.misfit_axis.yaxis.set_major_formatter(FormatStrFormatter("%.3f")) self.misfit_axis.twin_axis.yaxis.set_major_formatter( FormatStrFormatter("%.2g")) self.colorbar_axis.yaxis.set_major_formatter( FormatStrFormatter("%.1f")) plt.tight_layout() plt.draw() # write adjoint source to file --------------------------------------- if plot_only is not True: self.adjoint_source_manager.write_adjoint_src( adsrc["adjoint_source"], trace.id, starttime, endtime)
def _onWindowSelected(self, window_start, window_width, axis): """ Function called upon window selection. """ if window_width <= 0: return if axis is self.plot_axis_z: data = self.data["data"].select(component="Z")[0] synth = self.data["synthetics"].select(component="Z")[0] elif axis is self.plot_axis_n: data = self.data["data"].select(component="N")[0] synth = self.data["synthetics"].select(component="N")[0] elif axis is self.plot_axis_e: data = self.data["data"].select(component="E")[0] synth = self.data["synthetics"].select(component="E")[0] else: return if not data: return trace = data time_range = trace.stats.endtime - trace.stats.starttime plot_range = axis.get_xlim()[1] - axis.get_xlim()[0] starttime = trace.stats.starttime + (window_start / plot_range) * \ time_range endtime = starttime + window_width / plot_range * time_range self.window_manager.write_window(trace.id, starttime, endtime, 1.0, "cosine", "TimeFrequencyPhaseMisfitFichtner2008") # Window the data. data_trimmed = data.copy() data_trimmed.trim(starttime, endtime) data_trimmed.taper() data_trimmed.trim(synth.stats.starttime, synth.stats.endtime, pad=True, fill_value=0.0) synth_trimmed = synth.copy() synth_trimmed.trim(starttime, endtime) synth_trimmed.taper() synth_trimmed.trim(synth.stats.starttime, synth.stats.endtime, pad=True, fill_value=0.0) t = np.linspace(0, synth.stats.npts * synth.stats.delta, synth.stats.npts) self.misfit_axis.cla() self.colorbar_axis.cla() try: self.misfit_axis.twin_axis.cla() self.misfit_axis.twin_axis.set_xticks([]) self.misfit_axis.twin_axis.set_yticks([]) except: pass t = np.require(t, dtype="float64", requirements="C") data_d = np.require(data_trimmed.data, dtype="float64", requirements="C") synth_d = np.require(synth_trimmed.data, dtype="float64", requirements="C") adsrc = adsrc_tf_phase_misfit(t, data_d, synth_d, 5.0, 50.0, 0.00000001, axis=self.misfit_axis, colorbar_axis=self.colorbar_axis) plt.tight_layout() plt.draw()
def _onWindowSelected(self, window_start, window_width, axis): """ Function called upon window selection. """ if window_width <= 0: return if axis is self.plot_axis_z: data = self.data["data"].select(component="Z")[0] synth = self.data["synthetics"].select(component="Z")[0] elif axis is self.plot_axis_n: data = self.data["data"].select(component="N")[0] synth = self.data["synthetics"].select(component="N")[0] elif axis is self.plot_axis_e: data = self.data["data"].select(component="E")[0] synth = self.data["synthetics"].select(component="E")[0] else: return if not data: return trace = data time_range = trace.stats.endtime - trace.stats.starttime plot_range = axis.get_xlim()[1] - axis.get_xlim()[0] starttime = trace.stats.starttime + (window_start / plot_range) * \ time_range endtime = starttime + window_width / plot_range * time_range self.window_manager.write_window( trace.id, starttime, endtime, 1.0, "cosine", "TimeFrequencyPhaseMisfitFichtner2008") # Window the data. data_trimmed = data.copy() data_trimmed.trim(starttime, endtime) data_trimmed.taper() data_trimmed.trim(synth.stats.starttime, synth.stats.endtime, pad=True, fill_value=0.0) synth_trimmed = synth.copy() synth_trimmed.trim(starttime, endtime) synth_trimmed.taper() synth_trimmed.trim(synth.stats.starttime, synth.stats.endtime, pad=True, fill_value=0.0) t = np.linspace(0, synth.stats.npts * synth.stats.delta, synth.stats.npts) self.misfit_axis.cla() self.colorbar_axis.cla() try: self.misfit_axis.twin_axis.cla() self.misfit_axis.twin_axis.set_xticks([]) self.misfit_axis.twin_axis.set_yticks([]) except: pass t = np.require(t, dtype="float64", requirements="C") data_d = np.require(data_trimmed.data, dtype="float64", requirements="C") synth_d = np.require(synth_trimmed.data, dtype="float64", requirements="C") adsrc = adsrc_tf_phase_misfit(t, data_d, synth_d, 5.0, 50.0, 0.00000001, axis=self.misfit_axis, colorbar_axis=self.colorbar_axis) plt.tight_layout() plt.draw()