pysep ===== .. py:module:: pysep Submodules ---------- .. toctree:: :maxdepth: 1 /autoapi/pysep/declust/index /autoapi/pysep/pysep/index /autoapi/pysep/recsec/index /autoapi/pysep/utils/index Attributes ---------- .. autoapisummary:: pysep.__version__ pysep.logger pysep.ch pysep.FORMAT pysep.formatter Classes ------- .. autoapisummary:: pysep.Pysep pysep.Declust Functions --------- .. autoapisummary:: pysep.get_data pysep.read_sem pysep.read_stations pysep.read_events_plus Package Contents ---------------- .. py:data:: __version__ .. py:data:: logger .. py:data:: ch .. py:data:: FORMAT :value: '[%(asctime)s] - %(name)s - %(levelname)s: %(message)s' .. py:data:: formatter .. py:class:: Pysep(client='IRIS', minlatitude=None, minlongitude=None, maxlatitude=None, maxlongitude=None, user=None, password=None, use_mass_download=False, client_debug=False, timeout=600, llnl_db_path=None, event_selection='default', origin_time=None, event_latitude=None, event_longitude=None, event_depth_km=None, event_magnitude=None, seconds_before_event=20, seconds_after_event=20, reference_time=None, seconds_before_ref=100, seconds_after_ref=300, extra_download_pct=0.005, networks='*', stations='*', locations='*', channels='*', station_ids=None, mindistance_km=0, maxdistance_km=20000.0, minazimuth=0, maxazimuth=360, remove_clipped=True, remove_insufficient_length=True, remove_masked_data=True, fill_data_gaps=False, gap_fraction=1.0, detrend=True, demean=True, taper_percentage=0.0, rotate=None, resample_freq=None, scale_factor=1, remove_response=True, output_unit='VEL', water_level=60, pre_filt='default', phase_list=None, taup_model='ak135', config_file=None, log_level='DEBUG', legacy_naming=False, overwrite_event_tag=None, write_files='inv,event,stream,sac,config_file,station_list', plot_files='all', output_dir=None, overwrite=False, **kwargs) Download, preprocess, and save waveform data using ObsPy .. note:: Parameters for general data gathering control :type client: str :param client: ObsPy FDSN client to query data from, e.g., IRIS, LLNL, NCEDC or any FDSN clients accepted by ObsPy. Defaults to 'IRIS' :type minlatitude: float :param minlatitude: for event, station and waveform retrieval. Defines the minimum latitude for a rectangular bounding box that is used to search for data. Only used for events if `event_selection`=='search' :type maxlatitude: float :param maxlatitude: for event, station and waveform retrieval. Defines the maximum latitude for a rectangular bounding box that is used to search for data. Only used for events if `event_selection`=='search' :type minlongitude: float :param minlongitude: for event, station and waveform retrieval. Defines the minimum longitude for a rectangular bounding box that is used to search for data. Only used for events if `event_selection`=='search' :type maxlongitude: float :param maxlongitude: for event, station and waveform retrieval. Defines the maximum longitude for a rectangular bounding box that is used to search for data. Only used for events if `event_selection`=='search' :type user: str :param user: User ID if IRIS embargoes data behind passwords. This is passed into the instantiation of `client`. :type password: str :param password: Password if IRIS embargoes data behind passwords. This is passed into the instantiation of 'client' :type use_mass_download: bool :param use_mass_download: Use ObsPy's mass download option to download all available stations in the region regardless of data provider. :type client_debug: bool :param client_debug: turn on DEBUG mode for the ObsPy FDSN client, which outputs information-rich log messages to std out. Use for debugging when FDSN fails mysteriously. :type timeout: float :param timeout: time out time in units of seconds, passed to the `client` to determine how long to wait for return data before exiting. Defaults to 600s. :type llnl_db_path: str :param llnl_db_path: If `client`=='LLNL', PySEP assumes we are accesing data from the LLNL waveeform database (which must be stored local). Points to the path where this is saved. .. note:: Event selection parameters :type event_selection: str :param event_selection: How to define the Event which is used to define the event origin time and hypocentral location. - 'default': User defines Event `origin_time`, and location with `event_latitude` and `event_longitude` - 'search': PySEP will use `client` to search for a Catalog event defined by `event_origintime`, `event_magnitude` and `event_depth_km`. Buffer time around the `origin_time` can be defined by `seconds_before_event` and `seconds_after_event`. :type origin_time: str :param origin_time: the event origin time used as a central reference point for data gathering. Must be in a string format that is recognized by ObsPy UTCDateTime. For example '2000-01-01T00:00:00'. :type event_latitude: float :param event_latitude: latitude of the event in units of degrees. used for defining the event hypocenter and for removing stations based on distance from the event. :type event_longitude: float :param event_longitude: longitude of the event in units of degrees. used for defining the event hypocenter and for removing stations based on distance from the event. :type event_depth_km: float or NoneType :param event_depth_km: depth of event in units of kilometers. postive values for deeper depths. Used for: 1) `event_selection`=='search' 2) estimating phase arrivals with TauP 3) plotting events and title on source receiver maps If set to None, (2) and (3) will fail. Best-guesses are acceptable. :type event_magnitude: float or NoneType :param event_magnitude: event magnitude in Mw used for `event_selection`=='search' and source receiver map plotting. If provided as None, map plotting will fail. :type seconds_before_event: float :param seconds_before_event: For event selection only, only used if `event_selection`=='search'. Time [s] before given `origin_time` to search :param seconds_after_event: For event selection only, only used if `event_selection`=='search'. Time [s] after given `origin_time` to search for a matching catalog event from the given `client` .. note:: Waveform and station metadata gathering parameters :type reference_time: str :param reference_time: Waveform origin time. If not given, defaults to the event origin time. This allows for a static time shift from the event origin time, e.g., if there are timing errors with relation to the `origin_time`. Defaults to NoneType (`origin_time`). :type seconds_before_ref: float :param seconds_before_ref: For waveform fetching. Defines the time before `reference_time` to fetch waveform data. Units [s] :type seconds_after_ref: float :param seconds_after_ref: For waveform fetching. Defines the time after `reference_time` to fetch waveform data. Units [s] :type extra_download_pct: float :param extra_download_pct: extra download percentage. Adds a buffer around `origin_time` + `seconds_before_ref` + `extra_download_pct` (also -`seconds_after_ref`), which gathers a bit of extra data which will be trimmed away. Used because gathering data directly at the requested time limits may lead to shorter expected waveforms after resampling or preprocessing procedures. Given as a percent [0,1], defaults to .5%. :type networks: str :param networks: name or names of networks to query for, if names plural, must be a comma-separated list, i.e., 'AK,AT,AV'. Wildcards okay, defaults to '*'. :type stations: str :param stations: station name or names to query for. If multiple stations, input as a list of comma-separated values, e.g., 'STA01,STA02,STA03'. Wildcards acceptable, if using wildcards, use a '-' to exclude stations (e.g., '*,-STA01' will gather all stations available, except STA01. Defaults to '*' :type locations: str :param locations: locations name or names to query for, wildcard okay. See `stations` for inputting multiple location values. Default '*'. :type channels: str :param channels: channel name or names to query for, wildcard okay. If multiple stations, input as a list of comma-separated values, e.g., 'HH?,BH?'. Wildcards acceptable. Defaults to '*'. :type station_ids: list of str :param station_ids: an alternative to gathering based on individual codes, allow the user to input a direct list of trace IDs which will be broken up and used to gather waveforms and metadata. NOTE: OVERRIDES `network`, `stations`, `locations`, and `channels`, these parameters will NOT be used. Station ids should be provided as: ['NN.SSS.LL.CCC', ...] .. note:: Station removal and curtailing parameters :type mindistance_km: float :param mindistance_km: Used for removing stations and mass download option - Removing stations: Remove any stations who are closer than the given minimum distance away from event (units: km). Always applied - Mass Download: If `use_mass_download` is True and `domain_type`=='circular', defines the minimum radius around the event hypocenter to gather waveform data and station metadata :type maxdistance_km: float :param maxdistance_km: Used for removing stations and mass download option - Removing stations: Remove any stations who are farther than the given maximum distance away from event (units: km). Always applied - Mass Download: If `use_mass_download` is True and `domain_type`=='circular', defines the maximum radius around the event hypocenter to gather waveform data and station metadata :type minazimuth: float :param minazimuth: for station removal. stations whose azimuth relative to the event hypocenter that do not fall within the bounds [`minazimuth`, `maxazimuth`] are removed from the final list. Defaults to 0 degrees. :param minazimuth: for station removal. stations whose azimuth relative to the event hypocenter that do not fall within the bounds [`minazimuth`, `maxazimuth`] are removed from the final list. Defaults to 360 degrees. :type remove_clipped: bool :param remove_clipped: remove any clipped stations from gathered stations. Checks the max amplitude of against a maximum value expected for a 24 bit signal. Defaults False :type remove_insufficient_length: bool :param remove_insufficient_length: remove waveforms whose trace length does not match the average (mode) trace length in the stream. Defaults to True :type remove_masked_data: bool :param remove_masked_data: If `fill_data_gaps` is False or None, data with gaps that go through the merge process will contain masked arrays (essentially retaining gaps). By default, PySEP will remove these data during processing. To keep this data, set `remove_masked_data` == True. :type fill_data_gaps: str or int or float or bool :param fill_data_gaps: How to deal with data gaps (missing sections of waveform over a continuous time span). False by default, which means data with gaps are removed completely. Users who want access to data with gaps must choose how gaps are filled. See API for ObsPy.core.stream.Stream.merge() for how merge is handled: Options include: - 'mean': fill with the mean of all data values in the gappy data - : fill with a constant, user-defined value, e.g., 0 or 1.23 or 9.999 - 'interpolate': linearly interpolate from the last value pre-gap to the first value post-gap - 'latest': fill with the last value of pre-gap data - False: do not fill data gaps, which will lead to stations w/ data gaps being removed. NOTE: Be careful about data types, as there are no checks that the fill value matches the internal data types. This may cause unexpected errors. :type gap_fraction: float :param gap_fraction: if `fill_data_gaps` is not None, determines the maximum allowable fraction (percentage) of data that gaps can comprise. For example, a value of 0.3 means that 30% of the data (in samples) can be gaps that will be filled by `fill_data_gaps`. Traces with gap fractions that exceed this value will be removed. Defaults to 1. (100%) of data can be gaps. .. note:: Data processing parameters :type detrend: bool :param detrend: apply simple linear detrend as the first preprocessing step :type demean: bool :param demean: apply demeaning to data during instrument reseponse removal. Only applied if `remove_response` == True. :type taper_percentage: float :param taper_percentage: apply a taper to the waveform with ObsPy taper, fraction between 0 and 1 as the percentage of the waveform to be tapered Applied generally used when data is noisy, e.g., HutchisonGhosh2016 Note: To get the same results as the default taper in SAC, use max_percentage=0.05 and leave type as hann. Tapering also happens while resampling (see util_write_cap.py). Only applied if `remove_response` == True. :type rotate: list of str or NoneType :param rotate: choose how to rotate the waveform data. pre-rotation processing will be applied. Can include the following options (order insensitive): * ZNE: Rotate from arbitrary components to North, East, Up * RTZ: Rotate from ZNE to Radial, Transverse, Up * UVW: Rotate from ZNE to orthogonal UVW orientation If set to None, no rotation processing will take place. :type resample_freq: float :param resample_freq: frequency to resample data in units Hz. If not given, no data resampling will take place. Defaults to NoneType :type scale_factor: float :param scale_factor: scale all data by a constant factor Note: for CAP use 10**2 (to convert m/s to cm/s). Defaults to NoneType (no scaling applied) .. note:: Instrument response removal parameters :type remove_response: bool :param remove_response: remove instrument response using station response information gathered from `client`. Defaults to True. :type output_unit: str :param output_unit: the output format of the waveforms if instrument response removal is applied. Only relevant if `remove_response`==True. See ObsPy.core.trace.Trace.remove_response for acceptable values. Typical values are: 'DISP', 'VEL', 'ACC' (displacement [m], velocity [m/s], acceleration [m/s^2]). :type water_level: float or None :param water_level: a water level threshold to apply during filtering for small values. Passed to Obspy.core.trace.Trace.remove_response :type pre_filt: str, tuple or NoneType :param pre_filt: apply a pre-filter to the waveforms before deconvolving instrument response. Options are: * 'default': automatically calculate (f0, f1, f2, f3) based on the length of the waveform (dictating longest allowable period) and the sampling rate (dictating shortest allowable period). This is the default behavior. * NoneType: do not apply any pre-filtering * tuple of float: (f0, f1, f2, f3) define the corners of your pre filter in units of frequency (Hz) .. note:: SAC header control parameters :type phase_list: list of str :param phase_list: phase names to get ray information from TauP with. Defaults to 'ttall', which is ObsPy's default for getting all phase arrivals. Must match Phases expected by TauP (see ObsPy TauP documentation for acceptable phases). Earliest P and S phase arrivals will be added to SAC headers, the remainder will be discarded. :type taup_model: str :param taup_model: name of TauP model to use to calculate phase arrivals See also `phase_list` which defines phases to grab arrival data for. Defaults to 'AK135'. See ObsPy TauP documentation for avilable models. .. note:: PySEP Configuration parameters :type config_file: str :param config_file: path to YAML configuration file which will be used to overwrite internal default parameters. Used for command-line version of PySEP :type log_level: str :param log_level: Level of verbosity for the internal PySEP logger. In decreasing order of verbosity: 'DEBUG', 'INFO', 'WARNING', 'CRITICAL' :type legacy_naming: bool :param legacy_naming: if True, revert to old PySEP naming schema for event tags, which is responsible for naming the output directory and SAC files. Legacy filenames look something like '20000101000000.NN.SSS.LL.CC.c' (event origin time, network, station, location, channel, component). Default to False :type overwrite_event_tag: str or bool :param overwrite_event_tag: option to allow the user to set their own event tag, rather than the automatically generated one. - NoneType (default): use automatically generated event tag which consists of event origin time and Flinn-Engdahl region - '': empty string will dump ALL files into `output_dir`, no new directories will be made - str: User-defined event tag which will be created in `output_dir`, all files will be stored in {output_dir}/{overwrite_event_tag}/* .. note:: Output file and figure control :type write_files: str or NoneType :param write_files: Which files to write out after data gathering. 1) User-defined comma-separated list of the following - weights_az: write out CAP weight file sorted by azimuth - weights_dist: write out CAP weight file sorted by distance - weights_code: write out CAP weight file sorted by station code - station_list: write out a text file with station information - inv: save a StationXML (.xml) file (ObsPy inventory) - event: save a QuakeML (.xml) file (ObsPy Catalog) - stream: save an ObsPy stream in Mseed (.ms) (ObsPy Stream) - config_file: save YAML config file w/ all input parameters - sac: save all waveforms as SAC (.sac) files w/ correct headers - sac_raw: save raw waveforms. these are straight from the data center with no quality check and no SAC headers - sac_zne: save only ZNE channel SAC files - sac_rtz: save only RTZ channel SAC files - sac_uvw: save only UVW channel SAC files Example input: `write_files`=='inv,event,stream,sac' By Default: 'inv,event,stream,sac,config_file,station_list' 2) If NoneType or an empty string, no files will be written. 3) If 'all', write all files listed in (1) :type plot_files: str or NoneType :param plot_files: What to plot after data gathering. Should be a comma-separated list of the following: - map: plot a source-receiver map with event and all stations - record_section: plot a record section with default parameters - all: plot all of the above (default value) If None, no files will be plotted. :type output_dir: str :param output_dir: path to output directory where all the files and figures defined by `write_files` and `plot_files` will be stored. Defaults to the current working directory. :type overwrite: bool :param overwrite: If True, overwrite an existing PySEP event directory. This prevents Users from re-downloading data. Defaults to False. .. py:attribute:: event_tag :value: None .. py:attribute:: config_file :value: None .. py:attribute:: client :value: 'IRIS' .. py:attribute:: client_debug :value: False .. py:attribute:: timeout :value: 600 .. py:attribute:: _user :value: None .. py:attribute:: _password :value: None .. py:attribute:: taup_model :value: 'ak135' .. py:attribute:: use_mass_download :value: False .. py:attribute:: _extra_download_pct :value: 0.005 .. py:attribute:: event_selection :value: 'default' .. py:attribute:: seconds_before_event :value: 20 .. py:attribute:: seconds_after_event :value: 20 .. py:attribute:: event_latitude :value: None .. py:attribute:: event_longitude :value: None .. py:attribute:: event_depth_km :value: None .. py:attribute:: event_magnitude :value: None .. py:attribute:: networks :value: '*' .. py:attribute:: stations :value: '*' .. py:attribute:: channels :value: '*' .. py:attribute:: locations :value: '*' .. py:attribute:: station_ids :value: None .. py:attribute:: reference_time .. py:attribute:: seconds_before_ref :value: 100 .. py:attribute:: seconds_after_ref :value: 300 .. py:attribute:: llnl_db_path :value: '/store/raw/LLNL/UCRL-MI-222502/westernus.wfdisc' .. py:attribute:: mindistance_km :value: 0 .. py:attribute:: maxdistance_km :value: 20000.0 .. py:attribute:: minazimuth :value: 0 .. py:attribute:: maxazimuth :value: 360 .. py:attribute:: minlatitude :value: None .. py:attribute:: maxlatitude :value: None .. py:attribute:: minlongitude :value: None .. py:attribute:: maxlongitude :value: None .. py:attribute:: demean :value: True .. py:attribute:: detrend :value: True .. py:attribute:: taper_percentage :value: 0.0 .. py:attribute:: rotate :value: None .. py:attribute:: remove_response :value: True .. py:attribute:: output_unit :value: 'VEL' .. py:attribute:: water_level :value: 60 .. py:attribute:: pre_filt :value: 'default' .. py:attribute:: scale_factor :value: 1 .. py:attribute:: resample_freq :value: None .. py:attribute:: remove_clipped :value: True .. py:attribute:: remove_insufficient_length :value: True .. py:attribute:: remove_masked_data :value: True .. py:attribute:: fill_data_gaps :value: False .. py:attribute:: gap_fraction :value: 1.0 .. py:attribute:: _output_dir .. py:attribute:: output_dir :value: None .. py:attribute:: write_files :value: 'inv,event,stream,sac,config_file,station_list' .. py:attribute:: plot_files :value: 'all' .. py:attribute:: log_level :value: 'DEBUG' .. py:attribute:: legacy_naming :value: False .. py:attribute:: _overwrite :value: False .. py:attribute:: _overwrite_event_tag :value: None .. py:attribute:: c :value: None .. py:attribute:: st :value: None .. py:attribute:: inv :value: None .. py:attribute:: event :value: None .. py:attribute:: st_raw :value: None .. py:attribute:: kwargs .. py:method:: check() Check input parameter validity against expected Pysep behavior .. py:method:: get_client() Options to choose different Clients based on attribute `client` which will be used to gather waveforms and metadata :rtype: obspy.clients.fdsn.client.Client :return: Client used to gather waveforms and metadata .. py:method:: load(config_file=None, overwrite_event=True) Overwrite default parameters using a YAML config file :type config_file: str :param config_file: YAML configuration file to load from :type overwrite_event: bool :param overwrite_event: overwrite event search parameters (origin time, lat, lon etc.) from the YAML config file. Defaults to True .. py:method:: get_event() Exposed API for grabbing event metadata depending on the `event_selection` choice. Options for `event_selection` are: 'search': query FDSN with event parameters 'default': create an event from scratch using user parameters or if 'client'=='LLNL', grab event from internal database :rtype: obspy.core.event.Event :return: Matching event given event criteria. If multiple events are returned with the query, returns the first in the catalog .. py:method:: _query_event_from_client(magnitude_buffer=0.1, depth_buffer_km=1.0) Retrieve an event catalog using ObsPy Client.get_events(). Searches Client for a given origin time, location, depth (optional) and magnitude (optional). To use this, set attribute `event_selection`=='search' :type magnitude_buffer: float :param magnitude_buffer: if attribute `event_magnitude` is given, will search events for events with magnitude: event_magnitude +/- magnitude_buffer :type depth_buffer_km: float :param depth_buffer_km: if attribute `event_depth_km` is given, will search events for events with depth: event_depth_km +/- depth_buffer_km :rtype: obspy.core.event.Event :return: Matching event given event criteria. If multiple events are returned with the query, returns the first in the catalog .. py:method:: _create_event_from_scratch() Make a barebones event object based on user-defined parameters which will then be used to query for waveforms and StationXML data :rtype: obspy.core.event.Event :return: Event object with origin and magnitude information appended .. py:method:: _get_event_from_llnl_catalog() Special getter function for Lawrence Livermore National Lab data LLNL database has a special client TODO Do we need more filtering in the catalog? :rtype: obspy.core.event.Event :return: Event information queried from LLNL database .. py:method:: get_stations() Exposed API for grabbing station metadata from client. Download station metadata using ObsPy get_stations() with a user-defined bounding box and for user-defined networks, stations etc. :rtype: obspy.core.inventory.Inventory :return: Station metadata queried from Client .. py:method:: get_waveforms() Exposed API for grabbing waveforms from client. Internal logic determines how waveforms are queried, but mainly it is controlled by the internal `inv` attribute detailing station information, and reference times for start and end times. .. note:: We do not use the `minimumlength` variable so that we can figure out which stations have data gaps :rtype: obspy.core.stream.Stream :return: Stream of channel-separated waveforms .. py:method:: _bulk_query_waveforms_from_client() Make a bulk request query to the Client based on the internal `inv` attribute defining the available station metadata. :rtype: obspy.core.stream.Stream :return: Stream of channel-separated waveforms .. py:method:: mass_download() Use ObsPy Mass downloader to grab events from a pre-determined region :keyword str domain_type: How to define the search region domain - rectangular: rectangular bounding box defined by min/max latitude/longitude - circular: circular bounding circle defined by the events latitude and longitude, with radii defined by `mindistance_km` and `maxdistance_km` :keyword bool delete_tmpdir: Remove the temporary directories that store the MSEED and StationXML files which were downloaded by the mass downloader. Saves space but also if anything fails prior to saving data, the downloaded data will not be saved. Defaults to True. .. py:method:: curtail_stations() Remove stations from `inv` based on station distance, azimuth, etc. .. note:: One-function function currently, but we can expand curtailing here if need by :rtype: obspy.core.inventory.Inventory :return: station metadata that has been curtailed based on acceptable paramaters .. py:method:: preprocess() Very simple preprocessing to remove response and apply a prefilter scale waveforms (if necessary) and clean up waveform time series :rtype: obspy.core.stream.Stream :return: a preprocessed stream with response removed, amplitude scaled (optional), and time series standardized .. py:method:: _remove_response_llnl(st) Remove response information from LLNL stations. This requires using the custom LLNL DB client. There are also some internal checks that need to be bypassed else they cause the program to crash .. py:method:: rotate_streams() Rotate arbitrary three-component seismograms to desired orientation 'ZNE', 'RTZ' or 'UVW'. .. warning:: This function combines all traces, both rotated and non-rotated components (ZNE, RTZ, UVW, but not raw, e.g., 12Z), into a single stream. This is deemed okay because we don't do any component-specific operations after rotation. :rtype: obspy.core.stream.Stream :return: a stream that has been rotated to desired coordinate system with SAC headers that have been adjusted for the rotation, as well as non-rotated streams which are saved incase user needs access to other components .. py:method:: write(write_files=None, _return_filenames=False, _subset=None, **kwargs) Write out various files specifying information about the collected stations and waveforms. Options are: * config_file: write the current configuration as a YAML file * station_list: write a text file with station information * inv: write the inventory as a StationXML file * event: write the event as a QuakeML file * stream: write the stream as a single MSEED file * sac_zne: write the stream as individual (per-channel) SAC files for ZNE components with the appropriate SAC header * sac_rtz: write out per-channel SAC files for RTZ components * sac_uvw: write out per-channel SAC files for UVW components * weights_dist: write out CAP 'weights.dat' file sorted by distance * weights_az: write out CAP 'weights.dat' file sorted by azimuth * weights_code: write out CAP 'weights.dat' file sorted by sta code :type write_files: list of str :param write_files: list of files that should be written out, must match the acceptable list defined in the function or here in the docstring. If not given, defaults to internal list of files :type _return_filenames: bool :param _return_filenames: internal flag to not actually write anything but just return a list of acceptable filenames. This keeps all the file naming definitions in one function. This is only required by the check() function. :type _subset: list :param _subset: internal parameter used for intermediate file saving. PySEP will attempt to save files once they have been collected however if the files it tries to save do not match against the User-defined file list, they will be ignored. :keyword str order_station_list_by: how to order the station list available options are: network, station, latitude, longitude, elevation, burial. :keyword str config_fid: optional name for the configuration file name defaults to 'pysep_config.yaml' :keyword str station_fid: optional name for the stations list file name defaults to 'station_list.txt' :keyword str inv_fid: optional name for saved ObsPy inventory object, defaults to 'inv.xml' :keyword str event_fid: optional name for saved ObsPy Event object, defaults to 'event.xml' :keyword str stream_fid: optional name for saved ObsPy Stream miniseed object, defaults to 'stream.ms' :keyword str sac_subdir: sub-directory within output directory and event directory to save SAC files. Defaults to SAC/. Use an empty string to dump files directly into the event directory .. py:method:: _write_sac(st, output_dir=os.getcwd(), components=None) Write SAC files with a specific naming schema, which allows for both legacy (old PySEP) or non-legacy (new PySEP) naming. :type st: obspy.core.stream.Stream :param st: Stream to be written :type output_dir: str :param output_dir: where to save the SAC files, defaults to the current working directory :type components: str :param components: acceptable component values for saving files, allows only saving subsets of the Stream. Example 'RTZNE' or just 'R'. Must match against Trace.stats.component .. py:method:: write_config(fid=None, overwrite=False) Write a YAML config file based on the internal `Pysep` attributes. Remove a few internal attributes (those containing data) before writing and also change types on a few to keep the output file simple but also re-usable for repeat queries. :type fid: str :param fid: name of the file to write. defaults to config.yaml :type overwrite: bool :param overwrite: if True and `fid` already exists, save a new config file with the same name, overwriting the old file. if False (default), throws a warning if encountering existing `fid` and does not write config file .. py:method:: plot() Plot map and record section if requested. Allow general error catching for mapping and record section plotting because we don't want these auxiliary steps to crash the entire workflow since they are not critical. .. py:method:: _event_tag_and_output_dir() Convenience function to establish and naming schema for files and directories. Also takes care of making empty directories. :rtype: tuple of str :return: (unique event tag, path to output directory) .. py:method:: _set_log_file(mode) Write logger to file as well as stdout, with the same format as the stdout logger. Need mode==1 to move the log file after everything is done because we don't know the event tag prior to starting the logs :type mode: int :param mode: Two options for using this function 0: set the logger to a temporary file 'pysep.log', 1: move the logger from the temporary file into final output dir .. py:method:: run(event=None, inv=None, st=None, **kwargs) Run PySEP: Seismogram Extraction and Processing. Steps in order are: 1) Set default parameters or load from config file 2) Check parameter validity, exit if unexpected values 3) Get data and metadata (QuakeML, StationXML, waveforms) 4) Remove unacceptable stations based on user-defined criteria 5) Remove unacceptable waveforms based on user-defined criteria 6) Generate some new metadata for tagging and output 7) Pre-process waveforms and standardize for general use 8) Generate output files and figures as end-product :type event: obspy.core.event.Event :param event: optional user-provided event object which will force a skip over QuakeML/event searching :type inv: obspy.core.inventory.Inventory :param inv: optional user-provided inventory object which will force a skip over StationXML/inventory searching :type st: obspy.core.stream.Stream :param st: optional user-provided strean object which will force a skip over waveform searching .. py:function:: get_data(config_file=None, event=None, inv=None, st=None, write_files=None, plot_files=None, log_level=None, *args, **kwargs) Interactive/scripting function to run PySep and return quality controlled, SAC-headed stream object which can then be used for other processes. .. note:: By default turns file writing and plotting OFF so that this function acts solely as a data collection/processing call. .. note:: args and kwargs are passed directly to Pysep.__init__() so you can define all your parameters in this call, or through a config file .. rubric:: >>> from pysep import get_data >>> st = get_data(config_file='config.yaml') :type config_file: str :param config_file: path to YAML config file which will overload any default configs :type event: obspy.core.event.Event :param event: optional user-provided event object which will force a skip over QuakeML/event searching :type inv: obspy.core.inventory.Inventory :param inv: optional user-provided inventory object which will force a skip over StationXML/inventory searching :type st: obspy.core.stream.Stream :param st: optional user-provided strean object which will force a skip over waveform searching :type write_files: list or None :param write_files: list of files to write, acceptable options defined in write(). Defaults to None, no files will be written :type plot_files: list or None :param plot_files: list of files to plot, acceptable options defined in plot(). Defaults to None, no figures will be made :type log_level: str or None :param log_level: verbosity of logger. Defaults to no logging to mimic a standard function call rather than a standalone package :rtype: tuple of (obspy.core.event.Event, obspy.core.inventory.Inventory, obspy.core.stream.Stream) :return: returns obspy objects defining data and metadata that have been collected by PySEP .. py:class:: Declust(cat, inv=None, data_avail=None, min_lat=None, max_lat=None, min_lon=None, max_lon=None) Declustering class in charge of declustering and source receiver weighting User-input parameters to determine algorithm behavior :type cat: obspy.core.catalog.Catalog :param cat: Catalog of events to consider. Events must include origin information `latitude` and `longitude` :type inv: obspy.core.inventory.Inventory :param inv: Inventory of stations to consider :type data_avail: dict :param data_avail: If None, Declust assumes that all events in `cat` were recorded by all stations in `inv`. This is typically not the case however, so this dict allows the user to tell `Declust` about data availability. Keys of `data_avail` must match resource IDs, and values must be lists of station names (NN.SSSS) :type min_lat: float :param min_lat: optional, minimum latitude for bounding box defining the region of interest. If not given, will use the minimum latitude in the catalog of events :type max_lat: float :param max_lat: optional, maximum latitude for bounding box defining the region of interest. If not given, will use the maximum latitude in the catalog of events :type min_lon: float :param min_lon: optional, minimum longitude for bounding box defining the region of interest. If not given, will use the minimum longitude in the catalog of events :type max_lon: float :param max_lon: optional, maximum longitude for bounding box defining the region of interest. If not given, will use the maximum longitude in the catalog of events .. py:attribute:: cat .. py:attribute:: inv :value: None .. py:attribute:: _user_min_lat :value: None .. py:attribute:: _user_max_lat :value: None .. py:attribute:: _user_min_lon :value: None .. py:attribute:: _user_max_lon :value: None .. py:attribute:: _user_data_avail :value: None .. py:attribute:: evlats :value: None .. py:attribute:: evlons :value: None .. py:attribute:: evids :value: None .. py:attribute:: stalats :value: None .. py:attribute:: stalons :value: None .. py:attribute:: staids :value: None .. py:attribute:: min_lat :value: None .. py:attribute:: max_lat :value: None .. py:attribute:: min_lon :value: None .. py:attribute:: max_lon :value: None .. py:attribute:: depths :value: None .. py:attribute:: mags :value: None .. py:attribute:: data_avail :value: None .. py:attribute:: navail :value: None .. py:method:: update_metadata(cat=None, inv=None) Get metadata like location and event depth and magnitude from a given Cat and Inv and set as internal attributes. Needs to be as separate function as `threshold_events` will cut down the internal catalog representation so this will need to be re-run .. py:method:: threshold_catalog(zedges=None, min_mags=None, min_data=None) Kick out events that fall below a given magnitude range or a given data availability range. Allow this to be done for various depth ranges or for the entire volume at once. .. note:: Updates internal `cat` Catalog object and metadata in place :type zedges: list of float :param zedges: depth [km] slices to partition domain into when thresholding data :type min_mags: int or list :param min_mags: a list of minimum magnitude thresholds for each depth slice. If `zedges` is None, should be a list of length==1, which provides minimum magnitude for entire catalog. Elif `zedges` is given, should be a list of len(zedges)-1, which defines minimum magnitude for each depth bin. For example if zedges=[0, 35, 400], then one example is min_mags=[4, 6]. Meaning between 0-34km the minimum magnitude is 4, and between 35-400km the minimum magnitude is 6. :type min_data: int or list :param min_data: an integer or list of length len(zedges)-1 that defines the minimum number of stations on for a given event origin time, which allows user to prioritize stations with available data .. py:method:: calculate_srcrcv_weights(cat=None, inv=None, write='weights.txt', plot=False, show=False, save='srcrcvwght.png') Calculate event and station specific weights based on event geographic weights, and event-dependent station geographic weights which take into account data availability for each event. Uses the internal `cat` and `inv` attributes of the class. If declustering was run to thin out the catalog, run `update_metadata` first to update internal attributes which are used for defining weights. :type cat: obspy.core.catalog.Catalog :param cat: Optional, catalog of events to consider. If none given, will use whatever internal catalog is available :type inv: obspy.core.inventory.Inventory :param inv: Inventory of stations to consider :type plot: bool :param plot: plot source weights and an average of station weights on a single figure. :type write: str :param write: filename used to write station weights to text file. if None, will not write :type show: bool :param show: show figure in GUI :type save: str :param save: if given, file id for the name of the output figure to save if not given, will not save figure :rtype: np.array :return: a 2D array where each row corresponds to a station and each column corresponds to an event. The value for a given row and column is the weight of that station w.r.t all other available stations. Stations that were not available (not on) are given a weight of 0 .. py:method:: _get_weights(lons, lats, norm=None, plot=False, save='reference_distance_scan.png') Given a set of coordinates (either stations or earthquakes), calculate a reference distance and a set of weights for each coordinate. Reference distance is chosen as one-third the largest possible value for all possible reference distances :type lons: np.array :param lons: array of longitude values :type lats: np.array :param lats: array of latitude values :type plot: bool :param plot: plot a simple scatterplot showing the weights for each station :type norm: str :param norm: how to normalize the weights - None: don't normalize, provide raw weights - 'max': normalize by the maximum weight - 'len': normalize by the length of the array - 'avg': normalize by the mean weight value :rtype: np.array :return: relative, normalized weights for each lon/lat pair .. py:method:: _covert_dist_to_weight(dists, ref_dist) :staticmethod: Calculate distance weights from a matrix of distances and a reference distance :type dists: np.array :param dists: array of inter-source distances :type ref_dist: float :param ref_dist: user-defined reference distance in units km. larger values for reference distances increase the sensitivity to inter-station distances. lower values tend to reduce scatter. .. py:method:: decluster_events(cat=None, inv=None, choice='cartesian', zedges=None, min_mags=None, nkeep=1, select_by='magnitude', **kwargs) Main logic function for choosing how to decluster events. Allow for both cartesian and polar binning of the domain. See `_decluster_events_cartesian` and `_decluster_events_polar` for specific input parameters to control declustering. :type cat: obspy.core.catalog.Catalog :param cat: Optional, catalog of events to consider. If none given, will use whatever internal catalog is available :type inv: obspy.core.inventory.Inventory :param inv: Inventory of stations to consider :type choice: str :param choice: choice of domain partitioning, can be one of: - cartesian: grid the domain as a cube with `nx` by `ny` cells - polar: grid the domain with polar coordinates and `ntheta` bins :type zedges: list of float :param zedges: depth [km] slices to partition domain into. Each slice will be given equal weighting w.r.t to all other slices, independent of slice size. e.g., allows upweighting crustal events :type min_mags: list :param min_mags: a list of minimum magnitude thresholds for each depth slice. If `zedges` is None, should be a list of length==1, which provides minimum magnitude for entire catalog. Elif `zedges` is given, should be a list of len(zedges)-1, which defines minimum magnitude for each depth bin. For example if zedges=[0, 35, 400], then one example is min_mags=[4, 6]. Meaning between 0-34km the minimum magnitude is 4, and between 35-400km the minimum magnitude is 6. :type nkeep: int or list of int :param nkeep: number of events to keep per cell. If `zedges` is None, then this must be an integer which defines a blanket value to apply. If `zedges` is given, then this must be a list of length `zedges` - 1, defining the number of events to keep per cell, per depth slice. See `min_mags` definition for example. :type select_by: str :param select_by: determine how to prioritize events in the cell - magnitude (default): largest magnitudes prioritized - magnitude_r: smallest magnitudes prioritized - depth: shallower depths prioritized - depth_r: deeper depths prioritized - data: prioritize events which have the most data availability .. py:method:: _decluster_events_cartesian(nx=10, ny=10, zedges=None, nkeep=1, select_by='magnitude_r', plot=False, plot_dir='./', **kwargs) Decluster event catalog by partitioning the 3D domain in the X, Y and Z directions, and then selecting a given number of events in each cell. :type nx: int :param nx: Number of X/longitude cells to partition domain into :type ny: int :param ny: Number of Y/latitude cells to partition domain into :type zedges: list of float :param zedges: depth [km] slices to partition domain into. Each slice will be given equal weighting w.r.t to all other slices, independent of slice size. e.g., allows upweighting crustal events :type nkeep: int or list of int :param nkeep: number of events to keep per cell. If `zedges` is None, then this must be an integer which defines a blanket value to apply. If `zedges` is given, then this must be a list of length `zedges` - 1, defining the number of events to keep per cell, per depth slice. See `min_mags` definition for example. :type select_by: str :param select_by: determine how to prioritize events in the cell - magnitude (default): largest magnitudes prioritized - magnitude_r: smallest magnitudes prioritized - depth: shallower depths prioritized - depth_r: deeper depths prioritized - data: less data availability prioritized - data_r: more data availability prioritized :type plot: bool :param plot: create a before and after catalog scatter plot to compare which events were kept/removed. Plots within the cwd :type plot_dir: str :param plot_dir: directory to save figures to. file names will be generated automatically :rtype: obspy.core.catalog.Catalog :return: a declustered event catalog .. py:method:: _decluster_events_polar(ntheta=16, zedges=None, nkeep=1, select_by='magnitude_r', plot=False, plot_dir='./', **kwargs) Run the declustering agorithm but partition the domain in polar. That is, divide each depth slice into a pie with `ntheta` partitions and keep events based on events within each slice of the pie. Option to cut each slice of pie by radius (distance from center of domain) and put additional constraints (e.g., more distant events require larger magnitude). :type ntheta: int :param ntheta: Number of theta bins to break a polar search into. Used to break up 360 degrees, so e.g., `ntheta`==17 will return bins of size 22.5 degrees ([0, 22.5, 45., 67.5 .... 360.]) :type zedges: list of float :param zedges: depth [km] slices to partition domain into. Each slice will be given equal weighting w.r.t to all other slices, independent of slice size. e.g., allows upweighting crustal events :type nkeep: int or list of int :param nkeep: number of events to keep per cell. If `zedges` is None, then this must be an integer which defines a blanket value to apply. If `zedges` is given, then this must be a list of length `zedges` - 1, defining the number of events to keep per cell, per depth slice. See `min_mags` definition for example. :type select_by: str :param select_by: determine how to prioritize events in the cell - magnitude (default): largest magnitudes prioritized - magnitude_r: smallest magnitudes prioritized - depth: shallower depths prioritized - depth_r: deeper depths prioritized - data: less data availability prioritized - data_r: more data availability prioritized :type plot: bool :param plot: create a before and after catalog scatter plot to compare which events were kept/removed. Plots within the cwd :type plot_dir: str :param plot_dir: directory to save figures to. file names will be generated automatically :rtype: obspy.core.catalog.Catalog :return: a declustered event catalog .. py:method:: plot(cat=None, inv=None, color_by='depth', connect_data_avail=False, vmin=None, vmax=None, title=None, cmap='inferno_r', show=True, save=None, equal_scale=False, **kwargs) Geranalized plot function used to plot an event catalog and station inventory. :type cat: obspy.core.catalog.Catalog :param cat: Catalog of events to consider. Events must include origin information `latitude` and `longitude` :type inv: obspy.core.inventory.Inventory :param inv: Inventory of stations to consider :type color_by: str :param color_by: how to color the event markers, available are - 'depth': color by the event depth - 'data': color by data availability for given event - 'custom': used by internal plotting routines to provide custom color array to the plot :type connect_data_avail: bool :param connect_data_avail: connect sources and receivers with a thin line based on data availability :type vmin: float :param vmin: min value for the colorbar, defaults to smallest value in array defined by `color_by` :type vmax: float: :param vmax: maximum value for colorbar, defaults to largest value in the array defined by `color_by` :type title: str :param title: custom user-input title for the figure, otherwise defaults to useful information about the catalog and inventory :type cmap: str :param cmap: matplotlib colormap to use for array defined by `color_by` :type show: bool :param show: show figure in GUI :type save: str :param save: if given, file id for the name of the output figure to save if not given, will not save figure :type equal_scale: bool :param equal_scale: set the scale of lat and lon equal, False by default .. py:method:: _plot_cartesian(cat, inv, xedges, yedges, title, save) Convenience function to plot catalogs with edges .. py:method:: _plot_polar(cat, inv, evrad, theta_array, mid_lon, mid_lat, title, save) Convenience function to plot catalogs with radial bin lines .. py:function:: read_sem(fid, origintime='1970-01-01T00:00:00', source=None, stations=None, location='', precision=4, source_format='CMTSOLUTION') Specfem3D outputs seismograms to ASCII (.sem? or .sem.ascii) files. Converts SPECFEM synthetics into ObsPy Stream objects with the correct header information. If `source` and `stations` files are also provided, PySEP will write appropriate SAC headers to the underlying data. :type fid: str :param fid: path of the given ascii file :type origintime: obspy.UTCDateTime :param origintime: UTCDatetime object for the origintime of the event. If None given, defaults to dummy value of '1970-01-01T00:00:00' :type source: str :param source: optional SPECFEM source file (e.g., CMTSOLUTION, SOURCE) defining the event which generated the synthetics. Used to grab event information and append as SAC headers to the ObsPy Stream :type stations: str :param stations: optional STATIONS file defining the station locations for the SPECFEM generated synthetics, used to generate SAC headers :type location: str :param location: location value for a given station/component :type precision: int :param precision: dt precision determined by differencing two adjancent time steps in the underlying ascii text file. :rtype st: obspy.Stream.stream :return st: stream containing header and data info taken from ascii file .. py:function:: read_stations(path_to_stations) Convert a SPECFEM STATIONS file into an ObsPy Inventory object. Specfem3D STATION files contain no channel or location information, so the inventory can only go down to the station level. .. note:: This assumes a row structure for the station file is STA, NET, LAT [deg], LON [deg], ELEVATION [m], BURIAL [m] :type path_to_stations: str :param path_to_stations: the path to the STATIONS file that is associated with the Specfem3D DATA directory :rtype: obspy.core.inventory.Inventory :return: a station-level Inventory object :raises ValueError: if latitude and longitude values are not in geographic coordinates (i.e., in cartesian coordinates). Thrown by the init of the Station class. .. py:function:: read_events_plus(fid, format, **kwargs) Addition to the base ObsPy.read_events() function that, in addition to the acceptable formats read by ObsPy, can also read the following: * SPECFEM2D SOURCE * SPECFEM3D/3D_GLOBE FORCESOLUTION * SPECFEM3D/3D_GLOBE CMTSOLUTION (both geographic and non-geographic) See the following link for acceptable ObsPy formats: See the following link for acceptable ObsPy formats: https://docs.obspy.org/packages/autogen/obspy.core.event.read_events.html :type fid: str :param fid: full path to the event file to be read :type format: str :param format: Expected format of the file (case-insensitive), available are - SOURCE - FORCESOLUTION - CMTSOLUTION - any of ObsPy's accepted arguments for ObsPy.read_events() :rtype: obspy.core.catalog.Catalog :return: Catalog which should only contain one event, read from the `fid` for the given `fmt` (format)