def test_deconvolution_of_stream_Qpeak_position(self): # S receiver deconvolution from pkg_resources import resource_filename fname = resource_filename('rf', 'example/minimal_example_S.tar.gz') stream = read_rf(fname)[:3] rfstats(stream, phase='S') stream.filter('bandpass', freqmin=0.2, freqmax=0.5) stream.trim2(10, 120, reftime='starttime') stream.rotate('ZNE->LQT') # check that maximum in Q component is at 0s (at S onset) test_deconvolve_Qpeak(self, stream, 'time') test_deconvolve_Qpeak(self, stream, 'freq') test_deconvolve_Qpeak(self, stream, 'time', winsrc=(-5, 18, 5)) test_deconvolve_Qpeak(self, stream, 'freq', winsrc=(-5, 18, 5)) test_deconvolve_Qpeak(self, stream, 'time', winsrc=(-20, 40, 5)) test_deconvolve_Qpeak(self, stream, 'freq', winsrc=(-20, 40, 5))
def get_waveforms(): events = get_events()[::-1] client = Client('GFZ') stream_raw = Stream() stream = RFStream() coords = inventory.get_coordinates(seedid[:-1] + 'Z') for i, event in enumerate(events): t = event.preferred_origin().time args = seedid.split('.') + [t + 4.9 * 60, t + 14.1 * 60] s = client.get_waveforms(*args) s.trim(t + 5 * 60, t + 14 * 60) s.decimate(int(round(s[0].stats.sampling_rate)) // 5, no_filter=True) stream_raw.extend(s) if i in (0, 2, 4): s = s.copy() stats = rfstats(station=coords, event=event, dist_range=(20, 95)) if stats is None: continue s.trim(stats.onset - 25, stats.onset + 75) stats = obj2stats(station=coords, event=event) s = RFStream(s) for tr in s: tr.stats.update(stats) stream.extend(s) stream_raw.write(wavname, 'MSEED') stream.write(wavname2, 'SAC')
def batch_rf(init, events, inventory, path, format='H5', request_window=None, phase='P', dist_range=None, **rf_kwargs): get_waveform = init() root = phase + 'rf' _check_path(join(path, root)) method = phase[-1] if dist_range is None: dist_range = (30, 90) if method == 'P' else (60, 85) if request_window is None: request_window = (-50, 150) if method == 'P' else (-80, 50) for kwargs, event, coords in _iter(events, inventory, rf=True): stats = rfstats(station=coords, event=event, phase=phase, dist_range=dist_range) if not stats: continue kwargs.update({'starttime': stats.onset + request_window[0], 'endtime': stats.onset + request_window[1]}) stream = get_waveform(**kwargs) if stream is None: continue stream = RFStream(stream, warn=False) stream.merge() if len(stream) != 3: import warnings warnings.warn('Need 3 component seismograms. More or less ' 'than three components for event %s, station %s.' % (stats.event_id, kwargs['seed_id'])) continue for tr in stream: tr.stats.update(stats) stream.rf(method=method, **rf_kwargs) if len(stream) != 3: continue _write(stream, path, root, format)
def get_waveforms(): events = get_events()[::-1] client = Client('GFZ') stream_raw = Stream() stream = RFStream() coords = inventory.get_coordinates(seedid[:-1] + 'Z') for i, event in enumerate(events): t = event.preferred_origin().time args = seedid.split('.') + [t + 4.9 * 60, t + 14.1 * 60] s = client.get_waveforms(*args) s.trim(t+5*60, t+14*60) s.decimate(int(round(s[0].stats.sampling_rate)) // 5, no_filter=True) stream_raw.extend(s) if i in (0, 2, 4): s = s.copy() stats = rfstats(station=coords, event=event, dist_range=(20, 95)) if stats is None: continue s.trim(stats.onset - 25, stats.onset + 75) stats = obj2stats(station=coords, event=event) s = RFStream(s) for tr in s: tr.stats.update(stats) stream.extend(s) stream_raw.write(wavname, 'MSEED') stream.write(wavname2, 'SAC')
def rf_client(get_waveform, rf, stations=None, events=None, request_window=(-50, 150), phase='P', dist=None, **rf_kwargs): # S: -300 bis 300 """ TODO: doc rf_client """ events = readEvents(events) stations = _read_stations(stations) for event in events: event_id = event.resource_id.getQuakeMLURI().split('/')[-1] for station in stations: stats = rfstats(station=stations[station], event=event, phase=phase, dist_range=dist) if not stats: continue st = get_waveform(station, stats.onset + request_window[0], stats.onset + request_window[1]) st = RFStream(stream=st) st.merge() if len(st) != 3: import warnings warnings.warn('Need 3 component seismograms. More or less ' 'than three components for event %s, station %s.' % (event_id, station)) continue for tr in st: tr.stats.update(stats) st.rf(method=phase[0], **rf_kwargs) st.write_sac_header() for tr in st: output = rf.format(eventid=event_id, stats=tr.stats) _create_dir(output) tr.write(output, 'SAC')
def rf_dmt(data_path, rf, events=None, phase='P', dist=None, **rf_kwargs): """ TODO: doc rf_dmt """ events = readEvents(events) print events for event in events: event_id = event.resource_id.getQuakeMLURI().split('/')[-1] inputs = data_path.format(eventid=event_id) inputs = glob.glob(data_path) while len(inputs) > 0: files_tmp = inputs[0][:-1] + '?' for f in glob.glob(files_tmp): inputs.remove(f) st = RFStream(read(files_tmp, headonly=True)) st.read_sac_header() stats = rfstats(stats=st[0].stats, event=event, phase=phase, dist_range=dist) if not stats: continue st = RFStream(read(files_tmp)) st.merge() if len(st) != 3: import warnings warnings.warn('Need 3 component seismograms. ' 'Error for files %s' % files_tmp) continue for tr in st: tr.stats.update(stats) st.rf(method=phase[0], **rf_kwargs) for tr in st: output = rf.format(eventid=event_id, stats=tr.stats) _create_dir(output) tr.write(output, 'SAC')
def test_deconvolution_of_stream_Lpeak_position(self): stream = read_rf()[:3] rfstats(stream) stream.filter('bandpass', freqmin=0.4, freqmax=1) stream.trim2(5, 95, reftime='starttime') stream.rotate('ZNE->LQT') # check that maximum in L component is at 0s (at P onset) test_deconvolve_Lpeak(self, stream, 'time') test_deconvolve_Lpeak(self, stream, 'freq') test_deconvolve_Lpeak(self, stream, 'time', winsrc=(-20, 40, 5)) test_deconvolve_Lpeak(self, stream, 'freq', winsrc=(-20, 40, 5)) stream.trim2(5, 70, reftime='starttime') test_deconvolve_Lpeak(self, stream, 'time') test_deconvolve_Lpeak(self, stream, 'freq') test_deconvolve_Lpeak(self, stream, 'time', winsrc=(-20, 40, 5)) test_deconvolve_Lpeak(self, stream, 'freq', winsrc=(-20, 40, 5)) test_deconvolve_Lpeak(self, stream, 'time', winsrc=(-5, 18, 5)) test_deconvolve_Lpeak(self, stream, 'freq', winsrc=(-5, 18, 5))
def minimal_example_Srf(): """ Return S receiver functions calculated from example data. """ cache_key = 'minimal_example_Srf' if cache_key in __CACHE: return __CACHE[cache_key].copy() from rf.rfstream import read_rf, rfstats fname = resource_filename('rf', 'example/minimal_example_S.tar.gz') stream = read_rf(fname) rfstats(stream, phase='S') stream.filter('bandpass', freqmin=0.2, freqmax=0.5) stream.trim2(10, 120, reftime='starttime') stream.rf(method='S', winsrc=(-5, 15, 5)) stream.moveout(phase='Sp') stream.ppoints(50, pp_phase='P') __CACHE[cache_key] = stream return stream.copy()
def minimal_example_rf(): """ Return receiver functions calculated from the data returned by read_rf(). """ cache_key = 'minimal_example_rf' if cache_key in __CACHE: return __CACHE[cache_key].copy() from rf.rfstream import read_rf, rfstats stream = read_rf() rfstats(stream) stream.filter('bandpass', freqmin=0.5, freqmax=2) stream.trim2(10, 110, reftime='starttime') stream.rf(winsrc=(-5, 25, 5)) stream.moveout() stream.trim2(-10, 80, reftime='onset') stream.ppoints(50) __CACHE[cache_key] = stream return stream.copy()
def test_deconvolve_custom_function(self): def test_func_stream(rsp, src, **kw): for r_ in rsp: r_.data[:] = 1 r_.stats.custom = 'X' src.data return rsp stream = read_rf()[:3] rfstats(stream) stream1 = stream.copy() stream1.rf(deconvolve='func', func=test_func_stream) for tr in stream1: np.testing.assert_equal(tr.data, 1) self.assertIn('custom', tr.stats) stream1 = stream stream1.deconvolve(method='func', func=test_func_stream) for tr in stream1: np.testing.assert_equal(tr.data, 1) self.assertIn('custom', tr.stats)
def run_rf(events, inventory, get_waveforms, path, format='H5', request_window=None, phase='P', dist_range=None, tt_model='iasp91', pp_depth=None, pp_phase=None, model='iasp91', **rf_kwargs): root = phase + 'rf' _check_path(join(path, root)) method = phase[-1].upper() if dist_range is None: dist_range = (30, 90) if method == 'P' else (60, 85) if request_window is None: request_window = (-50, 150) if method == 'P' else (-100, 50) for kwargs, event, coords in _iter(events, inventory, rf=True): stats = rfstats(station=coords, event=event, phase=phase, dist_range=dist_range, tt_model=tt_model, pp_depth=pp_depth, pp_phase=pp_phase, model=model) if not stats: continue kwargs.update({ 'starttime': stats.onset + request_window[0], 'endtime': stats.onset + request_window[1] }) stream = get_waveforms(**kwargs) if stream is None: continue stream = RFStream(stream, warn=False) stream.merge() if len(stream) != 3: import warnings warnings.warn('Need 3 component seismograms. More or less ' 'than three components for event %s, station %s.' % (stats.event_id, kwargs['seed_id'])) continue for tr in stream: tr.stats.update(stats) stream.rf(method=method, **rf_kwargs) if len(stream) != 3: continue _write(stream, path, root, format)
def iter_event_data(events, inventory, get_waveforms, phase='P', request_window=None, pad=10, pbar=None, **kwargs): """ Return iterator yielding three component streams per station and event. :param events: list of events or `~obspy.core.event.Catalog` instance :param inventory: `~obspy.core.inventory.inventory.Inventory` instance with station and channel information :param get_waveforms: Function returning the data. It has to take the arguments network, station, location, channel, starttime, endtime. :param phase: Considered phase, e.g. 'P', 'S', 'PP' :type request_window: tuple (start, end) :param request_window: requested time window around the onset of the phase :param float pad: add specified time in seconds to request window and trim afterwards again :param pbar: tqdm_ instance for displaying a progressbar :return: three component streams with raw data Example usage with progressbar:: from tqdm import tqdm from rf.util import iter_event_data with tqdm() as t: for stream3c in iter_event_data(*args, pbar=t): do_something(stream3c) .. _tqdm: https://pypi.python.org/pypi/tqdm """ from rf.rfstream import rfstats, RFStream method = phase[-1].upper() if request_window is None: request_window = (-50, 150) if method == 'P' else (-100, 50) stations = _get_stations(inventory) if pbar is not None: pbar.total = len(events) * len(stations) for event, seedid in itertools.product(events, stations): if pbar is not None: pbar.update(1) origin_time = (event.preferred_origin() or event.origins[0])['time'] try: args = (seedid[:-1] + stations[seedid], origin_time) coords = inventory.get_coordinates(*args) except: # station not available at that time continue stats = rfstats(station=coords, event=event, phase=phase, **kwargs) if not stats: continue net, sta, loc, cha = seedid.split('.') starttime = stats.onset + request_window[0] endtime = stats.onset + request_window[1] kws = {'network': net, 'station': sta, 'location': loc, 'channel': cha, 'starttime': starttime - pad, 'endtime': endtime + pad} try: stream = get_waveforms(**kws) except: # no data available continue stream.trim(starttime, endtime) stream.merge() if len(stream) != 3: from warnings import warn warn('Need 3 component seismograms. %d components ' 'detected for event %s, station %s.' % (len(stream), event.resource_id, seedid)) continue if any(isinstance(tr.data, np.ma.masked_array) for tr in stream): from warnings import warn warn('Gaps or overlaps detected for event %s, station %s.' % (event.resource_id, seedid)) continue for tr in stream: tr.stats.update(stats) yield RFStream(stream, warn=False)
def iter_event_data(events, inventory, get_waveforms, phase='P', request_window=None, pad=10, pbar=None, **kwargs): """ Return iterator yielding three component streams per station and event. :param events: list of events or `~obspy.core.event.Catalog` instance :param inventory: `~obspy.core.inventory.inventory.Inventory` instance with station and channel information :param get_waveforms: Function returning the data. It has to take the arguments network, station, location, channel, starttime, endtime. :param phase: Considered phase, e.g. 'P', 'S', 'PP' :type request_window: tuple (start, end) :param request_window: requested time window around the onset of the phase :param float pad: add specified time in seconds to request window and trim afterwards again :param pbar: tqdm_ instance for displaying a progressbar :param kwargs: all other kwargs are passed to `~rf.rfstream.rfstats()` :return: three component streams with raw data Example usage with progressbar:: from tqdm import tqdm from rf.util import iter_event_data with tqdm() as t: for stream3c in iter_event_data(*args, pbar=t): do_something(stream3c) .. _tqdm: https://pypi.python.org/pypi/tqdm """ logger = logging.getLogger(__name__) from rf.rfstream import rfstats, RFStream method = phase[-1].upper() if request_window is None: request_window = (-50, 150) if method == 'P' else (-100, 50) # else: # print(f"\nRequested window is {request_window}") stations = _get_stations(inventory) # print(f"Available stations are {stations}") if pbar is not None: pbar.total = len(events) * len(stations) for event, seedid in itertools.product(events, stations): if pbar is not None: pbar.update(1) origin_time = (event.preferred_origin() or event.origins[0])['time'] # print(f"Origin time is {origin_time}") try: args = (seedid[:-1] + stations[seedid], origin_time) coords = inventory.get_coordinates(*args) # print(f"Station coords are {coords}") except Exception as exception: # station not available at that time logger.error("Station not available at given time", exc_info=True) continue try: stats = rfstats(station=coords, event=event, phase=phase, **kwargs) except: logger.warning(f"Unable to read for: {event}") pass if not stats: continue net, sta, loc, cha = seedid.split('.') starttime = stats.onset + request_window[0] endtime = stats.onset + request_window[1] kws = {'network': net, 'station': sta, 'location': loc, 'channel': cha, 'starttime': starttime - pad, 'endtime': endtime + pad} try: stream = get_waveforms(**kws) # print(f"stream obtained {len(stream)}") except: # no data available # logger.warning(f"No data available for {event}") continue stream.trim(starttime, endtime) stream.merge() # print(f"length of the stream is {len(stream)}") if len(stream) != 3: from warnings import warn warn(f'Need 3 component seismograms. {len(stream)} components ' 'detected for event {event.resource_id}, station {seedid}.') logger.warning(f'Need 3 component seismograms. {len(stream)} components ' 'detected for event {event.resource_id}, station {seedid}.') continue if any(isinstance(tr.data, np.ma.masked_array) for tr in stream): from warnings import warn logger.warning(f'Gaps or overlaps detected for event {event.resource_id}, station {seedid}.') continue for tr in stream: tr.stats.update(stats) yield RFStream(stream)