Source code for pyatoa.utils.form

"""
Formatting functionality

Pyatoa relies on data structure being ordered and consistent throughout all the
various bits of data required, as well as a few standardized string formatters
to keep everything playing nice. Functions here will aid in reshaping data
into the correct formats.
"""
from pyasdf import ASDFDataSet
from obspy.core.event import Event


[docs] def channel_code(dt): """ Specfem outputs seismograms with channel band codes set by IRIS. Instrument codes are always X for synthetics, but band code will vary with the sampling rate of the data, return the correct code given a sampling rate. Taken from Appenix B of the Specfem3D cartesian manual (June 15, 2018) :type dt: float :param dt: sampling rate of the data in seconds :rtype: str :return: band code as specified by Iris :raises KeyError: when dt is specified incorrectly """ if dt >= 1: return "L" # long period elif 0.1 < dt < 1: return "M" # mid period elif 0.0125 < dt <= 0.1: return "B" # broad band elif 0.001 <= dt <= 0.0125: return "H" # high broad band elif 0.004 <= dt < 0.001: return "C" elif 0.001 <= dt < 0.0002: return "F" else: raise KeyError("Channel code does not exist for this value of 'dt'")
[docs] def format_iter(iteration): """ Format the iteration to be used in internal path naming and labelling. Standard is to format with a leading 'i' character followed by two digits. Inputs can be strings or integers. Assumes iterations won't go above 99. :type iteration: str or int :param iteration: input model number, e.g. 0, '0', 'i0', 'i00' :rtype: str :return: formatted model number, e.g. 'i00', or None if no matching format """ if isinstance(iteration, str): # If e.g. iteration = "0" if not iteration[0] == "i": iternum = f"i{iteration:0>2}" # If e.g. iteration = "m00" else: iternum = iteration # If e.g. iteration = 0 elif isinstance(iteration, int): iternum = f"i{iteration:0>2}" else: iternum = None return iternum
[docs] def format_step(count): """ Same as for iteration but step count is formatted with a leading 's' :type count: str or int :param count: input model number, e.g. 0, '0', 's0', 's00' :rtype: str :return: formatted model number, e.g. 's00', or None if no matching format """ if isinstance(count, str): if not count[0] == "s": stpcnt = f"s{count:0>2}" else: stpcnt = count elif isinstance(count, int): stpcnt = f"s{count:0>2}" else: stpcnt = None return stpcnt
[docs] def format_event_name(ds_or_event): """ Formalize the definition of Event ID in Pyatoa :type ds_or_event: pyasdf.ASDFDataSet or obspy.core.event.Event or str :param ds_or_event: get dataset event name from the event resource_id :rtype: str :return: the event name to be used for naming schema in the workflow """ # Extract the resource id dependent on the input file type if isinstance(ds_or_event, Event): rid = ds_or_event.resource_id.id elif isinstance(ds_or_event, str): rid = ds_or_event elif isinstance(ds_or_event, ASDFDataSet): rid = ds_or_event.events[0].resource_id.id else: raise TypeError("format_event_name() only accepts pyasdf.ASDFDataSet " "or obspy.core.event.Event objects") rid_up = rid.upper() # GeoNet Client: smi:nz.org.geonet/2018p130600 if "GEONET" in rid_up: return rid.split("/")[-1] # IRIS Client: smi:service.iris.edu/fdsnws/event/1/query?eventid=5197722 elif "IRIS" in rid_up: return rid.split("eventid=")[-1] # SPUD, GCMT: smi:local/ndk/C202005010101A/event # or CMTSOLUTION: smi:local/cmtsolution/2013p617227/event elif ("NDK" in rid_up) or ("CMTSOLUTION" in rid_up): return rid.split("/")[-2] # USGS Client: quakeml:earthquake.usgs.gov/fdsnws/event/1/... # ...query?eventid=ak0198gdhuwa&format=quakeml elif "USGS" in rid_up: rid_ = rid.split("eventid=")[-1] return rid_.split("&")[0] # USGS ANSS ComCat: quakeml:us.anss.org/event/20005ysu elif "ANSS" in rid_up: return rid.split("event/")[-1] else: raise NotImplementedError(f"Unexpected resource id format '{rid}', " "Please raise a GitHub issue and the " "developers will address this")