Source code for mspasspy.algorithms.basic

from mspasspy.util.decorators import mspass_func_wrapper
from mspasspy.ccore.algorithms.basic import LinearTaper, CosineTaper, VectorTaper
from mspasspy.ccore.utility import MsPASSError, ErrorSeverity
from mspasspy.util import logging_helper
import mspasspy.ccore.algorithms.basic as bsc
from mspasspy.ccore.seismic import (
    TimeSeries,
    TimeSeriesEnsemble,
    Seismogram,
    SeismogramEnsemble,
    SlownessVector,
)
from mspasspy.ccore.utility import SphericalCoordinate
import numpy as np


[docs]@mspass_func_wrapper def ExtractComponent( data, component, *args, object_history=False, alg_name=None, alg_id=None, dryrun=False, inplace_return=False, function_return_key=None, **kwargs, ): """ Extract single component from three-component data. The function creates a scalar TimeSeries object from a three component Seismogram object Or a TimeSeriesEnsemble object from a SeismogramEnsemble object :param data: data object to extract from. :type data: either :class:`~mspasspy.ccore.seismic.Seismogram` or :class:`~mspasspy.ccore.seismic.SeismogramEnsemble` :param component: the index of component that will be extracted, it can only be 0, 1, or 2 :type component: :class:`int` :param object_history: True to preserve the processing history. For details, refer to :class:`~mspasspy.util.decorators.mspass_func_wrapper`. :param alg_name: alg_name is the name the func we are gonna save while preserving the history. :type alg_name: :class:`str` :param alg_id: alg_id is a unique id to record the usage of func while preserving the history. :type alg_id: :class:`bson.objectid.ObjectId` :param dryrun: True for dry-run, which return "OK". Used in the mspass_func_wrapper. :param inplace_return: True to return data in mspass_func_wrapper. This is set false to handle exception directly in the function, without passing it to mspass_func_wrapper. :param function_return_key: Some functions one might want to wrap with this decorator return something that is appropriate to save as Metadata. If so, use this argument to define the key used to set that field in the data that is returned. """ if isinstance(data, Seismogram): try: d = bsc._ExtractComponent(data, component) return d except Exception as err: data.elog.log_error("ExtractComponent", str(err), ErrorSeverity.Invalid) empty = TimeSeries() empty.load_history(data) empty.kill() return empty elif isinstance(data, SeismogramEnsemble): if data.dead(): empty = TimeSeriesEnsemble() empty.elog = data.elog empty.kill() return empty try: d = TimeSeriesEnsemble(bsc._ExtractComponent(data, component)) # second copy to convert type from CoreTimeSeriesEnsemble to TimeSeriesEnsemble return d except Exception as err: logging_helper.ensemble_error( data, "ExtractComponent", err, ErrorSeverity.Invalid ) empty = TimeSeriesEnsemble() empty.elog = data.elog empty.kill() return empty
[docs]@mspass_func_wrapper def ator( data, tshift, *args, object_history=False, alg_name=None, alg_id=None, dryrun=False, inplace_return=True, function_return_key=None, **kwargs, ): """ Absolute to relative time conversion. Sometimes we want to convert data from absolute time (epoch times) to a relative time standard. Examples are conversions to travel time using an event origin time or shifting to an arrival time reference frame. This operation simply switches the tref variable and alters t0 by tshift. :param data: data object to be converted. :type data: either :class:`mspasspy.ccore.seismic.TimeSeries` or :class:`mspasspy.ccore.seismic.Seismogram` :param tshift: time shift applied to data before switching data to relative time mode. :type tshift: :class:`float` :param object_history: True to preserve the processing history. For details, refer to :class:`~mspasspy.util.decorators.mspass_func_wrapper`. :param alg_name: alg_name is the name the func we are gonna save while preserving the history. :type alg_name: :class:`str` :param alg_id: alg_id is a unique id to record the usage of func while preserving the history. :type alg_id: :class:`bson.objectid.ObjectId` :param dryrun: True for dry-run, which return "OK". Used in the mspass_func_wrapper. :param inplace_return: True to return data in mspass_func_wrapper. This is necessary to be used in mapreduce. :param function_return_key: Some functions one might want to wrap with this decorator return something that is appropriate to save as Metadata. If so, use this argument to define the key used to set that field in the data that is returned. """ data.ator(tshift)
[docs]@mspass_func_wrapper def rtoa( data, *args, object_history=False, alg_name=None, alg_id=None, dryrun=False, inplace_return=True, function_return_key=None, **kwargs, ): """ Relative to absolute time conversion. Sometimes we want to convert data from relative time to to an UTC time standard. An example would be converting segy shot data to something that could be processed like earthquake data in a css3.0 database. This function returns data previously converted to relative back to UTC using the internally stored time shift attribute. :param data: data object to be converted. :type data: either :class:`~mspasspy.ccore.seismic.TimeSeries` or :class:`~mspasspy.ccore.seismic.Seismogram` :param object_history: True to preserve the processing history. For details, refer to :class:`~mspasspy.util.decorators.mspass_func_wrapper`. :param alg_name: alg_name is the name the func we are gonna save while preserving the history. :type alg_name: :class:`str` :param alg_id: alg_id is a unique id to record the usage of func while preserving the history. :type alg_id: :class:`bson.objectid.ObjectId` :param dryrun: True for dry-run, which return "OK". Used in the mspass_func_wrapper. :param inplace_return: True to return data in mspass_func_wrapper. This is necessary to be used in mapreduce. :param function_return_key: Some functions one might want to wrap with this decorator return something that is appropriate to save as Metadata. If so, use this argument to define the key used to set that field in the data that is returned. """ data.rtoa()
[docs]@mspass_func_wrapper def rotate( data, rotate_param, *args, object_history=False, alg_name=None, alg_id=None, dryrun=False, inplace_return=True, function_return_key=None, **kwargs, ): """ Rotate data using a P wave type coordinate definition. This function can apply three different types of rotation depending on the type of parameter given. If a :class:`~mspasspy.ccore.utility.SphericalCoordinate` is given, it will rotate the data into a coordinate system defined by the direction defined by the spherical coordinate. The data are rotated such that x1 becomes the transverse component, x2 becomes radial, and x3 becomes longitudinal. If an unite vector of three components that defines the direction of x3 direction (longitudinal) is give, it will turn the vector into a :class:`~mspasspy.ccore.utility.SphericalCoordinate` object and calles the related rotate with it. If a :class:`float` number is given, it will rotate the horizontal components by this much angle in radians. :param data: data object to be rotated. :type data: :class:`~mspasspy.ccore.seismic.Seismogram` :param rotate_param: the parameter that defines the rotation. :type rotate_param: see above for details. :param object_history: True to preserve the processing history. For details, refer to :class:`~mspasspy.util.decorators.mspass_func_wrapper`. :param alg_name: alg_name is the name the func we are gonna save while preserving the history. :type alg_name: :class:`str` :param alg_id: alg_id is a unique id to record the usage of func while preserving the history. :type alg_id: :class:`bson.objectid.ObjectId` :param dryrun: True for dry-run, which return "OK". Used in the mspass_func_wrapper. :param inplace_return: True to return data in mspass_func_wrapper. This is necessary to be used in mapreduce. :param function_return_key: Some functions one might want to wrap with this decorator return something that is appropriate to save as Metadata. If so, use this argument to define the key used to set that field in the data that is returned. """ data.rotate(rotate_param)
[docs]@mspass_func_wrapper def rotate_to_standard( data, *args, object_history=False, alg_name=None, alg_id=None, dryrun=False, inplace_return=True, function_return_key=None, **kwargs, ): """ Apply inverse transformation matrix to return data to cardinal direction components. It is frequently necessary to make certain a set of three component data are oriented to the standard reference frame (EW, NS, Vertical). This function does this. For efficiency it checks the components_are_cardinal variable and does nothing if it is set true. Otherwise, it applies the inverse transformation and then sets this variable true. Note even if the current transformation matrix is not orthogonal it will be put back into cardinal coordinates. If inversion of the transformation matrix is not possible (e.g. two components are colinear) an error thrown by the C++ function is caught, posted to elog, and the datum return will be marked dead. :param data: data object to be rotated. :type data: :class:`~mspasspy.ccore.seismic.Seismogram` :param object_history: True to preserve the processing history. For details, refer to :class:`~mspasspy.util.decorators.mspass_func_wrapper`. :param alg_name: alg_name is the name the func we are gonna save while preserving the history. :type alg_name: :class:`str` :param alg_id: alg_id is a unique id to record the usage of func while preserving the history. :type alg_id: :class:`bson.objectid.ObjectId` :param dryrun: True for dry-run, which return "OK". Used in the mspass_func_wrapper. :param inplace_return: True to return data in mspass_func_wrapper. This is necessary to be used in mapreduce. :param function_return_key: Some functions one might want to wrap with this decorator return something that is appropriate to save as Metadata. If so, use this argument to define the key used to set that field in the data that is returned. :exception: :class:`~mspasspy.ccore.utility.MsPASSError` thrown if the an inversion of the transformation matrix is required and that matrix is singular. This can happen if the transformation matrix is incorrectly defined or the actual data are coplanar. """ try: data.rotate_to_standard() except MsPASSError as merr: data.elog.log_error(merr) data.kill()
[docs]@mspass_func_wrapper def free_surface_transformation( data, uvec=None, vp0=None, vs0=None, ux_key="ux", uy_key="uy", vp0_key="vp0", vs0_key="vs0", *args, object_history=False, alg_name=None, alg_id=None, dryrun=False, inplace_return=True, function_return_key=None, **kwargs, ): """ Computes and applies the Kennett [1991] free surface transformation matrix. Kennett [1991] gives the form for a free surface transformation operator that defines a transformation matrix that provides optimal separation of P, SV, and SH for a receiver at the free surface of an isotropic medium with constant P and S velocity. The transformation is only valid if the incident wavefield is not evanescent (i.e. at or past the SV critical angle). It is important to realize the tranformation matrix does not define an orthogonal transformation. It is also, of course, only an approximation since it is strictly correct only for a constant velocity medium. The tranformation operator requires: (1) a slowness vector, (2) an estimate of surface P wave velocity, and (3) an estimate of surface shear wave velocity. In all cases the input for the slowness vector uses a local cartesian system with the vector specified as component ux and uy. ux is the component of the slowness of an incident wavefield in the geographic x direction, which means positive at local east. uy is the complementary component for the y direction defined by local north. The components of the slowness vector are assumed to be in units of s/km. (Warning: obspy's and other implementations of the commonly used tau-p calculator return slowness (ray parameter) in spherical units of s/radian - r sin(theta)/v) The required parameters (slowness vector and velocities) can be passed to the function one of two ways. Because it is much simpler to implement in a map operator the default expect those parameters to be set in the data object's Metadata container. The default keys for fetching each attribute are defined by the four arguments "ux_key", "uy_key", "vp0_key", and "vs0_key". All four have standard defaults defined in the function signature and below. The Metadata fetching algorithm can be overridden by defining the same data through the three optional arguments with the key names "uvec", "vp0", and "vs0". (see below for detailed descriptions) The switching between Metadata fetching and a constant arguments is not all or none. If a slowness vector is defined through uvec it will always override metadata. Handing of vp0 and vs0 is independent. i.e. you can define uvec and not define vp0 and vs0 or conversely you can (more commonly) define vp0 and vs0 but not define uvec. In all cases not defining an arg is a signal to fetch it from Metadata. When this function is applied to ensembles and the Metadata fetch approach is used (default) the function assumes all ensemble members have the required metadata keys defined. Any that do not are killed. The same happens for atomic data passed to this function if any of the required keys are missing. In fact, you should realize the ensemble algorithm simply applies this function in a recursion over all the members. The output components are in the order defined in Kennett's original paper. The order is 0=SH, 1=SV, 2=L. :param data: data object to be transformed. For ensembles the transformation is applied to all members. Note the Metadata fetch mechanism is the only recommended way to handle ensembles. An elog message will be posted to the ensemble's elog container if you try to use a constant slowness vector passed via uvec. It will not warn about constant vp0 and vs0 as that case is common. :type data: :class:`~mspasspy.ccore.seismic.Seismogram` or :class:`~mspasspy.ccore.seismic.SeismogramEnsemble` :param ux_key: key to use to fetch EW component of slowness vector from Metadata container. Default is "ux". :type ux_key: string :param uy_key: key to use to fetch NS component of slowness vector from Metadata container. Default is "uy". :type uy_key: string :param vp0_key: key to use to fetch free surface P wave velocity from Metadata container. Default is "vp0". :type vp0_key: string :param vs0_key: key to use to fetch free surface S wave velocity from Metadata container. Default is "vs0". :type vs0_key: string :param uvec: slowness vector of the incident wavefield defined via custom C++ class :class:`~mspasspy.ccore.seismic.SlownessVector`. Default is None which is taken as a signal to fetch the slowness vector components from Metadata using ux_key and uy_key. :type uvec: :class:`~mspasspy.ccore.seismic.SlownessVector` :param vp0: Surface P wave velocity. Default is None which is taken as a signal to fetch this quantity from Metadata using the vp0_key. :type vp0: :class:`float` :param vs0: Surface S wave velocity. Default is None which is taken as a signal to fetch this quantity from Metadata using the vs0_key. :type vs0: :class:`float` :param object_history: True to preserve the processing history. For details, refer to :class:`~mspasspy.util.decorators.mspass_func_wrapper`. :param alg_name: alg_name is the name the func we are gonna save while preserving the history. :type alg_name: :class:`str` :param alg_id: alg_id is a unique id to record the usage of func while preserving the history. :type alg_id: :class:`bson.objectid.ObjectId` :param dryrun: True for dry-run, which return "OK". Used in the mspass_func_wrapper. :param inplace_return: True to return data in mspass_func_wrapper. This is necessary to be used in mapreduce. :param function_return_key: Some functions one might want to wrap with this decorator return something that is appropriate to save as Metadata. If so, use this argument to define the key used to set that field in the data that is returned. """ if isinstance(data, Seismogram): if uvec: slowness_vector = uvec else: if data.is_defined(ux_key) and data.is_defined(uy_key): ux = data[ux_key] uy = data[uy_key] slowness_vector = SlownessVector(ux, uy) else: message = "required Metadata with keys =" + ux_key + " and " + uy_key message += " are not defined - datum killed" data.elog.log_error( "free_surface_transformation", message, ErrorSeverity.Invalid ) data.kill() if vp0: P_fs = vp0 else: if data.is_defined(vp0_key): P_fs = data[vp0_key] else: message = ( "required Metadata attribute " + vp0_key + " is not defined - datum killed" ) data.elog.log_error( "free_surface_transformation", message, ErrorSeverity.Invalid ) data.kill() if vs0: S_fs = vs0 else: if data.is_defined(vs0_key): S_fs = data[vs0_key] else: message = ( "required Metadata attribute " + vs0_key + " is not defined - datum killed" ) data.elog.log_error( "free_surface_transformation", message, ErrorSeverity.Invalid ) data.kill() if data.live: data.free_surface_transformation(slowness_vector, P_fs, S_fs) elif isinstance(data, SeismogramEnsemble): if uvec: message = "Using a constant slowness vector and surface velocities for all ensemble members\n" message = "That is ill advised unless this is an event gather for a small aperture array" data.elog.log_error( "free_surface_transformation", message, ErrorSeverity.Complaint ) for i in range(len(data.member)): # this is a recursion so be aware data.member[i] = free_surface_transformation( data.member[i], ux_key=ux_key, uy_key=uy_key, vp0_key=vp0_key, vs0_key=vs0_key, uvec=uvec, vp0=vp0, vs0=vs0, object_history=object_history, alg_name=alg_name, alg_id=alg_id, dryrun=dryrun, inplace_return=inplace_return, function_return_key=function_return_key, ) else: message = ( "free_surface_transform received invalid type for arg0 of {}\n".format( type(data) ) ) message += "Must be either a Seismogram or SeismogramEnsemble" raise TypeError(message) return data
[docs]@mspass_func_wrapper def transform( data, matrix, *args, object_history=False, alg_name=None, alg_id=None, dryrun=False, inplace_return=True, function_return_key=None, **kwargs, ): """ Applies an arbitrary transformation matrix to the data. i.e. after calling this function the data will have been multiplied by the matrix and the transformation matrix will be updated. The later allows cascaded transformations to data. :param data: data object to be transformed. :type data: :class:`~mspasspy.ccore.seismic.Seismogram` :param matrix: a 3x3 matrix that defines the transformation. :type matrix: :class:`numpy.array` :param object_history: True to preserve the processing history. For details, refer to :class:`~mspasspy.util.decorators.mspass_func_wrapper`. :param alg_name: alg_name is the name the func we are gonna save while preserving the history. :type alg_name: :class:`str` :param alg_id: alg_id is a unique id to record the usage of func while preserving the history. :type alg_id: :class:`bson.objectid.ObjectId` :param dryrun: True for dry-run, which return "OK". Used in the mspass_func_wrapper. :param inplace_return: True to return data in mspass_func_wrapper. This is necessary to be used in mapreduce. :param function_return_key: Some functions one might want to wrap with this decorator return something that is appropriate to save as Metadata. If so, use this argument to define the key used to set that field in the data that is returned. """ data.transform(matrix)
[docs]@mspass_func_wrapper def transform_to_RTZ( data, key="seaz", phi=None, angle_units="degrees", key_is_backazimuth=True, object_history=False, alg_name=None, alg_id=None, dryrun=False, inplace_return=False, function_return_key=None, ): """ Applies coordinate transform to RTZ version of ray coordinates. RTZ is the simplest transformation for three component data to what is commonly called ray coordinates. R-radial (SV), T-transverse (SH). and Z=vertical (bad measure of longitudinal). The function first forces the data to cardinal direction using rotate_to_standard and then rotates the coordinates around the vertical axis. The rotation can be defined in one of two ways. The default behavior is to attempt to extract the back azimuth from the station to the source with the key defined by the "key" argument (defaults to 'seaz'). That behavior will be overriden if the "phi" kwarg value is set. Phi is assumed to be the angle to rotate the coordinates using the math convention for the phi angle with positive anticlockwise. The units of the value retrieved with the key argument or the value passed via the phi argument are by default assumed to be in degrees. If using the phi argument you specify the angle in radians if you also set the "angle_units" argument to "radians". :param data: data object to be transformed :type data: :class:`~mspasspy.ccore.seismic.Seismogram` or :class:`~mspass.ccore.seismic.SeismogramEnsemble`. :param key: key to use to fetch back azimuth value (assumed degrees always) :type key: string :param phi: angle to rotate around vertical to define the transformation (positive anticlockwise convention NOT azimuth convention) Default is None which means ignore this parameter and use key. Setting this value to something other than None causes the key method to be overridden. :type phi: float :param angle_units: should be either 'degrees' (default) or 'radians'. An invalid value will be treated as an attempt to switch to radians but will generate an elog warning message. This argument is ignored unless phi is not null (None type) :type angle_units: string :param key_is_backazimuth: boolean that when True (default) assumes the angle extrated with the key argument value is a backazimuth in degrees. If set False, the angle will be assumed to be a rotation angle in with the anticlockwise positive convention. :param alg_name: alg_name is the name the func we are gonna save while preserving the history. :type alg_name: :class:`str` :param alg_id: alg_id is a unique id to record the usage of func while preserving the history. :type alg_id: :class:`bson.objectid.ObjectId` :param dryrun: True for dry-run, which return "OK". Used in the mspass_func_wrapper. :param inplace_return: True to return data in mspass_func_wrapper. This is necessary to be used in mapreduce. :param function_return_key: Some functions one might want to wrap with this decorator return something that is appropriate to save as Metadata. If so, use this argument to define the key used to set that field in the data that is returned. :return: transformed version of input. For ensembles the entire ensemble is transformed. """ if phi: if angle_units == "degrees": phi_rad = np.radians(phi) else: if angle_units != "radians": message = "Illegal value for angle_units argument=" + angle_units message += " assuming radians" data.elog.log_error( "transform_to_RTZ", message, ErrorSeverity.Complaint ) phi_rad = phi use_metadata = False else: use_metadata = True if isinstance(data, Seismogram): if use_metadata: if data.is_defined(key): phi_deg = data[key] if key_is_backazimuth: az = phi_deg + 180.0 phi_deg = 90.0 - az phi_rad = np.radians(phi_deg) else: message = ( "required Metadata key=" + key + " not defined for this datum - killed" ) data.elog.log_error("transform_to_RTZ", message, ErrorSeverity.Invalid) data.kill() return data try: data.rotate_to_standard() data.rotate(phi_rad) except MsPASSError as merr: data.log_error(merr) data.kill() elif isinstance(data, SeismogramEnsemble): for i in range(len(data.member)): # this is a recursion so be aware data.member[i] = transform_to_RTZ( data.member[i], key=key, phi=phi, angle_units=angle_units, object_history=object_history, alg_name=alg_name, alg_id=alg_id, dryrun=dryrun, inplace_return=inplace_return, function_return_key=function_return_key, ) else: message = "transform_to_RTZ received invalid type for arg0 of {}\n".format( type(data) ) message += "Must be either a Seismogram or SeismogramEnsemble" raise TypeError(message) return data
[docs]@mspass_func_wrapper def transform_to_LQT( data, seaz_key="seaz", ema_key="ema", phi=None, theta=None, angle_units="degrees", object_history=False, alg_name=None, alg_id=None, dryrun=False, inplace_return=False, function_return_key=None, ): """ Applies coordinate transform to LQT version of ray coordinates. LQT is an orthogonal coordinate transformation for Seismogram objects that cause the output data to have x1-Longitudinal (positive up normally set to the predicted emergence angle of P particle motion), x2 - Q a rotated radial direction (in propagation direction but tilted by theta). and x3 - transverse (T) in direction to define a right handed coordinate system. The function produces this transformation by the product f three transformation: 1. Uses rotate_to_standard to assure we start from cardinal directions. 2. Transformation to what might be called TQL using the Seismogram C++ method rotate using a SphericalCoordinate definition. 3. Transformation to LQT to rearrange the order of the Seismogram data matrix (also requires a sign change on T to keep the output right handed) The form of the transformation can be specified in one of two completely different ways. By default the function attempts to extract the back azimuth from station to event with using the metadata key defined by 'seaz_key' (default 'seaz') and the P emergence angle with the metadata key defined by the 'ema_key' argument (default 'ema'). If the arguments 'phi' and 'theta' are defined they are assumed angles to be used to defined the transformation and no attempt will be made to fetch the value from Metaata (Rarely a good idea with ensemble but can be useful for atomic data. Using Metadata is strongly preferred because it also preserves what the angles used where. They are not if the argument approach is used.) Metadata values are required to be in degree units. If the argument approach is used radian values can to used if you also set the argument "angle_units" to "radians". Note the operation handles the singular case of theta==0.0 where it simply uses the phi value and rotates the coordinates in a variant of RTZ (variant because order is different). :param seaz_key: key to use to fetch back azimuth value (assumed degrees always) :type key: string (default "seaz") :param ema_key: key to use to fetch emergence angle defining L direction relative to local vertical. :type ema_key: string (defautl "ema") :param phi: angle to rotate around vertical to define the transformation (positive anticlockwise convention NOT azimuth convention) Default is None which means ignore this parameter and use key. Setting this value to something other than None causes the Metadata fetch method to be overridden. WARNING: this is not backazimuth but angle relative to E direction. Note that is not at all what is expected when using a Metadata key :type phi: float :param theta: angle relative to local vertical for defining the L coordinate direction. It is the same as theta in spherical coordinates with emergence angle pointing upward. Default is None which causes the algorithm to automatically assume the Metadata key method should be used. :type theta: float :param angle_units: should be either 'degrees' (default) or 'radians'. An invalid value will be treated as an attempt to switch to radians but will generate an elog warning message. This argument is ignored unless phi is not null (None type) :type angle_units: string :param alg_name: alg_name is the name the func we are gonna save while preserving the history. :type alg_name: :class:`str` :param alg_id: alg_id is a unique id to record the usage of func while preserving the history. :type alg_id: :class:`bson.objectid.ObjectId` :param dryrun: True for dry-run, which return "OK". Used in the mspass_func_wrapper. :param inplace_return: True to return data in mspass_func_wrapper. This is necessary to be used in mapreduce. :param function_return_key: Some functions one might want to wrap with this decorator return something that is appropriate to save as Metadata. If so, use this argument to define the key used to set that field in the data that is returned. :return: transformed version of input. For ensembles the entire ensemble is transformed. """ if phi and theta: if angle_units == "degrees": phi_rad = np.radians(phi) theta_rad = np.radians(theta) else: if angle_units != "radians": message = "Illegal value for angle_units argument=" + angle_units message += " assuming radians" data.elog.log_error( "transform_to_LQT", message, ErrorSeverity.Complaint ) phi_rad = phi theta_rad = theta use_metadata = False else: use_metadata = True if isinstance(data, Seismogram): if use_metadata: if data.is_defined(seaz_key) and data.is_defined(ema_key): seaz = data[seaz_key] # need azimuth not back azimuth az = seaz - 180.0 phi_deg = 90.0 - az # trig funtions work the same if angle wraps so no neeed to test # for fixed range phi_rad = np.radians(phi_deg) ema_deg = data[ema_key] theta_rad = np.radians(ema_deg) else: message = "At least one of required metadata keys=" message += seaz_key + " and " + ema_key message += " are not defined in this datume - killed" data.elog.log_error("transform_to_LQT", message, ErrorSeverity.Invalid) data.kill() return data try: data.rotate_to_standard() sc = SphericalCoordinate() sc.phi = phi_rad sc.theta = theta_rad sc.radius = 1.0 # not strictly necessary but prudent # rotate method is overloaded allowing this type of input data.rotate(sc) # The rotate method returns the data in TQL order. # Standard convention is LQT so we reorder the data # This could be done more efficiently with vector operators # but we need to use the transform method to assure the # internal tranformation matrix is properly updated a = np.zeros([3, 3]) a[0, 2] = 1.0 a[1, 1] = 1.0 a[2, 0] = -1.0 data.transform(a) # x = np.array(data.data[0,:]) # data.data[0,:] = data.data[2,:] # change the sign of T to keep coordinates right handed == LQT # data.data[2,:] = -x except MsPASSError as merr: data.log_error(merr) data.kill() elif isinstance(data, SeismogramEnsemble): for i in range(len(data.member)): # this is a recursion so be aware data.member[i] = transform_to_LQT( data.member[i], seaz_key=seaz_key, ema_key=ema_key, phi=phi, theta=theta, angle_units=angle_units, object_history=object_history, alg_name=alg_name, alg_id=alg_id, dryrun=dryrun, inplace_return=inplace_return, function_return_key=function_return_key, ) else: message = "transform_to_LQT received invalid type for arg0 of {}\n".format( type(data) ) message += "Must be either a Seismogram or SeismogramEnsemble" raise TypeError(message) return data
[docs]@mspass_func_wrapper def linear_taper( data, t0head, t1head, t1tail, t0tail, *args, object_history=False, alg_name=None, alg_id=None, dryrun=False, inplace_return=True, function_return_key=None, **kwargs, ): """ Taper front and/or end of a data object with a linear taper. Linear tapers are defined here as a time spanning a ramp running from 0 to 1. Data will be zeroed on each end of a 0 mark and a linear weight applied between 0 points and 1 points. Postive ramp slope on left and negative slope ramp on right. Setting t0 == t1 will disable the taper on the specified end (e.g., t0head == t1head). :param data: data object to be processed. :type data: either :class:`~mspasspy.ccore.seismic.TimeSeries` or :class:`~mspasspy.ccore.seismic.Seismogram` :param t0head: t0 of the head taper :type t0head: :class:`float` :param t1head: t1 of the head taper :type t1head: :class:`float` :param t1tail: t1 of the tail taper :type t1tail: :class:`float` :param t0tail: t0 of the tail taper :type t0tail: :class:`float` :param object_history: True to preserve the processing history. For details, refer to :class:`~mspasspy.util.decorators.mspass_func_wrapper`. :param alg_name: alg_name is the name the func we are gonna save while preserving the history. :type alg_name: :class:`str` :param alg_id: alg_id is a unique id to record the usage of func while preserving the history. :type alg_id: :class:`bson.objectid.ObjectId` :param dryrun: True for dry-run, which return "OK". Used in the mspass_func_wrapper. :param inplace_return: True to return data in mspass_func_wrapper. This is necessary to be used in mapreduce. :param function_return_key: Some functions one might want to wrap with this decorator return something that is appropriate to save as Metadata. If so, use this argument to define the key used to set that field in the data that is returned. """ taper = LinearTaper(t0head, t1head, t1tail, t0tail) taper.apply(data)
[docs]@mspass_func_wrapper def cosine_taper( data, t0head, t1head, t1tail, t0tail, *args, object_history=False, alg_name=None, alg_id=None, dryrun=False, inplace_return=True, function_return_key=None, **kwargs, ): """ Taper front and/or end of a data object with a half cosine function. A cosine taper is a common, simple approach to taper data. When applied at the front it defnes a half cycle of a cosine curve +1.0 in range -pi to 0. On the right it defines the same function for the range 0 to pi. The period of the left and right operator can be different. Turn off left or right by giving illegal start and end points and the operator will silently be only one sided. :param data: data object to be processed. :type data: either :class:`~mspasspy.ccore.seismic.TimeSeries` or :class:`~mspasspy.ccore.seismic.Seismogram` :param t0head: t0 of the head taper :type t0head: :class:`float` :param t1head: t1 of the head taper :type t1head: :class:`float` :param t1tail: t1 of the tail taper :type t1tail: :class:`float` :param t0tail: t0 of the tail taper :type t0tail: :class:`float` :param object_history: True to preserve the processing history. For details, refer to :class:`~mspasspy.util.decorators.mspass_func_wrapper`. :param alg_name: alg_name is the name the func we are gonna save while preserving the history. :type alg_name: :class:`str` :param alg_id: alg_id is a unique id to record the usage of func while preserving the history. :type alg_id: :class:`bson.objectid.ObjectId` :param dryrun: True for dry-run, which return "OK". Used in the mspass_func_wrapper. :param inplace_return: True to return data in mspass_func_wrapper. This is necessary to be used in mapreduce. :param function_return_key: Some functions one might want to wrap with this decorator return something that is appropriate to save as Metadata. If so, use this argument to define the key used to set that field in the data that is returned. """ taper = CosineTaper(t0head, t1head, t1tail, t0tail) taper.apply(data)
[docs]@mspass_func_wrapper def vector_taper( data, taper_array, *args, object_history=False, alg_name=None, alg_id=None, dryrun=False, inplace_return=True, function_return_key=None, **kwargs, ): """ Apply a general taper defined by a vector to the data object. This method provides a simple way to build a taper from a set of uniformly spaced points. The apply methods will dogmatically only accept input data of the same length as the taper defined in the operator. :param data: data object to be processed. :type data: either :class:`~mspasspy.ccore.seismic.TimeSeries` or :class:`~mspasspy.ccore.seismic.Seismogram` :param taper_array: the array that defines the taper :type taper_array: :class:`numpy.array` :param object_history: True to preserve the processing history. For details, refer to :class:`~mspasspy.util.decorators.mspass_func_wrapper`. :param alg_name: alg_name is the name the func we are gonna save while preserving the history. :type alg_name: :class:`str` :param alg_id: alg_id is a unique id to record the usage of func while preserving the history. :type alg_id: :class:`bson.objectid.ObjectId` :param dryrun: True for dry-run, which return "OK". Used in the mspass_func_wrapper. :param inplace_return: True to return data in mspass_func_wrapper. This is necessary to be used in mapreduce. :param function_return_key: Some functions one might want to wrap with this decorator return something that is appropriate to save as Metadata. If so, use this argument to define the key used to set that field in the data that is returned. """ taper = VectorTaper(taper_array) taper.apply(data)