def setUpClass(cls): cls.detect_dir = os.path.join( os.path.abspath(os.path.dirname(__file__)), ".test_detections") client = Client('GEONET') cls.t1 = UTCDateTime(2016, 9, 4, 18) cls.t2 = UTCDateTime(2016, 9, 5) catalog = client.get_events(starttime=cls.t1, endtime=cls.t2, minmagnitude=4, minlatitude=-49, maxlatitude=-35, minlongitude=175.0, maxlongitude=180.0) catalog = catalog_utils.filter_picks(catalog, channels=['EHZ'], top_n_picks=2) cls.tribe = Tribe().construct(method='from_client', catalog=catalog, client_id='GEONET', lowcut=2.0, highcut=9.0, samp_rate=100.0, filt_order=4, length=3.0, prepick=0.15, swin='all', process_len=300) cls.client = "GEONET" cls.inventory = get_inventory(client=client, tribe=cls.tribe, location=dict(latitude=-42, longitude=177.5), starttime=cls.t1)
def test_save_progress(self): """ Test template creation with progress saving """ client = Client('GEONET') catalog = client.get_events(starttime=UTCDateTime(2016, 1, 4, 0, 50), endtime=UTCDateTime(2016, 1, 4, 1, 20)) # Gets a catalog of 2 events separated by 127s # Need a bigger gap to allow moveouts catalog[0].origins[0].time -= 600 for pick in catalog[0].picks: pick.time -= 600 catalog = filter_picks(catalog=catalog, top_n_picks=5) templates = template_gen(method="from_client", catalog=catalog, client_id="GEONET", lowcut=2, highcut=5, samp_rate=20, filt_order=4, prepick=0.4, process_len=600, swin="P", save_progress=True, length=2) assert (os.path.isdir("eqcorrscan_temporary_templates")) saved_templates = [ read(f) for f in sorted(glob.glob("eqcorrscan_temporary_templates/*.ms")) ] # Writing to miniseed adds miniseed stats dict for saved_template, template in zip(saved_templates, templates): for saved_tr in saved_template: tr = template.select(id=saved_tr.id)[0] assert (np.allclose(saved_tr.data, tr.data, atol=0.01)) shutil.rmtree("eqcorrscan_temporary_templates")
def mktemplates( network_code='GEONET', plot=True, publicIDs=['2016p008122', '2016p008353', '2016p008155', '2016p008194']): """Functional wrapper to make templates""" client = Client(network_code) # We want to download a few events from an earthquake sequence, these are # identified by publiID numbers, given as arguments catalog = Catalog() for publicID in publicIDs: try: catalog += client.get_events(eventid=publicID, includearrivals=True) except TypeError: # Cope with some FDSN services not implementing includearrivals catalog += client.get_events(eventid=publicID) # Lets plot the catalog to see what we have if plot: catalog.plot(projection='local', resolution='h') # We don't need all the picks, lets take the information from the # five most used stations - note that this is done to reduce computational # costs. catalog = filter_picks(catalog, top_n_picks=5) # We only want the P picks in this example, but you can use others or all # picks if you want. for event in catalog: for pick in event.picks: if pick.phase_hint == 'S': event.picks.remove(pick) # Now we can generate the templates templates = template_gen.template_gen(method='from_client', catalog=catalog, client_id=network_code, lowcut=2.0, highcut=9.0, samp_rate=20.0, filt_order=4, length=3.0, prepick=0.15, swin='all', process_len=3600, plot=plot) # We now have a series of templates! Using Obspy's Stream.write() method we # can save these to disk for later use. We will do that now for use in the # following tutorials. for i, template in enumerate(templates): template.write('tutorial_template_' + str(i) + '.ms', format='MSEED') # Note that this will warn you about data types. As we don't care # at the moment, whatever obspy chooses is fine. return
def get_test_data(): """ Generate a set of waveforms from GeoNet for use in subspace testing :return: List of cut templates with no filters applied :rtype: list """ from http.client import IncompleteRead from obspy import UTCDateTime from eqcorrscan.utils.catalog_utils import filter_picks from eqcorrscan.utils.clustering import catalog_cluster from obspy.clients.fdsn import Client client = Client("GEONET") cat = client.get_events(minlatitude=-40.98, maxlatitude=-40.85, minlongitude=175.4, maxlongitude=175.5, starttime=UTCDateTime(2016, 5, 11), endtime=UTCDateTime(2016, 5, 13)) 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])) clusters = catalog_cluster(catalog=cat, thresh=2, show=False, metric='distance') cluster = sorted(clusters, key=lambda c: len(c))[-1] client = Client('GEONET') design_set = [] st = Stream() for event in cluster: # This print is just in to force some output during long running test print("Downloading for event {0}".format(event.resource_id)) bulk_info = [] t1 = event.origins[0].time + 5 t2 = t1 + 15.1 for station, channel in stachans: bulk_info.append(('NZ', station, '10', channel[0:2] + '?', t1, t2)) st += client.get_waveforms_bulk(bulk=bulk_info) for event in cluster: t1 = event.origins[0].time + 5 t2 = t1 + 15 design_set.append(st.copy().trim(t1, t2)) t1 = UTCDateTime(2016, 5, 11, 19) t2 = UTCDateTime(2016, 5, 11, 20) bulk_info = [('NZ', stachan[0], '10', stachan[1][0:2] + '?', t1, t2) for stachan in stachans] st = Stream() for _bulk in bulk_info: try: st += client.get_waveforms(*_bulk) except IncompleteRead: print(f"Could not download {_bulk}") st.merge().detrend('simple').trim(starttime=t1, endtime=t2) return design_set, st
def test_not_delayed(self): """Test the method of template_gen without applying delays to channels.""" client = Client("GEONET") 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, 2)) cat = filter_picks(catalog=cat, top_n_picks=5) template = from_client(catalog=cat, client_id='GEONET', lowcut=None, highcut=None, samp_rate=100.0, filt_order=4, length=10.0, prepick=0.5, swin='all', process_len=3600, debug=0, plot=False, delayed=False)[0] for tr in template: tr.stats.starttime.precision = 6 starttime = template[0].stats.starttime length = template[0].stats.npts self.assertEqual(len(template), 5) for tr in template: self.assertTrue( abs((tr.stats.starttime - starttime)) <= tr.stats.delta) self.assertEqual(tr.stats.npts, length) template = from_client(catalog=cat, client_id='GEONET', lowcut=None, highcut=None, samp_rate=100.0, filt_order=4, length=10.0, prepick=0.5, swin='P_all', process_len=3600, debug=0, plot=False, delayed=False)[0] for tr in template: tr.stats.starttime.precision = 6 starttime = template[0].stats.starttime length = template[0].stats.npts self.assertEqual(len(template), 15) for tr in template: self.assertTrue( abs((tr.stats.starttime - starttime)) <= tr.stats.delta) self.assertEqual(tr.stats.npts, length)
def mktemplates(network_code='GEONET', publicIDs=['2016p008122', '2016p008353', '2016p008155', '2016p008194'], plot=True): """Functional wrapper to make templates""" # We want to download some QuakeML files from the New Zealand GeoNet # network, GeoNet currently doesn't support FDSN event queries, so we # have to work around to download quakeml from their quakeml.geonet site. client = Client(network_code) # We want to download a few events from an earthquake sequence, these are # identified by publiID numbers, given as arguments catalog = Catalog() for publicID in publicIDs: if network_code == 'GEONET': data_stream = client._download( 'http://quakeml.geonet.org.nz/quakeml/1.2/' + publicID) data_stream.seek(0, 0) catalog += read_events(data_stream, format="quakeml") data_stream.close() else: catalog += client.get_events( eventid=publicID, includearrivals=True) # Lets plot the catalog to see what we have if plot: catalog.plot(projection='local', resolution='h') # We don't need all the picks, lets take the information from the # five most used stations - note that this is done to reduce computational # costs. catalog = filter_picks(catalog, top_n_picks=5) # We only want the P picks in this example, but you can use others or all # picks if you want. for event in catalog: for pick in event.picks: if pick.phase_hint == 'S': event.picks.remove(pick) # Now we can generate the templates templates = template_gen.template_gen( method='from_client', catalog=catalog, client_id=network_code, lowcut=2.0, highcut=9.0, samp_rate=20.0, filt_order=4, length=3.0, prepick=0.15, swin='all', process_len=3600, debug=0, plot=plot) # We now have a series of templates! Using Obspy's Stream.write() method we # can save these to disk for later use. We will do that now for use in the # following tutorials. for i, template in enumerate(templates): template.write('tutorial_template_' + str(i) + '.ms', format='MSEED') # Note that this will warn you about data types. As we don't care # at the moment, whatever obspy chooses is fine. return
def test_filter_picks(self): """ Test various methods of filetring picks in a catalog.""" from obspy.clients.fdsn import Client from eqcorrscan.utils.catalog_utils import filter_picks from obspy import UTCDateTime client = Client(str("NCEDC")) t1 = UTCDateTime(2004, 9, 28) t2 = t1 + 86400 catalog = client.get_events(starttime=t1, endtime=t2, minmagnitude=3, minlatitude=35.7, maxlatitude=36.1, minlongitude=-120.6, maxlongitude=-120.2, includearrivals=True) stations = ['BMS', 'BAP', 'PAG', 'PAN', 'PBI', 'PKY', 'YEG', 'WOF'] channels = ['SHZ', 'SHN', 'SHE', 'SH1', 'SH2'] networks = ['NC'] locations = [''] top_n_picks = 5 filtered_catalog = filter_picks(catalog=catalog, stations=stations, channels=channels, networks=networks, locations=locations, top_n_picks=top_n_picks) for event in filtered_catalog: for pick in event.picks: self.assertTrue(pick.waveform_id.station_code in stations) self.assertTrue(pick.waveform_id.channel_code in channels) self.assertTrue(pick.waveform_id.network_code in networks) self.assertTrue(pick.waveform_id.location_code in locations) filtered_catalog = filter_picks(catalog=catalog, top_n_picks=top_n_picks) filtered_stations = [] for event in filtered_catalog: for pick in event.picks: filtered_stations.append(pick.waveform_id.station_code) self.assertEqual(len(list(set(filtered_stations))), top_n_picks)
def setUpClass(cls): print('\t\t\t Downloading data') client = Client('NCEDC') t1 = UTCDateTime(2004, 9, 28, 17) t2 = t1 + 3600 process_len = 3600 # t1 = UTCDateTime(2004, 9, 28) # t2 = t1 + 80000 # process_len = 80000 catalog = client.get_events(starttime=t1, endtime=t2, minmagnitude=4, minlatitude=35.7, maxlatitude=36.1, minlongitude=-120.6, maxlongitude=-120.2, includearrivals=True) catalog = catalog_utils.filter_picks(catalog, channels=['EHZ'], top_n_picks=5) cls.templates = template_gen.from_client(catalog=catalog, client_id='NCEDC', lowcut=2.0, highcut=9.0, samp_rate=50.0, filt_order=4, length=3.0, prepick=0.15, swin='all', process_len=process_len) for template in cls.templates: template.sort() # Download and process the day-long data template_stachans = [] for template in cls.templates: for tr in template: template_stachans.append((tr.stats.network, tr.stats.station, tr.stats.channel)) template_stachans = list(set(template_stachans)) bulk_info = [(stachan[0], stachan[1], '*', stachan[2][0] + 'H' + stachan[2][1], t1, t1 + process_len) for stachan in template_stachans] # Just downloading an hour of data st = client.get_waveforms_bulk(bulk_info) st.merge(fill_value='interpolate') cls.st = pre_processing.shortproc(st, lowcut=2.0, highcut=9.0, filt_order=4, samp_rate=50.0, debug=0, num_cores=1) cls.template_names = [str(template[0].stats.starttime) for template in cls.templates]
def get_test_data(): """ Generate a set of waveforms from GeoNet for use in subspace testing :return: List of cut templates with no filters applied :rtype: list """ from obspy import UTCDateTime from eqcorrscan.utils.catalog_utils import filter_picks from eqcorrscan.utils.clustering import space_cluster from obspy.clients.fdsn import Client client = Client("GEONET") cat = client.get_events(minlatitude=-40.98, maxlatitude=-40.85, minlongitude=175.4, maxlongitude=175.5, starttime=UTCDateTime(2016, 5, 11), endtime=UTCDateTime(2016, 5, 13)) 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])) clusters = space_cluster(catalog=cat, d_thresh=2, show=False) cluster = sorted(clusters, key=lambda c: len(c))[-1] client = Client('GEONET') design_set = [] bulk_info = [] for event in cluster: t1 = event.origins[0].time + 5 t2 = t1 + 15.1 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 + 5 t2 = t1 + 15 design_set.append(st.copy().trim(t1, t2)) t1 = UTCDateTime(2016, 5, 11, 19) t2 = UTCDateTime(2016, 5, 11, 20) bulk_info = [('NZ', stachan[0], '*', stachan[1][0:2] + '?', t1, t2) for stachan in stachans] st = client.get_waveforms_bulk(bulk_info) st.merge().detrend('simple').trim(starttime=t1, endtime=t2) return design_set, st
def setUpClass(cls) -> None: cls.test_path = ( os.path.abspath(os.path.dirname(__file__)) + os.path.sep + "db") if os.path.isdir(cls.test_path): shutil.rmtree(cls.test_path) os.makedirs(cls.test_path) logging.debug("Making the bank") cls.bank = TemplateBank( base_path=cls.test_path, name_structure="{event_id_short}") cls.client = Client("GEONET") logging.debug("Downloading the catalog") catalog = cls.client.get_events( starttime=UTCDateTime(2019, 6, 21), endtime=UTCDateTime(2019, 6, 23), latitude=-38.8, longitude=175.8, maxradius=0.2) cls.catalog = remove_unreferenced( filter_picks(catalog=catalog, top_n_picks=5)) cls.bank.put_events(cls.catalog)
def test_short_match_filter(self): """Test using short streams of data.""" from obspy.clients.fdsn import Client from obspy import UTCDateTime from eqcorrscan.core import template_gen, match_filter from eqcorrscan.utils import pre_processing, catalog_utils client = Client('NCEDC') t1 = UTCDateTime(2004, 9, 28) t2 = t1 + 86400 catalog = client.get_events(starttime=t1, endtime=t2, minmagnitude=4, minlatitude=35.7, maxlatitude=36.1, minlongitude=-120.6, maxlongitude=-120.2, includearrivals=True) catalog = catalog_utils.filter_picks(catalog, channels=['EHZ'], top_n_picks=5) templates = template_gen.from_client(catalog=catalog, client_id='NCEDC', lowcut=2.0, highcut=9.0, samp_rate=50.0, filt_order=4, length=3.0, prepick=0.15, swin='all', process_len=3600) # Download and process the day-long data bulk_info = [(tr.stats.network, tr.stats.station, '*', tr.stats.channel[0] + 'H' + tr.stats.channel[1], t2 - 3600, t2) for tr in templates[0]] # Just downloading an hour of data st = client.get_waveforms_bulk(bulk_info) st.merge(fill_value='interpolate') st = pre_processing.shortproc(st, lowcut=2.0, highcut=9.0, filt_order=4, samp_rate=50.0, debug=0, num_cores=4) template_names = [str(template[0].stats.starttime) for template in templates] detections = match_filter.match_filter(template_names=template_names, template_list=templates, st=st, threshold=8.0, threshold_type='MAD', trig_int=6.0, plotvar=False, plotdir='.', cores=4)
def setUpClass(cls): client = Client('GEONET') t1 = UTCDateTime(2016, 9, 4) t2 = t1 + 86400 catalog = get_geonet_events(startdate=t1, enddate=t2, minmag=4, minlat=-49, maxlat=-35, minlon=175.0, maxlon=185.0) catalog = catalog_utils.filter_picks(catalog, channels=['EHZ'], top_n_picks=5) for event in catalog: extra_pick = Pick() extra_pick.phase_hint = 'S' extra_pick.time = event.picks[0].time + 10 extra_pick.waveform_id = event.picks[0].waveform_id event.picks.append(extra_pick) cls.templates = template_gen.from_client(catalog=catalog, client_id='GEONET', lowcut=2.0, highcut=9.0, samp_rate=50.0, filt_order=4, length=3.0, prepick=0.15, swin='all', process_len=3600) # Download and process the day-long data bulk_info = [(tr.stats.network, tr.stats.station, '*', tr.stats.channel[0] + 'H' + tr.stats.channel[1], t1 + (4 * 3600), t1 + (5 * 3600)) for tr in cls.templates[0]] # Just downloading an hour of data print('Downloading data') st = client.get_waveforms_bulk(bulk_info) st.merge(fill_value='interpolate') st.trim(t1 + (4 * 3600), t1 + (5 * 3600)).sort() # This is slow? print('Processing continuous data') cls.st = pre_processing.shortproc(st, lowcut=2.0, highcut=9.0, filt_order=4, samp_rate=50.0, debug=0, num_cores=1) cls.st.trim(t1 + (4 * 3600), t1 + (5 * 3600)).sort() cls.template_names = [str(template[0].stats.starttime) for template in cls.templates]
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 test_stability(): """Test various threshold window lengths.""" from eqcorrscan.core.match_filter import _channel_loop from eqcorrscan.utils import pre_processing, catalog_utils, plotting from eqcorrscan.core import template_gen from obspy.clients.fdsn import Client from obspy import UTCDateTime, Trace import numpy as np import matplotlib.pyplot as plt # Do some set-up client = Client('NCEDC') t1 = UTCDateTime(2004, 9, 28) t2 = t1 + 86400 catalog = client.get_events(starttime=t1, endtime=t2, minmagnitude=2, minlatitude=35.7, maxlatitude=36.1, minlongitude=-120.6, maxlongitude=-120.2, includearrivals=True) catalog = catalog_utils.filter_picks(catalog, channels=['EHZ'], top_n_picks=5) templates = template_gen.from_client(catalog=catalog, client_id='NCEDC', lowcut=2.0, highcut=9.0, samp_rate=20.0, filt_order=4, length=3.0, prepick=0.15, swin='all') bulk_info = [ (tr.stats.network, tr.stats.station, '*', tr.stats.channel[0] + 'H' + tr.stats.channel[1], t2 - 3600, t2) for tr in templates[0] ] st = client.get_waveforms_bulk(bulk_info) st.merge(fill_value='interpolate') st = pre_processing.shortproc(st, lowcut=2.0, highcut=9.0, filt_order=4, samp_rate=20.0, debug=0, num_cores=4) i = 0 cccsums, no_chans, chans = _channel_loop(templates, st) cccsum = cccsums[0] MAD_thresh = 8 MAD_daylong = MAD_thresh * np.median(np.abs(cccsum)) MAD_hours = [] MAD_five_mins = [] MAD_minutes = [] for hour in range(24): ccc_hour_slice = cccsum[hour * 3600 * st[0].stats.sampling_rate:(hour + 1) * 3600 * st[0].stats.sampling_rate] MAD_hour_slice = MAD_thresh * np.median(np.abs(ccc_hour_slice)) MAD_hours.append(MAD_hour_slice) for five_min in range(12): ccc_five_slice = ccc_hour_slice[five_min * 300 * st[0].stats.sampling_rate: (five_min + 1) * 300 * st[0].stats.sampling_rate] MAD_five_slice = MAD_thresh * np.median(np.abs(ccc_five_slice)) MAD_five_mins.append(MAD_five_slice) for minute in range(60): ccc_min_slice = ccc_hour_slice[minute * 60 * st[0].stats.sampling_rate:(minute + 1) * 60 * st[0].stats.sampling_rate] MAD_min_slice = MAD_thresh * np.median(np.abs(ccc_min_slice)) MAD_minutes.append(MAD_min_slice) plotting_cccsum = Trace(cccsum) plotting_cccsum.stats.sampling_rate = st[0].stats.sampling_rate plotting_cccsum = plotting.chunk_data(plotting_cccsum, 1, 'Maxabs') x = np.arange(0, 24, 1.0 / (3600 * plotting_cccsum.stats.sampling_rate)) x = x[0:len(plotting_cccsum.data)] plt.plot(x, plotting_cccsum.data, linewidth=0.7, color='k') plt.plot(np.arange(0, 24, 1.0 / 60), MAD_minutes, label='1 minute MAD', color='y') plt.plot(np.arange(0, 24, 1.0 / 60), [-1 * m for m in MAD_minutes], color='y') plt.plot(np.arange(0, 24, 1.0 / 12), MAD_five_mins, label='5 minute MAD', color='b') plt.plot(np.arange(0, 24, 1.0 / 12), [-1 * m for m in MAD_five_mins], color='b') plt.plot(np.arange(24), MAD_hours, label='Hourly MAD', color='r', linewidth=1.4) plt.plot(np.arange(24), [-1 * m for m in MAD_hours], color='r', linewidth=1.4) plt.plot([0, 24], [MAD_daylong, MAD_daylong], label='Day-long MAD', linewidth=1.5, color='g') plt.plot([0, 24], [-1 * MAD_daylong, -1 * MAD_daylong], linewidth=1.5, color='g') plt.legend() plt.show()
def run(analysis_start, analysis_len, template_creation_start, template_creation_len, write_streams, intermediate_party_output, final_party_output, intermediate_stream_output, final_stream_output): client = Client("http://service.geonet.org.nz") # for template creation day_len = 86400 t2 = template_creation_start + (template_creation_len * day_len) catalog = client.get_events(starttime=template_creation_start, endtime=t2, minmagnitude=2.5, minlatitude=-37.95936, maxlatitude=-36.84226, minlongitude=176.63818, maxlongitude=177.80548) # Get rid of duplicately picked arrivals. for event in catalog: counted_stations = Counter(p.waveform_id.get_seed_string() for p in event.picks) _picks = [] for seed_id, n_picks in counted_stations.items(): nslc_picks = [ p for p in event.picks if p.waveform_id.get_seed_string() == seed_id ] if n_picks == 1: _picks.append(nslc_picks[0]) else: print("Multiple picks for {0}".format(seed_id)) nslc_picks.sort(key=lambda p: p.time) _picks.append(nslc_picks[0]) event.picks = _picks catalog = filter_picks(catalog=catalog, evaluation_mode="manual", top_n_picks=20) tribe = Tribe().construct(method="from_client", lowcut=2.0, highcut=15.0, samp_rate=50.0, length=6.0, filt_order=4, prepick=0.5, client_id=client, catalog=catalog, data_pad=20., process_len=day_len, min_snr=5.0, parallel=False) print(tribe) print(tribe[0]) tribe.templates = [ t for t in tribe if len({tr.stats.station for tr in t.st}) >= 5 ] print(tribe) if write_streams is True: for day in range(1, analysis_len): _party, st = tribe.client_detect( client=client, starttime=analysis_start + (day - 1) * day_len, endtime=analysis_start + day * day_len, threshold=9., threshold_type="MAD", trig_int=2.0, plot=False, return_stream=True) _party.write(intermediate_party_output + "/Detections_day_{0}".format(day)) st = st.split() # Required for writing to miniseed st.write(intermediate_stream_output + "/{0}.ms".format(day), format="MSEED") reform_party(final_party_output, intermediate_party_output) reform_stream(final_stream_output, intermediate_stream_output) else: for day in range(1, analysis_len): _party = tribe.client_detect( client=client, starttime=analysis_start + (day - 1) * day_len, endtime=analysis_start + day * day_len, threshold=9., threshold_type="MAD", trig_int=2.0, plot=False, return_stream=False) _party.write(intermediate_party_output + "/Detections_day_{0}".format(day)) reform_party(final_party_output, intermediate_party_output)
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
nslc_picks = [ p for p in event.picks if p.waveform_id.get_seed_string() == seed_id ] if n_picks == 1: _picks.append(nslc_picks[0]) else: print("Multiple picks for {0}".format(seed_id)) nslc_picks.sort(key=lambda p: p.time) _picks.append(nslc_picks[0]) event.picks = _picks # -the catalog holds a bunch of earthquake events which add p and s wave picks to siesmometers, the filter picks selects the 20 stations with the # greatest total number of all picks so essentially the stations with the most data. # - Why? catalog = filter_picks(catalog=catalog, top_n_picks=20) # evaluation_mode="manual") # -Makes a group of template objects (Tribe) from the events in the catalog # -Takes each event in the catalog and makes a template from it if it meets the specifications. each template contains all channels that meet the requirements # -Highcut is the highest allowed frequency for the template and must be at most half the samp_rate # -Length is the length of the template waveform in seconds # -Prepick is the number of seconds prior to the earthquake wave arrival. needed to compare the wavey bit to the non wavey bit 0.5 seconds is usually good # -Always set datapad to 20? # -Each template contains the event but also the data to run the event over # -Process_len must be set to the same length as what exactly? is the process length the data to run the template against? # -"WARNING No pick for NZ.KNZ.10.HHN" if there is no pick for this channel does that mean there was a pick on one of the other channels and catalog includes # all channels for events where there is a pick on at least one channel? process_len = 86400 tribe = Tribe().construct(method="from_client", lowcut=2.0, highcut=15.0,
def run_tutorial(min_magnitude=2, shift_len=0.2, num_cores=4, min_cc=0.5): """Functional, tested example script for running the lag-calc tutorial.""" if num_cores > cpu_count(): num_cores = cpu_count() client = Client('NCEDC') t1 = UTCDateTime(2004, 9, 28) t2 = t1 + 86400 print('Downloading catalog') catalog = client.get_events(starttime=t1, endtime=t2, minmagnitude=min_magnitude, minlatitude=35.7, maxlatitude=36.1, minlongitude=-120.6, maxlongitude=-120.2, includearrivals=True) # We don't need all the picks, lets take the information from the # five most used stations - note that this is done to reduce computational # costs. catalog = catalog_utils.filter_picks(catalog, channels=['EHZ'], top_n_picks=5) # There is a duplicate pick in event 3 in the catalog - this has the effect # of reducing our detections - check it yourself. for pick in catalog[3].picks: if pick.waveform_id.station_code == 'PHOB' and \ pick.onset == 'emergent': catalog[3].picks.remove(pick) print('Generating templates') templates = template_gen.template_gen(method="from_client", catalog=catalog, client_id='NCEDC', lowcut=2.0, highcut=9.0, samp_rate=50.0, filt_order=4, length=3.0, prepick=0.15, swin='all', process_len=3600) # In this section we generate a series of chunks of data. start_time = UTCDateTime(2004, 9, 28, 17) end_time = UTCDateTime(2004, 9, 28, 20) process_len = 3600 chunks = [] chunk_start = start_time while chunk_start < end_time: chunk_end = chunk_start + process_len if chunk_end > end_time: chunk_end = end_time chunks.append((chunk_start, chunk_end)) chunk_start += process_len all_detections = [] picked_catalog = Catalog() template_names = [ template[0].stats.starttime.strftime("%Y%m%d_%H%M%S") for template in templates ] for t1, t2 in chunks: print('Downloading and processing for start-time: %s' % t1) # Download and process the data bulk_info = [(tr.stats.network, tr.stats.station, '*', tr.stats.channel, t1, t2) for tr in templates[0]] # Just downloading a chunk of data try: st = client.get_waveforms_bulk(bulk_info) except FDSNException: st = Stream() for _bulk in bulk_info: st += client.get_waveforms(*_bulk) st.merge(fill_value='interpolate') st = pre_processing.shortproc(st, lowcut=2.0, highcut=9.0, filt_order=4, samp_rate=50.0, num_cores=num_cores) detections = match_filter.match_filter(template_names=template_names, template_list=templates, st=st, threshold=8.0, threshold_type='MAD', trig_int=6.0, plotvar=False, plotdir='.', cores=num_cores) # Extract unique detections from set. unique_detections = [] for master in detections: keep = True for slave in detections: if not master == slave and\ abs(master.detect_time - slave.detect_time) <= 1.0: # If the events are within 1s of each other then test which # was the 'best' match, strongest detection if not master.detect_val > slave.detect_val: keep = False break if keep: unique_detections.append(master) all_detections += unique_detections picked_catalog += lag_calc.lag_calc(detections=unique_detections, detect_data=st, template_names=template_names, templates=templates, shift_len=shift_len, min_cc=min_cc, interpolate=False, plot=False) # Return all of this so that we can use this function for testing. return all_detections, picked_catalog, templates, template_names
from obspy.clients.fdsn import Client from eqcorrscan.core.template_gen import from_client from eqcorrscan.tutorials.get_geonet_events import get_geonet_events from eqcorrscan.utils.catalog_utils import filter_picks from eqcorrscan.core import template_gen catalog = get_geonet_events( startdate = UTCDateTime('2016-11-13T11:00:00'), enddate = UTCDateTime('2016-11-14T11:00:00'), maxlat = -42.0, minlat = -43.0, minlon = 173, maxlon = 174) print catalog filtered_catalog = filter_picks(catalog, stations=['WEL'], top_n_picks=2) print filtered_catalog templates = from_client( catalog = filtered_catalog, client_id='GEONET', lowcut = 2.0, highcut = 9.0, samp_rate = 20.0, filt_order = 4, length = 2.0, prepick = 0.15, swin = 'all', process_len = 86400) print templates templates[0].plot() templates[1].plot() templates[2].plot() templates[3].plot() templates[0].write('kaik_eq-WEL.ms', format = 'MSEED') templates[1].write('kaik_eq-WEL2.ms', format = 'MSEED')
def run_tutorial(min_magnitude=2, shift_len=0.2, num_cores=4): import obspy if int(obspy.__version__.split('.')[0]) >= 1: from obspy.clients.fdsn import Client else: from obspy.fdsn import Client from obspy.core.event import Catalog from obspy import UTCDateTime from eqcorrscan.core import template_gen, match_filter, lag_calc from eqcorrscan.utils import pre_processing, catalog_utils client = Client('NCEDC') t1 = UTCDateTime(2004, 9, 28) t2 = t1 + 86400 print('Downloading catalog') catalog = client.get_events(starttime=t1, endtime=t2, minmagnitude=min_magnitude, minlatitude=35.7, maxlatitude=36.1, minlongitude=-120.6, maxlongitude=-120.2, includearrivals=True) # We don't need all the picks, lets take the information from the # five most used stations - note that this is done to reduce computational # costs. catalog = catalog_utils.filter_picks(catalog, channels=['EHZ'], top_n_picks=5) print('Generating templates') templates = template_gen.from_client(catalog=catalog, client_id='NCEDC', lowcut=2.0, highcut=9.0, samp_rate=50.0, filt_order=4, length=3.0, prepick=0.15, swin='all', process_len=3600) start_time = UTCDateTime(2004, 9, 28, 17) end_time = UTCDateTime(2004, 9, 28, 20) process_len = 1800 chunks = [] chunk_start = start_time while chunk_start < end_time: chunk_end = chunk_start + process_len if chunk_end > end_time: chunk_end = end_time chunks.append((chunk_start, chunk_end)) chunk_start += process_len all_detections = [] picked_catalog = Catalog() template_names = [ str(template[0].stats.starttime) for template in templates ] for t1, t2 in chunks: print('Downloading and processing for start-time: %s' % t1) # Download and process the data bulk_info = [(tr.stats.network, tr.stats.station, '*', tr.stats.channel[0] + 'H' + tr.stats.channel[1], t1, t2) for tr in templates[0]] # Just downloading a chunk of data st = client.get_waveforms_bulk(bulk_info) st.merge(fill_value='interpolate') st = pre_processing.shortproc(st, lowcut=2.0, highcut=9.0, filt_order=4, samp_rate=50.0, debug=0, num_cores=num_cores) detections = match_filter.match_filter(template_names=template_names, template_list=templates, st=st, threshold=8.0, threshold_type='MAD', trig_int=6.0, plotvar=False, plotdir='.', cores=num_cores) # Extract unique detections from set. unique_detections = [] for master in detections: keep = True for slave in detections: if not master == slave and\ abs(master.detect_time - slave.detect_time) <= 1.0: # If the events are within 1s of each other then test which # was the 'best' match, strongest detection if not master.detect_val > slave.detect_val: keep = False break if keep: unique_detections.append(master) all_detections += unique_detections picked_catalog += lag_calc.lag_calc(detections=unique_detections, detect_data=st, template_names=template_names, templates=templates, shift_len=shift_len, min_cc=0.5, interpolate=True, plot=False) # Return all of this so that we can use this function for testing. return all_detections, picked_catalog, templates, template_names