def get_surface_wave_streams(stats, bounds): """get all components of surface waves, radial and vertical for rayleigh and transverse for love wave. currently case study for M8.2 Mexico quake. match stats to streams already being used """ from obspy import read, read_inventory, Stream mseeds, response = get_beacon(station=stats.station, channel="HHZ", start=stats.starttime, end=stats.endtime) st_gsw = Stream() for ms in mseeds: st_gsw += read(ms) inv = read_inventory(response) # preprocess in the same fashion as pyfreqscan decimate_by = int(st_gsw[0].stats.sampling_rate//stats.sampling_rate) st_gsw.trim(stats.starttime, stats.endtime) st_gsw.decimate(decimate_by) st_gsw.detrend("demean") st_gsw.detrend("linear") st_gsw.taper(max_percentage=0.05) st_gsw.attach_response(inv) st_gsw.remove_response(output="VEL", pre_filt=[.001,.01,50,55], # not in original code water_level=60, # not in original code plot=False) st_gsw.filter('bandpass', freqmin=bounds[0], freqmax=bounds[1]) return st_gsw
def beacon_waveforms(station_name, start, end, **kwargs): """ get beacon station waveforms based on station number :param number: :return: """ path = kwargs.get("path", None) inv_path = kwargs.get("inv_path", None) code = f"XX.{station_name}.10.HH?.D.{start.year}.{start.julday:0>3}" net, sta, loc, cha, d, year, jday = code.split(".") path = path.format(year=start.year, sta=sta) st = Stream() for fid in glob.glob(os.path.join(path, code)): st += read(fid) st.trim(start, end) inv = read_inventory(inv_path) # Will only attach the relevant response st.attach_response(inv) return st
def process_stream(st, inventory=None, remove_response_flag=False, water_level=60, filter_flag=False, pre_filt=None, starttime=None, endtime=None, resample_flag=False, sampling_rate=1.0, taper_type="hann", taper_percentage=0.05, rotate_flag=False, event_latitude=None, event_longitude=None, sanity_check=False): """ Stream processing function defined for general purpose of tomography. The advantage of using Stream, rather than than Trace, is that rotation could be operated if the Stream contains multiple channels. But this function also deals with Trace, but you need to set rotate_flag to False :param st: input stream :type st: obspy.Stream :param remove_response_flag: flag for remove instrument response. If True, then inv should be specified, and filter_flag would not be taken caren of. If you want just filter the seismogram, please leave this to False and set filter_flag to True. :type remove_response_flag: bool :param inventory: station inventory information :type inventory: obspy.Inventory :param water_level: water level used in remove instrument response. The default value in obspy is 60. :type water_level: float :param filter_flag:flag for filter the seismogram :type filter_flag: bool :param pre_filt: list of tuple of 4 corner frequency for filter, in ascending order(unit: Hz) :type pre_filt: list, tuple or numpy.array :param starttime: starttime of cutting :type starttime: obspy.UTCDateTime :param endtime: endtime of cutting :type endtime: obspy.UTCDateTime :param resample_flag: flag for data resampling :type resample_flag: bool :param sampling_rate: resampling rate(unit: Hz) :type sampling_rate: float :param taper_type: taper type, options from obspy taper :type taper_type: str :param taper_percentage: percentage of taper :type taper_percentage: float :param rotate_flag: rotate flag. If true, both inv and event location information should be provided :param event_latitude: latitude of event, for rotation usage :type event_latitude: float :param event_longitude: longitude of event, for rotation usage :type event_longitude: float :param sanity_check: sanity check the inventory information when rotating. :type sanity_check: bool :return: processed stream """ # check input data type if isinstance(st, Trace): st = Stream(traces=[ st, ]) _is_trace = True elif isinstance(st, Stream): _is_trace = False else: raise TypeError("Input seismogram should be either obspy.Stream " "or obspy.Trace") # cut the stream out before processing to reduce computation if starttime is not None and endtime is not None: st = flex_cut_stream(st, starttime, endtime, dynamic_npts=10) if filter_flag or remove_response_flag: # detrend ,demean, taper st.detrend("linear") st.detrend("demean") st.taper(max_percentage=taper_percentage, type=taper_type) # remove response or filter if filter_flag: if pre_filt is None or len(pre_filt) != 4: raise ValueError("Filter band should be list or tuple with " "length of 4") if not check_array_order(pre_filt, order="ascending"): raise ValueError("Input pre_filt must be in ascending order: %s" % pre_filt) if remove_response_flag: # remove response if inventory is None: raise ValueError("Station information(inv) should be provided if" "you want to remove instrument response") st.attach_response(inventory) if filter_flag: st.remove_response(output="DISP", pre_filt=pre_filt, zero_mean=False, taper=False, water_level=water_level) else: st.remove_response(output="DISP", zero_mean=False, taper=False) elif filter_flag: # Perform a frequency domain taper like during the response removal # just without an actual response... filter_stream(st, pre_filt) if filter_flag or remove_response_flag: # detrend, demean or taper st.detrend("linear") st.detrend("demean") st.taper(max_percentage=taper_percentage, type=taper_type) # resample if resample_flag: # interpolation if sampling_rate is None: raise ValueError("sampling rate should be provided if you set" "resample_flag=True") if endtime is not None and starttime is not None: npts = int((endtime - starttime) * sampling_rate) + 1 st = interpolate_stream(st, sampling_rate, starttime=starttime, npts=npts) else: # it doesn't matter if starttime is None or not, cause # obspy will handle this case st = interpolate_stream(st, sampling_rate, starttime=starttime) else: if starttime is not None and endtime is not None: # just cut st.trim(starttime, endtime) # rotate if rotate_flag: st = rotate_stream(st, event_latitude, event_longitude, inventory=inventory, mode="ALL->RT", sanity_check=sanity_check) # Convert to single precision to save space. for tr in st: tr.data = np.require(tr.data, dtype="float32") # transfer back to trace if input type is Trace if _is_trace: st = st[0] return st
def process_stream(st, inventory=None, remove_response_flag=False, water_level=60, filter_flag=False, pre_filt=None, starttime=None, endtime=None, resample_flag=False, sampling_rate=1.0, taper_type="hann", taper_percentage=0.05, rotate_flag=False, event_latitude=None, event_longitude=None, sanity_check=False): """ Stream processing function defined for general purpose of tomography. The advantage of using Stream, rather than than Trace, is that rotation could be operated if the Stream contains multiple channels. But this function also deals with Trace, but you need to set rotate_flag to False :param st: input stream :type st: obspy.Stream :param remove_response_flag: flag for remove instrument response. If True, then inv should be specified, and filter_flag would not be taken caren of. If you want just filter the seismogram, please leave this to False and set filter_flag to True. :type remove_response_flag: bool :param inventory: station inventory information :type inventory: obspy.Inventory :param water_level: water level used in remove instrument response. The default value in obspy is 60. :type water_level: float :param filter_flag:flag for filter the seismogram :type filter_flag: bool :param pre_filt: list of tuple of 4 corner frequency for filter, in ascending order(unit: Hz) :type pre_filt: list, tuple or numpy.array :param starttime: starttime of cutting :type starttime: obspy.UTCDateTime :param endtime: endtime of cutting :type endtime: obspy.UTCDateTime :param resample_flag: flag for data resampling :type resample_flag: bool :param sampling_rate: resampling rate(unit: Hz) :type sampling_rate: float :param taper_type: taper type, options from obspy taper :type taper_type: str :param taper_percentage: percentage of taper :type taper_percentage: float :param rotate_flag: rotate flag. If true, both inv and event location information should be provided :param event_latitude: latitude of event, for rotation usage :type event_latitude: float :param event_longitude: longitude of event, for rotation usage :type event_longitude: float :param sanity_check: sanity check the inventory information when rotating. :type sanity_check: bool :return: processed stream """ # check input data type if isinstance(st, Trace): st = Stream(traces=[st, ]) _is_trace = True elif isinstance(st, Stream): _is_trace = False else: raise TypeError("Input seismogram should be either obspy.Stream " "or obspy.Trace") # cut the stream out before processing to reduce computation if starttime is not None and endtime is not None: st = flex_cut_stream(st, starttime, endtime, dynamic_npts=10) if filter_flag or remove_response_flag: # detrend ,demean, taper st.detrend("linear") st.detrend("demean") st.taper(max_percentage=taper_percentage, type=taper_type) # remove response or filter if filter_flag: if pre_filt is None or len(pre_filt) != 4: raise ValueError("Filter band should be list or tuple with " "length of 4") if not check_array_order(pre_filt, order="ascending"): raise ValueError("Input pre_filt must be in ascending order: %s" % pre_filt) if remove_response_flag: # remove response if inventory is None: raise ValueError("Station information(inv) should be provided if" "you want to remove instrument response") st.attach_response(inventory) if filter_flag: st.remove_response(output="DISP", pre_filt=pre_filt, zero_mean=False, taper=False, water_level=water_level) else: st.remove_response(output="DISP", zero_mean=False, taper=False) elif filter_flag: # Perform a frequency domain taper like during the response removal # just without an actual response... filter_stream(st, pre_filt) if filter_flag or remove_response_flag: # detrend, demean or taper st.detrend("linear") st.detrend("demean") st.taper(max_percentage=taper_percentage, type=taper_type) # resample if resample_flag: # interpolation if sampling_rate is None: raise ValueError("sampling rate should be provided if you set" "resample_flag=True") if endtime is not None and starttime is not None: npts = int((endtime - starttime) * sampling_rate) + 1 st = interpolate_stream(st, sampling_rate, starttime=starttime, npts=npts) else: # it doesn't matter if starttime is None or not, cause # obspy will handle this case st = interpolate_stream(st, sampling_rate, starttime=starttime) else: if starttime is not None and endtime is not None: # just cut st.trim(starttime, endtime) # rotate if rotate_flag: st = rotate_stream(st, event_latitude, event_longitude, inventory=inventory, mode="ALL->RT", sanity_check=sanity_check) # Convert to single precision to save space. for tr in st: tr.data = np.require(tr.data, dtype="float32") # transfer back to trace if input type is Trace if _is_trace: st = st[0] return st