def test_multi_detectors(self): """Test the efficient looping in subspace.""" templates = copy.deepcopy(self.templates) detector1 = subspace.Detector() detector1.construct(streams=templates, lowcut=2, highcut=9, filt_order=4, sampling_rate=20, multiplex=False, name=str('Tester1'), align=True, shift_len=6, reject=0.2).partition(4) templates = copy.deepcopy(self.templates) detector2 = subspace.Detector() detector2.construct(streams=templates[0:20], lowcut=2, highcut=9, filt_order=4, sampling_rate=20, multiplex=False, name=str('Tester2'), align=True, shift_len=6, reject=0.2).partition(4) detections = subspace.subspace_detect(detectors=[detector1, detector2], stream=self.st.copy(), threshold=0.7, trig_int=10, moveout=5, min_trig=5, parallel=False, num_cores=2) self.assertEqual(len(detections), 6) detections = subspace.subspace_detect(detectors=[detector1, detector2], stream=self.st.copy(), threshold=0.7, trig_int=10, moveout=5, min_trig=5, parallel=True, num_cores=2) self.assertEqual(len(detections), 6)
def test_refactor(self): """ Test subspace refactoring, checks that np.dot(U.T, U) is identity. """ templates = copy.deepcopy(self.templates) # Test a multiplexed version detector = subspace.Detector() detector.construct(streams=templates, lowcut=2, highcut=9, filt_order=4, sampling_rate=20, multiplex=True, name=str('Tester'), align=False, shift_len=None) for dim in range(2, len(detector.v[0])): detector.partition(dim) for u in detector.data: identity = np.dot(u.T, u).astype(np.float16) self.assertTrue(np.allclose( identity, np.diag(np.ones(len(identity), dtype=np.float16)))) # Test a non-multiplexed version detector = subspace.Detector() templates = copy.deepcopy(self.templates) detector.construct(streams=templates, lowcut=2, highcut=9, filt_order=4, sampling_rate=20, multiplex=False, name=str('Tester'), align=True, shift_len=0.2, reject=0.0) for dim in range(2, len(detector.v[0])): detector.partition(dim) for u in detector.data: identity = np.dot(u.T, u).astype(np.float16) self.assertTrue(np.allclose( identity, np.diag(np.ones(len(identity), dtype=np.float16))))
def test_write(self): """Test writing to an hdf5 file""" templates = copy.deepcopy(self.templates) # Test a multiplexed version detector = subspace.Detector() detector.construct(streams=templates, lowcut=2, highcut=9, filt_order=4, sampling_rate=20, multiplex=True, name=str('Tester'), align=True, shift_len=0.8, reject=0.2) detector.write('Test_file.h5') self.assertTrue(os.path.isfile('Test_file.h5')) os.remove('Test_file.h5') detector.construct(streams=templates, lowcut=2, highcut=9, filt_order=4, sampling_rate=20, multiplex=False, name=str('Tester'), align=True, shift_len=0.8, reject=0.2) detector.write('Test_file.h5') self.assertTrue(os.path.isfile('Test_file.h5')) os.remove('Test_file.h5')
def test_create_nonmultiplexed_unaligned(self): """Test creation of a non-multiplexed detector.""" # Test a non-multiplexed version detector = subspace.Detector() templates = copy.deepcopy(self.templates) templates = [template.select(station='TMWZ') for template in templates] detector.construct(streams=templates, lowcut=2, highcut=9, filt_order=4, sampling_rate=20, multiplex=False, name=str('Tester'), align=False, shift_len=0) for u in detector.data: identity = np.dot(u.T, u).astype(np.float16) self.assertTrue(np.allclose( identity, np.diag(np.ones(len(identity), dtype=np.float16)))) comparison_detector = subspace.read_detector( os.path.join( os.path.abspath(os.path.dirname(__file__)), 'test_data', 'subspace', 'master_detector_unaligned.h5')) for key in ['name', 'sampling_rate', 'multiplex', 'lowcut', 'highcut', 'filt_order', 'dimension', 'stachans']: # print(key) self.assertEqual(comparison_detector.__getattribute__(key), detector.__getattribute__(key)) for key in ['data', 'u', 'v', 'sigma']: # print(key) list_item = detector.__getattribute__(key) other_list = comparison_detector.__getattribute__(key) self.assertEqual(len(list_item), len(other_list)) for item, other_item in zip(list_item, other_list): if not np.allclose(np.abs(item), np.abs(other_item)): print(item) print(other_item) self.assertTrue(np.allclose(np.abs(item), np.abs(other_item), atol=0.001)) # Finally check that the __eq__ method works if all the above passes. self.assertEqual(detector, comparison_detector)
def test_read_func(self): """Check that the read function works too.""" path = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'test_data', 'Test_detector.h5') detector = subspace.read_detector(path) _detector = subspace.Detector() _detector.read(path) self.assertEqual(detector, _detector)
def partition_fail(self): templates = copy.deepcopy(self.templates) detector2 = subspace.Detector() with self.assertRaises(IndexError): detector2.construct(streams=templates[0:10], lowcut=2, highcut=9, filt_order=4, sampling_rate=20, multiplex=False, name=str('Tester'), align=True, shift_len=6, reject=0.2).partition(9)
def test_not_multiplexed(self): """Test that a non-multiplexed detector gets the same result.""" templates = copy.deepcopy(self.templates) detector = subspace.Detector() detector.construct(streams=templates, lowcut=2, highcut=9, filt_order=4, sampling_rate=20, multiplex=False, name=str('Tester'), align=True, shift_len=4, reject=0.3).partition(4) st = self.st detections = detector.detect(st=st, threshold=0.5, trig_int=4, debug=1, moveout=2, min_trig=5) self.assertEqual(len(detections), 16)
def test_read(self): """Test reading from hdf5 file""" detector = subspace.Detector() path = os.path.join(os.path.abspath(os.path.dirname(__file__)), 'test_data', 'Test_detector.h5') detector.read(path) self.assertEqual(detector.name, 'Tester') self.assertEqual(detector.multiplex, False) self.assertEqual(detector.lowcut, 2) self.assertEqual(detector.highcut, 9) self.assertEqual(detector.filt_order, 4) self.assertEqual(detector.dimension, 9) self.assertEqual(detector.sampling_rate, 20)
def setUpClass(cls): wavefiles = glob.glob(os.path.join( os.path.dirname(os.path.abspath(__file__)), 'test_data', 'WAV', 'TEST_', '*')) streams = [read(w) for w in wavefiles[1:10]] cls.stream_list = [] for st in streams: tr = st.select(station='GCSZ', channel='EHZ') tr = tr.detrend('simple').resample(100).filter( 'bandpass', freqmin=2, freqmax=8) cls.stream_list.append(tr) cls.detector = subspace.Detector().read(os.path.join( os.path.abspath(os.path.dirname(__file__)), '..', 'tests', 'test_data', 'subspace', 'stat_test_detector.h5'))
def test_detect(self): """Test standard detection with known result.""" templates = copy.deepcopy(self.templates) detector = subspace.Detector() detector.construct(streams=templates, lowcut=2, highcut=9, filt_order=4, sampling_rate=20, multiplex=True, name=str('Tester'), align=True, shift_len=4, reject=0.3, no_missed=False).partition(4) st = self.st detections = detector.detect(st=st, threshold=0.2, trig_int=4, debug=1) self.assertEqual(len(detections), 34)
def test_stat(self): """Test that the statistic calculation is the same regardless of system.""" detector = subspace.Detector() detector.read( os.path.join(os.path.abspath(os.path.dirname(__file__)), 'test_data', 'subspace', 'stat_test_detector.h5')) stream = read( os.path.join(os.path.abspath(os.path.dirname(__file__)), 'test_data', 'subspace', 'test_trace.ms')) tr_data = stream[0].data stat = subspace_statistic.det_statistic( detector.data[0].astype(np.float32), tr_data.astype(np.float32)) self.assertEqual((stat.max().round(6) - 0.252336).round(6), 0)
def test_stat(self): """Test that the statistic calculation is the same regardless of system.""" detector = subspace.Detector() detector.read(os.path.join(os.path.abspath(os.path.dirname(__file__)), 'test_data', 'subspace', 'stat_test_detector.h5')) detector.partition(2) stream = read(os.path.join(os.path.abspath(os.path.dirname(__file__)), 'test_data', 'subspace', 'test_trace.ms')) st = [stream] fft_vars = subspace._do_ffts(detector, st, len(detector.stachans)) stat = subspace._det_stat_freq(fft_vars[0][0], fft_vars[1][0], fft_vars[2][0], fft_vars[3], len(detector.stachans), fft_vars[4], fft_vars[5]) self.assertEqual((stat.max().round(6) - 0.229755).round(6), 0)
def run_tutorial(plot=False, multiplex=True, return_streams=False, cores=4, verbose=False): """ Run the tutorial. :return: detections """ client = Client("GEONET", debug=verbose) cat = client.get_events(minlatitude=-40.98, maxlatitude=-40.85, minlongitude=175.4, maxlongitude=175.5, starttime=UTCDateTime(2016, 5, 1), endtime=UTCDateTime(2016, 5, 20)) print(f"Downloaded a catalog of {len(cat)} events") # This gives us a catalog of events - it takes a while to download all # the information, so give it a bit! # We will generate a five station, multi-channel detector. cat = filter_picks(catalog=cat, top_n_picks=5) stachans = list( set([(pick.waveform_id.station_code, pick.waveform_id.channel_code) for event in cat for pick in event.picks])) # In this tutorial we will only work on one cluster, defined spatially. # You can work on multiple clusters, or try to whole set. clusters = catalog_cluster(catalog=cat, metric="distance", thresh=2, show=False) # We will work on the largest cluster cluster = sorted(clusters, key=lambda c: len(c))[-1] # This cluster contains 32 events, we will now download and trim the # waveforms. Note that each chanel must start at the same time and be the # same length for multiplexing. If not multiplexing EQcorrscan will # maintain the individual differences in time between channels and delay # the detection statistics by that amount before stacking and detection. client = Client('GEONET') design_set = [] st = Stream() for event in cluster: print(f"Downloading for event {event.resource_id.id}") bulk_info = [] t1 = event.origins[0].time t2 = t1 + 25.1 # Have to download extra data, otherwise GeoNet will # trim wherever suits. t1 -= 0.1 for station, channel in stachans: try: st += client.get_waveforms('NZ', station, '*', channel[0:2] + '?', t1, t2) except IncompleteRead: print(f"Could not download for {station} {channel}") print(f"Downloaded {len(st)} channels") for event in cluster: t1 = event.origins[0].time t2 = t1 + 25 design_set.append(st.copy().trim(t1, t2)) # Construction of the detector will process the traces, then align them, # before multiplexing. print("Making detector") detector = subspace.Detector() detector.construct(streams=design_set, lowcut=2.0, highcut=9.0, filt_order=4, sampling_rate=20, multiplex=multiplex, name='Wairarapa1', align=True, reject=0.2, shift_len=6, plot=plot).partition(9) print("Constructed Detector") if plot: detector.plot() # We also want the continuous stream to detect in. t1 = UTCDateTime(2016, 5, 11, 19) t2 = UTCDateTime(2016, 5, 11, 20) # We are going to look in a single hour just to minimize cost, but you can # run for much longer. bulk_info = [('NZ', stachan[0], '*', stachan[1][0] + '?' + stachan[1][-1], t1, t2) for stachan in detector.stachans] print("Downloading continuous data") st = client.get_waveforms_bulk(bulk_info) st.merge().detrend('simple').trim(starttime=t1, endtime=t2) # We set a very low threshold because the detector is not that great, we # haven't aligned it particularly well - however, at this threshold we make # two real detections. print("Computing detections") detections, det_streams = detector.detect(st=st, threshold=0.4, trig_int=2, extract_detections=True, cores=cores) if return_streams: return detections, det_streams else: return detections
def run_tutorial(plot=False, multiplex=True, return_streams=False): """ Run the tutorial. :return: detections """ # We are going to use data from the GeoNet (New Zealand) catalogue. GeoNet # do not implement the full FDSN system yet, so we have a hack to get # around this. It is not strictly part of EQcorrscan, so we haven't # included it here, but you can find it in the tutorials directory of the # github repository import obspy if int(obspy.__version__.split('.')[0]) >= 1: from obspy.clients.fdsn import Client else: from obspy.fdsn import Client from eqcorrscan.tutorials.get_geonet_events import get_geonet_events from obspy import UTCDateTime from eqcorrscan.utils.catalog_utils import filter_picks from eqcorrscan.utils.clustering import space_cluster from eqcorrscan.core import subspace cat = get_geonet_events(minlat=-40.98, maxlat=-40.85, minlon=175.4, maxlon=175.5, startdate=UTCDateTime(2016, 5, 1), enddate=UTCDateTime(2016, 5, 20)) # This gives us a catalog of events - it takes a while to download all # the information, so give it a bit! # We will generate a five station, multi-channel detector. cat = filter_picks(catalog=cat, top_n_picks=5) stachans = list( set([(pick.waveform_id.station_code, pick.waveform_id.channel_code) for event in cat for pick in event.picks])) # In this tutorial we will only work on one cluster, defined spatially. # You can work on multiple clusters, or try to whole set. clusters = space_cluster(catalog=cat, d_thresh=2, show=False) # We will work on the largest cluster cluster = sorted(clusters, key=lambda c: len(c))[-1] # This cluster contains 32 events, we will now download a trim the # waveforms. Note that each chanel must start at the same time and be the # same length for multiplexing. If not multiplexing EQcorrscan will # maintain the individual differences in time between channels and delay # the detection statistics by that amount before stacking and detection. client = Client('GEONET') design_set = [] bulk_info = [] for event in cluster: t1 = event.origins[0].time t2 = t1 + 25 for station, channel in stachans: bulk_info.append(('NZ', station, '*', channel[0:2] + '?', t1, t2)) st = client.get_waveforms_bulk(bulk=bulk_info) for event in cluster: t1 = event.origins[0].time t2 = t1 + 25 design_set.append(st.copy().trim(t1, t2)) # Construction of the detector will process the traces, then align them, # before multiplexing. detector = subspace.Detector() detector.construct(streams=design_set, lowcut=2.0, highcut=9.0, filt_order=4, sampling_rate=20, multiplex=multiplex, name='Wairarapa1', align=True, reject=0.2, shift_len=6, plot=plot).partition(9) if plot: detector.plot() # We also want the continuous stream to detect in. t1 = UTCDateTime(2016, 5, 11, 19) t2 = UTCDateTime(2016, 5, 11, 20) # We are going to look in a single hour just to minimize cost, but you can \ # run for much longer. bulk_info = [('NZ', stachan[0], '*', stachan[1][0] + '?' + stachan[1][-1], t1, t2) for stachan in detector.stachans] st = client.get_waveforms_bulk(bulk_info) st.merge().detrend('simple').trim(starttime=t1, endtime=t2) # We set a very low threshold because the detector is not that great, we # haven't aligned it particularly well - however, at this threshold we make # two real detections. detections, det_streams = detector.detect(st=st, threshold=0.005, trig_int=2, extract_detections=True) if return_streams: return detections, det_streams else: return detections