Source code for pyflex.config

#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
Configuration object for pyflex.

:copyright:
    Lion Krischer (krischer@geophysik.uni-muenchen.de), 2014
:license:
    GNU General Public License, Version 3
    (http://www.gnu.org/copyleft/gpl.html)
"""
from __future__ import (absolute_import, division, print_function,
                        unicode_literals)
from future.builtins import *  # NOQA

import collections
import numpy as np

from . import PyflexError


[docs]class Config(object): def __init__(self, min_period, max_period, stalta_waterlevel=0.07, tshift_acceptance_level=10.0, tshift_reference=0.0, dlna_acceptance_level=1.3, dlna_reference=0.0, cc_acceptance_level=0.7, s2n_limit=1.5, earth_model="ak135", min_surface_wave_velocity=3.0, max_time_before_first_arrival=50.0, c_0=1.0, c_1=1.5, c_2=0.0, c_3a=4.0, c_3b=2.5, c_4a=2.0, c_4b=6.0, check_global_data_quality=False, snr_integrate_base=3.5, snr_max_base=3.0, noise_start_index=0, noise_end_index=None, signal_start_index=None, signal_end_index=-1, window_weight_fct=None, window_signal_to_noise_type="amplitude", resolution_strategy="interval_scheduling"): """ Central configuration object for Pyflex. This replaces the old PAR_FILEs and user functions. It has sensible defaults for most values but you will probably want to adjust them for your given application. If necessary, the acceptance levels/limits can also be set as arrays. Each array must have the same number of samples as the observed and synthetic data. The corresponding values are then evaluated seperately at each necessary point. This enables the full emulation of the user functions in the original FLEXWIN code. The following basic example illustrates the concept which can become arbitrarily complex. .. code-block:: python stalta_waterlevel = 0.08 * np.ones(npts) tshift_acceptance_level = 15.0 * np.ones(npts) dlna_acceptance_level = 1.0 * np.ones(npts) cc_acceptance_level = 0.80 * np.ones(npts) s2n_limit = 1.5 * np.ones(npts) # Double all values from a certain index on. stalta_waterlevel[2500:] *= 2.0 tshift_acceptance_level[2500:] += 5.0 dlna_acceptance_level[2500:] *= 1.5 cc_acceptance_level[2500:] += 0.5 s2n_limit[2500:] *= 0.9 config = Config( min_period=10.0, max_period=50.0, stalta_waterlevel=stalta_waterlevel, tshift_acceptance_level=tshift_acceptance_level, dlna_acceptance_level=dlna_acceptance_level, cc_acceptance_level=cc_acceptance_level, s2n_limit=s2n_limit) :param min_period: Minimum period of the filtered input data in seconds. :type min_period: float :param max_period: Maximum period of the filtered input data in seconds. :type max_period: float :param stalta_waterlevel: Water level on the STA/LTA functional. Can be either a single value or an array with the same number of samples as the data. :type stalta_waterlevel: float or :class:`numpy.ndarray` :param tshift_acceptance_level: Maximum allowable cross correlation time shift/lag relative to the reference. Can be either a single value or an array with the same number of samples as the data. :type tshift_acceptance_level: float or :class:`numpy.ndarray` :param tshift_reference: Allows a systematic shift of the cross correlation time lag. :type tshift_reference: float :param dlna_acceptance_level: Maximum allowable amplitude ratio relative to the reference. Can be either a single value or an array with the same number of samples as the data. :type dlna_acceptance_level: float or :class:`numpy.ndarray` :param dlna_reference: Reference DLNA level. Allows a systematic shift. :type dlna_reference: float :param cc_acceptance_level: Limit on the normalized cross correlation per window. Can be either a single value or an array with the same number of samples as the data. :type cc_acceptance_level: float or :class:`numpy.ndarray` :param s2n_limit: Limit of the signal to noise ratio per window. If the maximum amplitude of the window over the maximum amplitude of the global noise of the waveforms is smaller than this window, then it will be rejected. Can be either a single value or an array with the same number of samples as the data. :type s2n_limit: float or :class:`numpy.ndarray` :param earth_model: The earth model used for the traveltime calculations. Either ``"ak135"`` or ``"iasp91"``. :type earth_model: str :param min_surface_wave_velocity: The minimum surface wave velocity in km/s. All windows containing data later then this velocity will be rejected. Only used if station and event information is available. :type min_surface_wave_velocity: float :param max_time_before_first_arrival: This is the minimum starttime of any window in seconds before the first arrival. No windows will have a starttime smaller than this. :type max_time_before_first_arrival: float :param c_0: Fine tuning constant for the rejection of windows based on the height of internal minima. Any windows with internal minima lower then this value times the STA/LTA water level at the window peak will be rejected. :type c_0: float :param c_1: Fine tuning constant for the minimum acceptable window length. This value multiplied by the minimum period will be the minimum acceptable window length. :type c_1: float :param c_2: Fine tuning constant for the maxima prominence rejection. Any windows whose minima surrounding the central peak are smaller then this value times the central peak will be rejected. This value is set to 0 in many cases as it is hard to control. :type c_2: float :param c_3a: Fine tuning constant for the separation height in the phase separation rejection stage. :type c_3a: float :param c_3b: Fine tuning constant for the separation time used in the decay function in the phase separation rejection stage. :type c_3b: float :param c_4a: Fine tuning constant for curtailing windows on the left with emergent start/stops and/or codas. :type c_4a: float :param c_4b: Fine tuning constant for curtailing windows on the right with emergent start/stops and/or codas. :type c_4b: float :param check_global_data_quality: Determines whether or not to check the signal to noise ratio of the whole observed waveform. If True, no windows will be selected if the signal to noise ratio is above the thresholds. :param snr_integrate_base: Minimal SNR ratio. If the squared sum of the signal normalized by its length over the squared sum of the noise normalized by its length is smaller then this value, no windows will be chosen for the waveforms. Only used if ``check_global_data_quality`` is ``True``. :type snr_integrate_base: float :param snr_max_base: Minimal amplitude SNR ratio. If the maximum amplitude of the signal over the maximum amplitude of the noise is smaller than this value no windows will be chosen for the waveforms. Only used if ``check_global_data_quality`` is ``True``. :type snr_max_base: float :param noise_start_index: Index in the observed data where noise starts for the signal to noise calculations. :type noise_start_index: int :param noise_end_index: Index in the observed data where noise ends for the signal to noise calculations. Will be set to the time of the first theoretical arrival minus the minimum period if not set and event and station information is available. :type noise_end_index: int :param signal_start_index: Index where the signal starts for the signal to noise calculations. Will be set to to the noise end index if not given. :type signal_start_index: int :param signal_end_index: Index where the signal ends for the signal to noise calculations. :type signal_end_index: int :param window_weight_fct: A function returning the weight for a specific window as a single number. Directly passed to the :class:`~pyflex.window.Window` 's initialization function. :type window_weight_fct: function :param window_signal_to_noise_type: The type of signal to noise ratio used to reject windows. If ``"amplitude"``, then the largest amplitude before the arrival is the noise amplitude and the largest amplitude in the window is the signal amplitude. If ``"energy"`` the time normalized energy is used in both cases. The later one is a bit more stable when having random wiggles before the first arrival. :type window_signal_to_noise_type: str :param resolution_strategy: Strategy used to resolve overlaps. Possibilities are ``"interval_scheduling"`` and ``"merge"``. Interval scheduling will chose the optimal subset of non-overlapping windows. Merging will simply merge overlapping windows. :type resolution_strategy: str """ self.min_period = min_period self.max_period = max_period self.stalta_waterlevel = stalta_waterlevel self.tshift_acceptance_level = tshift_acceptance_level self.tshift_reference = tshift_reference self.dlna_acceptance_level = dlna_acceptance_level self.dlna_reference = dlna_reference self.cc_acceptance_level = cc_acceptance_level self.s2n_limit = s2n_limit if earth_model.lower() not in ("ak135", "iasp91"): raise PyflexError("Earth model must either be 'ak135' or " "'iasp91'.") self.earth_model = earth_model.lower() self.min_surface_wave_velocity = min_surface_wave_velocity self.max_time_before_first_arrival = max_time_before_first_arrival self.c_0 = c_0 self.c_1 = c_1 self.c_2 = c_2 self.c_3a = c_3a self.c_3b = c_3b self.c_4a = c_4a self.c_4b = c_4b self.check_global_data_quality = check_global_data_quality self.snr_integrate_base = snr_integrate_base self.snr_max_base = snr_max_base self.noise_start_index = noise_start_index self.noise_end_index = noise_end_index self.signal_start_index = noise_start_index self.signal_end_index = noise_end_index self.window_weight_fct = window_weight_fct snr_type = window_signal_to_noise_type.lower() if snr_type not in ["amplitude", "energy"]: raise PyflexError("The window signal to noise type must be either" "'amplitude' or 'energy'.") self.window_signal_to_noise_type = snr_type if resolution_strategy.lower() not in ["interval_scheduling", "merge"]: raise PyflexError( "Invalid resolution strategy. Choose either " "'interval_scheduling' or 'merge'.") self.resolution_strategy = resolution_strategy.lower() def _convert_to_array(self, npts): """ Internally converts the acceptance and water levels to arrays. Not called during initialization as the array length is not yet known. """ attributes = ("stalta_waterlevel", "tshift_acceptance_level", "dlna_acceptance_level", "cc_acceptance_level", "s2n_limit") for name in attributes: attr = getattr(self, name) if isinstance(attr, collections.Iterable): if len(attr) != npts: raise PyflexError( "Config value '%s' does not have the same number of " "samples as the waveforms." % name) setattr(self, name, np.array(attr)) continue setattr(self, name, attr * np.ones(npts))