def test_fit_spectra(): config = get_config() datapath = os.path.join('data', 'testdata', 'demo', 'ci38457511', 'raw') datadir = pkg_resources.resource_filename('gmprocess', datapath) event = get_event_object('ci38457511') sc = StreamCollection.from_directory(datadir) for st in sc: st = signal_split(st, event) end_conf = config['windows']['signal_end'] st = signal_end(st, event_time=event.time, event_lon=event.longitude, event_lat=event.latitude, event_mag=event.magnitude, **end_conf) st = compute_snr(st, 30) st = get_corner_frequencies(st, method='constant', constant={ 'highpass': 0.08, 'lowpass': 20.0 }) for st in sc: spectrum.fit_spectra(st, event)
def snr_check(st, threshold=3.0, min_freq=0.2, max_freq=5.0, bandwidth=20.0): """ Check signal-to-noise ratio. Requires noise/singal windowing to have succeeded. Args: st (StationStream): Stream of data. threshold (float): Threshold SNR value. min_freq (float): Minimum frequency for threshold to be exeeded. max_freq (float): Maximum frequency for threshold to be exeeded. bandwidth (float): Konno-Omachi smoothing bandwidth parameter. Returns: stream: Streams with SNR calculations and checked that they pass the configured criteria. """ for tr in st: # Comput SNR tr = compute_snr(tr, bandwidth) if st.passed: snr_dict = tr.getParameter('snr') snr = np.array(snr_dict['snr']) freq = np.array(snr_dict['freq']) # Check if signal criteria is met min_snr = np.min(snr[(freq >= min_freq) & (freq <= max_freq)]) if min_snr < threshold: tr.fail('Failed SNR check; SNR less than threshold.') snr_dict = { 'threshold': threshold, 'min_freq': min_freq, 'max_freq': max_freq, 'bandwidth': bandwidth } tr.setParameter('snr_conf', snr_dict) return st
def test_corner_frequencies(): # Default config has 'constant' corner frequency method, so the need # here is to force the 'snr' method. data_files, origin = read_data_dir('geonet', 'us1000778i', '*.V1A') streams = [] for f in data_files: streams += read_data(f) sc = StreamCollection(streams) config = get_config() window_conf = config['windows'] processed_streams = sc.copy() for st in processed_streams: if st.passed: # Estimate noise/signal split time event_time = origin.time event_lon = origin.longitude event_lat = origin.latitude st = signal_split(st, origin) # Estimate end of signal end_conf = window_conf['signal_end'] event_mag = origin.magnitude print(st) st = signal_end( st, event_time=event_time, event_lon=event_lon, event_lat=event_lat, event_mag=event_mag, **end_conf ) wcheck_conf = window_conf['window_checks'] st = window_checks( st, min_noise_duration=wcheck_conf['min_noise_duration'], min_signal_duration=wcheck_conf['min_signal_duration'] ) pconfig = config['processing'] # Run SNR check # I think we don't do this anymore. test = [ d for d in pconfig if list(d.keys())[0] == 'compute_snr' ] snr_config = test[0]['compute_snr'] for stream in processed_streams: stream = compute_snr( stream, **snr_config ) # Run get_corner_frequencies test = [ d for d in pconfig if list(d.keys())[0] == 'get_corner_frequencies' ] cf_config = test[0]['get_corner_frequencies'] snr_config = cf_config['snr'] lp = [] hp = [] for stream in processed_streams: if not stream.passed: continue stream = get_corner_frequencies( stream, method="snr", snr=snr_config ) if stream[0].hasParameter('corner_frequencies'): cfdict = stream[0].getParameter('corner_frequencies') lp.append(cfdict['lowpass']) hp.append(cfdict['highpass']) np.testing.assert_allclose( np.sort(hp), [0.00751431, 0.01354455, 0.04250735], atol=1e-6 )
def test_corner_frequencies(): # Default config has 'constant' corner frequency method, so the need # here is to force the 'snr' method. data_files, origin = read_data_dir('geonet', 'us1000778i', '*.V1A') streams = [] for f in data_files: streams += read_data(f) sc = StreamCollection(streams) config = get_config() window_conf = config['windows'] processed_streams = sc.copy() for st in processed_streams: if st.passed: # Estimate noise/signal split time event_time = origin.time event_lon = origin.longitude event_lat = origin.latitude st = signal_split(st, origin) # Estimate end of signal end_conf = window_conf['signal_end'] event_mag = origin.magnitude print(st) st = signal_end(st, event_time=event_time, event_lon=event_lon, event_lat=event_lat, event_mag=event_mag, **end_conf) wcheck_conf = window_conf['window_checks'] st = window_checks( st, min_noise_duration=wcheck_conf['min_noise_duration'], min_signal_duration=wcheck_conf['min_signal_duration']) pconfig = config['processing'] # Run SNR check # I think we don't do this anymore. test = [d for d in pconfig if list(d.keys())[0] == 'compute_snr'] snr_config = test[0]['compute_snr'] for stream in processed_streams: stream = compute_snr(stream, **snr_config) # Run get_corner_frequencies test = [ d for d in pconfig if list(d.keys())[0] == 'get_corner_frequencies' ] cf_config = test[0]['get_corner_frequencies'] snr_config = cf_config['snr'] # With same_horiz False snr_config['same_horiz'] = False lp = [] hp = [] for stream in processed_streams: if not stream.passed: continue stream = get_corner_frequencies(stream, method="snr", snr=snr_config) if stream[0].hasParameter('corner_frequencies'): cfdict = stream[0].getParameter('corner_frequencies') lp.append(cfdict['lowpass']) hp.append(cfdict['highpass']) np.testing.assert_allclose(np.sort(hp), [0.00751431, 0.01354455, 0.04250735], atol=1e-6) st = processed_streams.select(station='HSES')[0] lps = [tr.getParameter('corner_frequencies')['lowpass'] for tr in st] hps = [tr.getParameter('corner_frequencies')['highpass'] for tr in st] np.testing.assert_allclose(np.sort(lps), [100., 100., 100.], atol=1e-6) np.testing.assert_allclose(np.sort(hps), [0.00305176, 0.00751431, 0.02527502], atol=1e-6) # With same_horiz True snr_config['same_horiz'] = True lp = [] hp = [] for stream in processed_streams: if not stream.passed: continue stream = get_corner_frequencies(stream, method="snr", snr=snr_config) if stream[0].hasParameter('corner_frequencies'): cfdict = stream[0].getParameter('corner_frequencies') lp.append(cfdict['lowpass']) hp.append(cfdict['highpass']) np.testing.assert_allclose(np.sort(hp), [0.00751431, 0.01354455, 0.04882812], atol=1e-6) st = processed_streams.select(station='HSES')[0] lps = [tr.getParameter('corner_frequencies')['lowpass'] for tr in st] hps = [tr.getParameter('corner_frequencies')['highpass'] for tr in st] np.testing.assert_allclose(np.sort(lps), [100., 100., 100.], atol=1e-6) np.testing.assert_allclose(np.sort(hps), [0.00751431, 0.00751431, 0.02527502], atol=1e-6)
def snr(tr, same_horiz=True, bandwidth=20): """Use constant corner frequencies across all records. Args: tr (StationTrace): Trace of data. same_horiz (bool): If True, horizontal traces in the stream must have the same corner frequencies. bandwidth (float): Konno-Omachi smoothing bandwidth parameter. Returns: stream: stream with selected corner frequencies appended to records. """ # Check for prior calculation of 'snr' if not tr.hasParameter('snr'): tr = compute_snr(tr, bandwidth) # If it doesn't exist then it must have failed because it didn't have # enough points in the noise or singal windows if not tr.hasParameter('failure'): snr_conf = tr.getParameter('snr_conf') threshold = snr_conf['threshold'] min_freq = snr_conf['min_freq'] max_freq = snr_conf['max_freq'] snr_dict = tr.getParameter('snr') snr = snr_dict['snr'] freq = snr_dict['freq'] # Loop through frequencies to find low corner and high corner lows = [] highs = [] have_low = False for idx, f in enumerate(freq): if have_low is False: if (snr[idx] >= threshold): lows.append(f) have_low = True else: continue else: if snr[idx] < threshold: highs.append(f) have_low = False else: continue # If we didn't find any corners if not lows: tr.fail('SNR not greater than required threshold.') return tr # If we find an extra low, add another high for the maximum # frequency if len(lows) > len(highs): highs.append(max(freq)) # Check if any of the low/high pairs are valid found_valid = False for idx, val in enumerate(lows): if (val <= min_freq and highs[idx] > max_freq): low_corner = val high_corner = highs[idx] found_valid = True if found_valid: tr.setParameter( 'corner_frequencies', { 'type': 'snr', 'highpass': low_corner, 'lowpass': high_corner } ) else: tr.fail('SNR not met within the required bandwidth.') return tr