Source code for specmod.sources.motion

"""Converting a displacement source spectrum to the recorded motion."""

from __future__ import annotations

import numpy as np
from numpy.typing import NDArray

from ..core.units import Motion

__all__ = ["motion_scaling"]

#: Differentiation in the frequency domain multiplies by ``2 pi f`` per order.
_ORDERS: dict[Motion, int] = {
    Motion.DISPLACEMENT: 0,
    Motion.VELOCITY: 1,
    Motion.ACCELERATION: 2,
}


[docs] def motion_scaling( freq: NDArray[np.float64], motion: Motion | str ) -> NDArray[np.float64]: """``log10 G(f)``: the factor taking displacement to ``motion``. Source models are written for displacement, because that is where ``Omega`` and hence ``M0`` are defined. Records are usually velocity. Each order of differentiation multiplies by ``2 pi f``, so in log space it is that many copies of ``log10(2 pi f)``. The order comes from :class:`specmod.core.units.Motion` rather than a string comparison, so an unrecognised motion fails at the enum instead of silently returning zero — which would fit a displacement model to velocity data and put ``Omega`` out by a factor of ``2 pi f``. """ order = _ORDERS[Motion(motion)] if order == 0: return np.zeros_like(np.asarray(freq, dtype=np.float64)) return np.asarray( order * np.log10(2.0 * np.pi * np.asarray(freq, dtype=np.float64)) )