From 29107ee40c71743935e4cf4d7f92032ced3777bf Mon Sep 17 00:00:00 2001 From: Marcel Date: Mon, 26 Aug 2024 17:18:41 +0200 Subject: [PATCH] [update] WIP: adding tests for autopylot (global) --- pylot/tests/__init__.py | 0 .../tests/test_pick_correlation_correction.py | 76 ------------- ...lot_alparray_mantle_corr_stack_0.03-0.5.in | 101 ++++++++++++++++++ tests/test_autopicker/test_autopylot.py | 27 +++++ 4 files changed, 128 insertions(+), 76 deletions(-) delete mode 100644 pylot/tests/__init__.py delete mode 100644 pylot/tests/test_pick_correlation_correction.py create mode 100644 tests/test_autopicker/pylot_alparray_mantle_corr_stack_0.03-0.5.in create mode 100644 tests/test_autopicker/test_autopylot.py diff --git a/pylot/tests/__init__.py b/pylot/tests/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/pylot/tests/test_pick_correlation_correction.py b/pylot/tests/test_pick_correlation_correction.py deleted file mode 100644 index fb9311e5..00000000 --- a/pylot/tests/test_pick_correlation_correction.py +++ /dev/null @@ -1,76 +0,0 @@ -import pytest -from obspy import read, Trace, UTCDateTime - -from pylot.correlation.pick_correlation_correction import XCorrPickCorrection - - -class TestXCorrPickCorrection(): - def setup(self): - self.make_test_traces() - self.make_test_picks() - self.t_before = 2. - self.t_after = 2. - self.cc_maxlag = 0.5 - - def make_test_traces(self): - # take first trace of test Stream from obspy - tr1 = read()[0] - # filter trace - tr1.filter('bandpass', freqmin=1, freqmax=20) - # make a copy and shift the copy by 0.1 s - tr2 = tr1.copy() - tr2.stats.starttime += 0.1 - - self.trace1 = tr1 - self.trace2 = tr2 - - def make_test_picks(self): - # create an artificial reference pick on reference trace (trace1) and another one on the 0.1 s shifted trace - self.tpick1 = UTCDateTime('2009-08-24T00:20:07.7') - # shift the second pick by 0.2 s, the correction should be around 0.1 s now - self.tpick2 = self.tpick1 + 0.2 - - def test_slice_trace_okay(self): - - self.setup() - xcpc = XCorrPickCorrection(UTCDateTime(), Trace(), UTCDateTime(), Trace(), - t_before=self.t_before, t_after=self.t_after, cc_maxlag=self.cc_maxlag) - - test_trace = self.trace1 - pick_time = self.tpick2 - - sliced_trace = xcpc.slice_trace(test_trace, pick_time) - assert ((sliced_trace.stats.starttime == pick_time - self.t_before - self.cc_maxlag / 2) - and (sliced_trace.stats.endtime == pick_time + self.t_after + self.cc_maxlag / 2)) - - def test_slice_trace_fails(self): - self.setup() - - test_trace = self.trace1 - pick_time = self.tpick1 - - with pytest.raises(ValueError): - xcpc = XCorrPickCorrection(UTCDateTime(), Trace(), UTCDateTime(), Trace(), - t_before=self.t_before + 20, t_after=self.t_after, cc_maxlag=self.cc_maxlag) - xcpc.slice_trace(test_trace, pick_time) - - with pytest.raises(ValueError): - xcpc = XCorrPickCorrection(UTCDateTime(), Trace(), UTCDateTime(), Trace(), - t_before=self.t_before, t_after=self.t_after + 50, cc_maxlag=self.cc_maxlag) - xcpc.slice_trace(test_trace, pick_time) - - def test_cross_correlation(self): - self.setup() - - # create XCorrPickCorrection object - xcpc = XCorrPickCorrection(self.tpick1, self.trace1, self.tpick2, self.trace2, t_before=self.t_before, - t_after=self.t_after, cc_maxlag=self.cc_maxlag) - - # execute correlation - correction, cc_max, uncert, fwfm = xcpc.cross_correlation(False, '', '') - - # define awaited test result - test_result = (-0.09983091718314982, 0.9578431835689154, 0.0015285160561610929, 0.03625786256084631) - - # check results - assert pytest.approx(test_result, rel=1e-6) == (correction, cc_max, uncert, fwfm) \ No newline at end of file diff --git a/tests/test_autopicker/pylot_alparray_mantle_corr_stack_0.03-0.5.in b/tests/test_autopicker/pylot_alparray_mantle_corr_stack_0.03-0.5.in new file mode 100644 index 00000000..d3dcd918 --- /dev/null +++ b/tests/test_autopicker/pylot_alparray_mantle_corr_stack_0.03-0.5.in @@ -0,0 +1,101 @@ +%This is a parameter input file for PyLoT/autoPyLoT. +%All main and special settings regarding data handling +%and picking are to be set here! +%Parameters are optimized for %extent data sets! +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +#main settings# + #rootpath# %project path + #datapath# %data path + #database# %name of data base +20171010_063224.a #eventID# %event ID for single event processing (* for all events found in database) + #invdir# %full path to inventory or dataless-seed file +PILOT #datastructure# %choose data structure +True #apverbose# %choose 'True' or 'False' for terminal output +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +#NLLoc settings# +None #nllocbin# %path to NLLoc executable +None #nllocroot# %root of NLLoc-processing directory +None #phasefile# %name of autoPyLoT-output phase file for NLLoc +None #ctrfile# %name of autoPyLoT-output control file for NLLoc +ttime #ttpatter# %pattern of NLLoc ttimes from grid +AUTOLOC_nlloc #outpatter# %pattern of NLLoc-output file +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +#parameters for seismic moment estimation# +3530.0 #vp# %average P-wave velocity +2500.0 #rho# %average rock density [kg/m^3] +300.0 0.8 #Qp# %quality factor for P waves (Qp*f^a); list(Qp, a) +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +#settings local magnitude# +1.0 1.0 1.0 #WAscaling# %Scaling relation (log(Ao)+Alog(r)+Br+C) of Wood-Anderson amplitude Ao [nm] If zeros are set, original Richter magnitude is calculated! +1.0 1.0 #magscaling# %Scaling relation for derived local magnitude [a*Ml+b]. If zeros are set, no scaling of network magnitude is applied! +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +#filter settings# +0.03 0.03 #minfreq# %Lower filter frequency [P, S] +0.5 0.5 #maxfreq# %Upper filter frequency [P, S] +4 4 #filter_order# %filter order [P, S] +bandpass bandpass #filter_type# %filter type (bandpass, bandstop, lowpass, highpass) [P, S] +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +#common settings picker# +global #extent# %extent of array ("local", "regional" or "global") +-100.0 #pstart# %start time [s] for calculating CF for P-picking (if TauPy: seconds relative to estimated onset) +50.0 #pstop# %end time [s] for calculating CF for P-picking (if TauPy: seconds relative to estimated onset) +-50.0 #sstart# %start time [s] relative to P-onset for calculating CF for S-picking +50.0 #sstop# %end time [s] after P-onset for calculating CF for S-picking +True #use_taup# %use estimated traveltimes from TauPy for calculating windows for CF +ak135 #taup_model# %Define TauPy model for traveltime estimation. Possible values: 1066a, 1066b, ak135, ak135f, herrin, iasp91, jb, prem, pwdk, sp6 +P,Pdiff,S,SKS #taup_phases# %Specify possible phases for TauPy (comma separated). See Obspy TauPy documentation for possible values. +0.03 0.5 #bpz1# %lower/upper corner freq. of first band pass filter Z-comp. [Hz] +0.01 0.5 #bpz2# %lower/upper corner freq. of second band pass filter Z-comp. [Hz] +0.03 0.5 #bph1# %lower/upper corner freq. of first band pass filter H-comp. [Hz] +0.01 0.5 #bph2# %lower/upper corner freq. of second band pass filter z-comp. [Hz] +#special settings for calculating CF# +%!!Edit the following only if you know what you are doing!!% +#Z-component# +HOS #algoP# %choose algorithm for P-onset determination (HOS, ARZ, or AR3) +300.0 #tlta# %for HOS-/AR-AIC-picker, length of LTA window [s] +4 #hosorder# %for HOS-picker, order of Higher Order Statistics +2 #Parorder# %for AR-picker, order of AR process of Z-component +16.0 #tdet1z# %for AR-picker, length of AR determination window [s] for Z-component, 1st pick +10.0 #tpred1z# %for AR-picker, length of AR prediction window [s] for Z-component, 1st pick +12.0 #tdet2z# %for AR-picker, length of AR determination window [s] for Z-component, 2nd pick +6.0 #tpred2z# %for AR-picker, length of AR prediction window [s] for Z-component, 2nd pick +0.001 #addnoise# %add noise to seismogram for stable AR prediction +60.0 5.0 20.0 12.0 #tsnrz# %for HOS/AR, window lengths for SNR-and slope estimation [tnoise, tsafetey, tsignal, tslope] [s] +50.0 #pickwinP# %for initial AIC pick, length of P-pick window [s] +30.0 #Precalcwin# %for HOS/AR, window length [s] for recalculation of CF (relative to 1st pick) +2.0 #aictsmooth# %for HOS/AR, take average of samples for smoothing of AIC-function [s] +2.0 #tsmoothP# %for HOS/AR, take average of samples in this time window for smoothing CF [s] +0.006 #ausP# %for HOS/AR, artificial uplift of samples (aus) of CF (P) +2.0 #nfacP# %for HOS/AR, noise factor for noise level determination (P) +#H-components# +ARH #algoS# %choose algorithm for S-onset determination (ARH or AR3) +12.0 #tdet1h# %for HOS/AR, length of AR-determination window [s], H-components, 1st pick +6.0 #tpred1h# %for HOS/AR, length of AR-prediction window [s], H-components, 1st pick +8.0 #tdet2h# %for HOS/AR, length of AR-determinaton window [s], H-components, 2nd pick +4.0 #tpred2h# %for HOS/AR, length of AR-prediction window [s], H-components, 2nd pick +4 #Sarorder# %for AR-picker, order of AR process of H-components +100.0 #Srecalcwin# %for AR-picker, window length [s] for recalculation of CF (2nd pick) (H) +195.0 #pickwinS# %for initial AIC pick, length of S-pick window [s] +60.0 10.0 30.0 12.0 #tsnrh# %for ARH/AR3, window lengths for SNR-and slope estimation [tnoise, tsafetey, tsignal, tslope] [s] +22.0 #aictsmoothS# %for AIC-picker, take average of samples in this time window for smoothing of AIC-function [s] +20.0 #tsmoothS# %for AR-picker, take average of samples for smoothing CF [s] (S) +0.001 #ausS# %for HOS/AR, artificial uplift of samples (aus) of CF (S) +2.0 #nfacS# %for AR-picker, noise factor for noise level determination (S) +#first-motion picker# +1 #minfmweight# %minimum required P weight for first-motion determination +3.0 #minFMSNR# %miniumum required SNR for first-motion determination +10.0 #fmpickwin# %pick window [s] around P onset for calculating zero crossings +#quality assessment# +0.1 0.2 0.4 0.8 #timeerrorsP# %discrete time errors [s] corresponding to picking weights [0 1 2 3] for P +4.0 8.0 16.0 32.0 #timeerrorsS# %discrete time errors [s] corresponding to picking weights [0 1 2 3] for S +0.005 #minAICPslope# %below this slope [counts/s] the initial P pick is rejected +1.1 #minAICPSNR# %below this SNR the initial P pick is rejected +0.002 #minAICSslope# %below this slope [counts/s] the initial S pick is rejected +1.3 #minAICSSNR# %below this SNR the initial S pick is rejected +20.0 #minsiglength# %length of signal part for which amplitudes must exceed noiselevel [s] +1.0 #noisefactor# %noiselevel*noisefactor=threshold +10.0 #minpercent# %required percentage of amplitudes exceeding threshold +0.1 #zfac# %P-amplitude must exceed at least zfac times RMS-S amplitude +100.0 #mdttolerance# %maximum allowed deviation of P picks from median [s] +50.0 #wdttolerance# %maximum allowed deviation from Wadati-diagram +25.0 #jackfactor# %pick is removed if the variance of the subgroup with the pick removed is larger than the mean variance of all subgroups times safety factor diff --git a/tests/test_autopicker/test_autopylot.py b/tests/test_autopicker/test_autopylot.py new file mode 100644 index 00000000..a5dd0af7 --- /dev/null +++ b/tests/test_autopicker/test_autopylot.py @@ -0,0 +1,27 @@ +import os +import pytest + +from autoPyLoT import autoPyLoT + + +class TestAutopickerGlobal(): + def init(self): + self.params_infile = 'pylot_alparray_mantle_corr_stack_0.03-0.5.in' + self.test_event_dir = 'dmt_database_test' + + if not os.path.isfile(self.params_infile): + print(f'Test input file {os.path.abspath(self.params_infile)} not found.') + return False + + if not os.path.exists(self.test_event_dir): + print( + f'Test event directory not found at location "{os.path.abspath(self.test_event_dir)}". ' + f'Make sure to load it from the website first.' + ) + return False + + return True + + def test_autopicker(self): + assert self.init(), 'Initialization failed due to missing input files.' + #autoPyLoT(inputfile=self.params_infile, eventid='20171010_063224.a')