Source code for kuehn_et_al_fdm.calc_params

"""This module calculates the statistical distribution parameters for forward predition of the model."""

# Python imports
import argparse
import warnings
import numpy as np


# Module imports
from kuehn_et_al_fdm.load_data import DATA
from kuehn_et_al_fdm.utilities import _check_type, _check_location_range, _check_magnitude_range
from kuehn_et_al_fdm.prediction_functions import _func_nm, _func_rv, _func_ss
from kuehn_et_al_fdm._common_args import *  # noqa: F403 *


def _calc_params(*, magnitude, location, style, coefficient_type="median", override=False):
    """
    Calculate the predicted statistical distribution parameters.

    Parameters
    ----------
    magnitude : int or float
        Earthquake moment magnitude.

    location : int or float
        Normalized location along rupture length, range [0, 1.0].

    style : tr
        Style of faulting (case-insensitive). Valid options are 'strike-slip', 'reverse', or
        'normal'.

    coefficient_type : str, optional
        Option to run model using full epistemic uncertainty or with point estimates (mean or
        median) of the model coefficients (case-insensitive). Valid options are 'mean', 'median',
        or 'full'. Default 'median'.

    override : boolean, optional
        Option to override single scenario limitation that is hard-coded. Not recommended for most
        users. Default False.

    Returns
    -------
    tuple
        - 'model_id': Model coefficient row number or point estimate definition.
        - 'bc_param': Box-Cox transformation parameter (lambda).
        - 'mean': Mean displacement in transformed units (unfolded).
        - 'stdv_total': Total standard deviation in transformed units (unfolded).
        - 'stdv_within': Within-event standard deviation in transformed units (unfolded).
        - 'stdv_between': Between-event standard deviation in transformed units (unfolded).

    Raises
    ------
    ValueError
        If `coefficient_type` is not 'mean', 'median', or 'full'.

    ValueError
        If `location` is not within range [0, 1].

    Warns
    -----
    UserWarning
        If `override` is `True`, indicating that multiple scenarios are being run.

    UserWarning
        If `magnitude` is not within the recommended range for that style.

    Examples
    --------
    From command line:

    .. code-block:: console

        $ kea-stat_params -m 6 -l 0.33 -s normal
    """
    # Only one value is allowed
    # TODO: vectorize / organize
    msg = "***Note: Only one value is allowed."
    _check_type(style, "style", str, msg=msg)

    if not override:
        _check_type(magnitude, "magnitude", (int, float), msg=msg)
        _check_type(location, "location", (int, float), msg=msg)
    else:
        magnitude = np.atleast_1d(magnitude)
        location = np.atleast_1d(location)
        warnings.warn("\n***Running multiple scenarios. Track your mag/loc.\n", UserWarning)

    style = style.lower()
    coefficient_type = coefficient_type.lower()

    # Check ranges of inputs
    _check_location_range(location)
    _check_magnitude_range(magnitude, style)

    function_map = {"strike-slip": _func_ss, "reverse": _func_rv, "normal": _func_nm}

    # Calculate parameters for each set of coefficients
    if coefficient_type == "full":
        coeffs = DATA["full"][style].to_records(index=False)
        model_id, lam, mu, sd_total, sd_u, sd_mode = function_map[style](
            coeffs, magnitude, location
        )

    # Calculate parameters for point estimates of coefficients
    else:
        if coefficient_type not in ["mean", "median"]:
            raise ValueError(
                f"'{coefficient_type}' is an invalid 'coefficient_type';"
                " only 'mean', 'median', or 'full' is allowed."
            )

        coeffs = DATA["point"][style]
        coeffs = coeffs[coeffs["model_id"] == coefficient_type].to_records(index=False)

        model_id, lam, mu, sd_total, sd_u, sd_mode = function_map[style](
            coeffs, magnitude, location
        )

    return model_id, lam, mu, sd_total, sd_u, sd_mode


# Create an ArgumentParser instance and add specific arguments to the parser
parser = argparse.ArgumentParser(
    description=_calc_params.__doc__, formatter_class=argparse.RawTextHelpFormatter
)
_add_magnitude(parser)
_add_location(parser)
_add_style(parser)
_add_coefficient_type(parser)


[docs]@_add_arguments(parser) def main(**kwargs): try: result = _calc_params(**kwargs) names = ["model_id", "bc_param", "mean", "stdv_total", "stdv_within", "stdv_between"] print( f" Displacement for magnitude {kwargs.get('magnitude')}, " f"location {kwargs.get('location')}, {kwargs.get('style')} faulting:" ) for name, val in zip(names, result): print(f" {name}: {val.squeeze()}") except ValueError as e: print(e)
if __name__ == "__main__": main()