From a901d9cbea19a1c71bf6fcb8de1200482ffdd3c0 Mon Sep 17 00:00:00 2001 From: Mustafa Comoglu Date: Mon, 22 Jun 2026 18:40:36 +1000 Subject: [PATCH 1/8] [magnitudes] Add Mwpd duration-amplitude moment magnitude plugin Native port of Early-est 1.2.9's Mwpd (Lomax & Michelini 2009): a per-station moment magnitude from the integral of the vertical displacement over the source duration T0. Amplitude processor (type "Mwpd"): from the raw vertical window it restitutes to velocity, high-passes at the BRB-HP corner (0.15 Hz), integrates to displacement and accumulates the running double integral into separate positive/negative displacement lobes. The source duration T0 is estimated from the high-frequency envelope (1-5 Hz band-pass, squared, boxcar-smoothed, 90/80/50/20 %-of-peak level crossings). It emits the displacement integral at T0 in nm*s and carries T0 as the amplitude period. Magnitude processor (type "Mwpd"): forms M0 from the Tsuboi constant and applies the INGV_EE distance correction, the PREM step depth correction and the >90 s duration ramp. Builds as plugin mwpd; no component combiner (vertical P only). Bindings documented in descriptions/global_mwpd.xml. Co-Authored-By: Claude Opus 4.8 --- plugins/magnitudes/CMakeLists.txt | 3 +- plugins/magnitudes/mwpd/CMakeLists.txt | 21 ++ plugins/magnitudes/mwpd/amplitude.cpp | 357 ++++++++++++++++++ plugins/magnitudes/mwpd/config.cpp | 118 ++++++ .../mwpd/descriptions/global_mwpd.xml | 98 +++++ plugins/magnitudes/mwpd/magnitude.cpp | 130 +++++++ plugins/magnitudes/mwpd/mwpd.h | 162 ++++++++ plugins/magnitudes/mwpd/plugin.cpp | 22 ++ plugins/magnitudes/mwpd/version.h | 14 + 9 files changed, 924 insertions(+), 1 deletion(-) create mode 100644 plugins/magnitudes/mwpd/CMakeLists.txt create mode 100644 plugins/magnitudes/mwpd/amplitude.cpp create mode 100644 plugins/magnitudes/mwpd/config.cpp create mode 100644 plugins/magnitudes/mwpd/descriptions/global_mwpd.xml create mode 100644 plugins/magnitudes/mwpd/magnitude.cpp create mode 100644 plugins/magnitudes/mwpd/mwpd.h create mode 100644 plugins/magnitudes/mwpd/plugin.cpp create mode 100644 plugins/magnitudes/mwpd/version.h diff --git a/plugins/magnitudes/CMakeLists.txt b/plugins/magnitudes/CMakeLists.txt index e161ff027..86ac0447f 100644 --- a/plugins/magnitudes/CMakeLists.txt +++ b/plugins/magnitudes/CMakeLists.txt @@ -1 +1,2 @@ -SUBDIRS(nuttli) \ No newline at end of file +SUBDIRS(nuttli) +SUBDIRS(mwpd) diff --git a/plugins/magnitudes/mwpd/CMakeLists.txt b/plugins/magnitudes/mwpd/CMakeLists.txt new file mode 100644 index 000000000..d03f372b1 --- /dev/null +++ b/plugins/magnitudes/mwpd/CMakeLists.txt @@ -0,0 +1,21 @@ +SET(PLUGIN_TARGET mwpd) + +SET( + PLUGIN_SOURCES + config.cpp + amplitude.cpp + magnitude.cpp + plugin.cpp +) + +SET( + PLUGIN_HEADERS + mwpd.h + version.h +) + +SC_ADD_PLUGIN_LIBRARY(PLUGIN ${PLUGIN_TARGET} "") +SC_LINK_LIBRARIES_INTERNAL(${PLUGIN_TARGET} client) + +FILE(GLOB descs "${CMAKE_CURRENT_SOURCE_DIR}/descriptions/*.xml") +INSTALL(FILES ${descs} DESTINATION ${SC3_PACKAGE_APP_DESC_DIR}) diff --git a/plugins/magnitudes/mwpd/amplitude.cpp b/plugins/magnitudes/mwpd/amplitude.cpp new file mode 100644 index 000000000..c5a412b53 --- /dev/null +++ b/plugins/magnitudes/mwpd/amplitude.cpp @@ -0,0 +1,357 @@ +/*************************************************************************** + * SeisComP duration-amplitude moment-magnitude plugin (mwpd) * + * * + * Amplitude processor. From the raw vertical window it reproduces two * + * Early-est streams: * + * 1. BRB-HP displacement: counts/gain -> velocity, high-passed at * + * MWPD_GAIN_FREQUENCY, single-integrated to displacement; the running * + * double integral is accumulated into separate positive- and * + * negative-displacement lobes (int_int_sum_pos/neg). * + * 2. HF envelope: raw band-passed 1-5 Hz, squared, boxcar-smoothed; its * + * peak/level (90/80/50/20 %) crossings give the source duration T0. * + * The emitted amplitude is the displacement integral at T0 (nm*s); T0 is * + * carried as the amplitude "period". * + * * + * Ports timedomain_processing.c (mwpd + T0 loops) and * + * timedomain_processing_data.c (calculate_Raw_Mwpd_Mag, calculate_duration).* + * * + * GNU Affero General Public License Usage - see LICENSE. * + ***************************************************************************/ + + +#define SEISCOMP_COMPONENT Mwpd + +#include +#include + +#include +#include +#include +#include + +#include "mwpd.h" + + +using namespace Seiscomp::Math::Filtering::IIR; + + +namespace Seiscomp { +namespace Magnitudes { +namespace Mwpd { + + +namespace { + +// Centred boxcar smoothing (half-width in samples), matching the T50 envelope +// smoothing. Edges shrink the window to the available samples. +void boxcarSmooth(std::vector &x, int halfWidth) { + if ( halfWidth < 1 || x.size() < 2 ) { + return; + } + const int n = static_cast(x.size()); + + // Prefix sums for an O(n) moving average. + std::vector pre(n + 1, 0.0); + for ( int i = 0; i < n; ++i ) { + pre[i + 1] = pre[i] + x[i]; + } + + std::vector out(n); + for ( int i = 0; i < n; ++i ) { + int a = std::max(0, i - halfWidth); + int b = std::min(n - 1, i + halfWidth); + out[i] = (pre[b + 1] - pre[a]) / (b - a + 1); + } + x.swap(out); +} + +// Source-duration estimate from the level-crossing indices (relative to the +// pick, in samples). Ports calculate_duration(). +double durationFromLevels(int idx90, int idx80, int idx50, int idx20, + double dt, double floorSec) { + const double t9 = idx90 * dt; + const double t8 = idx80 * dt; + const double t5 = idx50 * dt; + const double t2 = idx20 * dt; + + const double durEstimate = (t5 + t8) / 2.0; + double factor = (durEstimate - 20.0) / 40.0; // 0->1 for 20->60 s + if ( factor < 0.0 ) { + factor = 0.0; + } + else if ( factor > 1.0 ) { + factor = 1.0; + } + + double duration = t9 * (1.0 - factor) + t2 * factor; + if ( duration < floorSec ) { + duration = floorSec; + } + return duration; +} + +} // namespace + + +REGISTER_AMPLITUDEPROCESSOR(AmplitudeProcessor_Mwpd, MWPD_TYPE); + + +AmplitudeProcessor_Mwpd::AmplitudeProcessor_Mwpd() +: Processing::AmplitudeProcessor(MWPD_TYPE) { + setUsedComponent(Vertical); + setUnit(MWPD_AMP_UNIT); + applyConfig(); +} + + +void AmplitudeProcessor_Mwpd::applyConfig() { + // Pick at signalStart=0; integration starts analysisPreP before it (taken + // from the noise side of the window). Signal end covers the longest T0. + setSignalStart(0.0); + setSignalEnd(_cfg.maxDuration); + setNoiseStart(-(_cfg.analysisPreP + 30.0)); + setNoiseEnd(-_cfg.analysisPreP); + + setMinDist(_cfg.minDistanceDeg); + setMaxDist(_cfg.maxDistanceDeg); + setMinSNR(0); // T0 has its own S/N termination; no scalar SNR gate + computeTimeWindow(); +} + + +bool AmplitudeProcessor_Mwpd::setup(const Processing::Settings &settings) { + if ( !Processing::AmplitudeProcessor::setup(settings) ) { + return false; + } + + _cfg = MwpdConfig(); + if ( !readMwpdConfig(settings, std::string("amplitudes.") + type(), _cfg) ) { + return false; + } + + applyConfig(); + + SEISCOMP_DEBUG("%s: gainFreq=%.2fHz HF=%.1f-%.1fHz preP=%.1fs maxDur=%.0fs", + type().c_str(), _cfg.gainFrequency, _cfg.hfFmin, _cfg.hfFmax, + _cfg.analysisPreP, _cfg.maxDuration); + return true; +} + + +const DoubleArray *AmplitudeProcessor_Mwpd::processedData(Component comp) const { + return comp == targetComponent() ? &_processedData : nullptr; +} + + +bool AmplitudeProcessor_Mwpd::computeAmplitude( + const DoubleArray &data, + size_t i1, size_t i2, + size_t /*si1*/, size_t /*si2*/, + double offset, + AmplitudeIndex *dt, + AmplitudeValue *amplitude, + double *period, double *snr) { + + const double fsamp = _stream.fsamp; + if ( fsamp <= 0.0 ) { + setStatus(Error, 1); + return false; + } + const double deltaTime = 1.0 / fsamp; + + const double gain = std::fabs(_streamConfig[targetComponent()].gain); + if ( gain == 0.0 ) { + setStatus(MissingGain, 1); + return false; + } + + const int n = static_cast(i2); // end of usable window + const int iPick = static_cast(i1); // signalStart = pick + const int preP = static_cast(_cfg.analysisPreP * fsamp + 0.5); + const int iStart = iPick - preP; // integration start + if ( iStart < 0 || n > static_cast(data.size()) || n - iPick < 16 ) { + setStatus(Error, 2); + return false; + } + + const double *raw = static_cast(data.data()); + + // ===================================================================== + // 1) BRB-HP displacement and its positive/negative running integrals. + // ===================================================================== + // Velocity (counts -> m/s), demeaned by the noise offset, high-passed at + // the BRB-HP corner. We keep it as _processedData for inspection. + _processedData.resize(n); + double *vel = _processedData.typedData(); + for ( int i = 0; i < n; ++i ) { + vel[i] = (raw[i] - offset) / gain; + } + + ButterworthHighpass hp(_cfg.hpOrder, _cfg.gainFrequency, fsamp); + hp.apply(n, vel); + + // Running single integral (displacement) and double integral split into + // positive- and negative-displacement lobes (Early-est mwpd loop). + const int nAcc = (n - iStart) + 1; // index 0 == analysis start + std::vector intPos(nAcc, 0.0); + std::vector intNeg(nAcc, 0.0); + double intSum = 0.0, accPos = 0.0, accNeg = 0.0; + int k = 0; + for ( int i = iStart; i < n; ++i ) { + ++k; + intSum += vel[i] * deltaTime; // displacement [m] + const double area = intSum * deltaTime; // [m*s] + if ( intSum >= 0.0 ) { + accPos += area; + } + else { + accNeg += -area; + } + intPos[k] = accPos; + intNeg[k] = accNeg; + } + + // ===================================================================== + // 2) High-frequency envelope and the source duration T0. + // ===================================================================== + double duration; + + if ( _cfg.fixedDuration ) { + duration = _cfg.fixedDurationVal; + } + else { + std::vector env(n); + for ( int i = 0; i < n; ++i ) { + env[i] = raw[i]; + } + ButterworthBandpass bp(_cfg.hfOrder, _cfg.hfFmin, _cfg.hfFmax, fsamp); + bp.apply(n, env.data()); + for ( int i = 0; i < n; ++i ) { + env[i] *= env[i]; // square + } + const int smoothHW = static_cast(_cfg.smoothHalfWidth * fsamp + 0.5); + boxcarSmooth(env, smoothHW); + for ( int i = 0; i < n; ++i ) { + env[i] = std::sqrt(std::max(0.0, env[i])); + } + + // Level tracking from the pick onward (Early-est T0 loop). + double ampNoise = env[iPick]; + if ( ampNoise <= 0.0 ) { + ampNoise = DBL_MIN; + } + double ampPeak = -1.0; + double amp90 = -1.0, amp80 = -1.0, amp50 = -1.0, amp20 = -1.0; + int idx90 = 0, idx80 = 0, idx50 = 0, idx20 = 0; + const int minDurSamp = static_cast(_cfg.minDuration * fsamp + 0.5); + const int smooth2 = static_cast(2.0 * _cfg.smoothHalfWidth * fsamp + 0.5); + const double T0_INVALID = -1.0; + duration = T0_INVALID; + + for ( int i = iPick; i < n; ++i ) { + const double amp = env[i]; + const int rel = i - iPick; + + if ( amp > ampPeak ) { // new peak: unset all levels + ampPeak = amp; + amp90 = amp80 = amp50 = amp20 = -1.0; + } + else { + if ( amp90 < 0.0 ) { + if ( amp <= 0.9 * ampPeak ) { amp90 = amp; idx90 = rel; } + } + else if ( amp > 0.9 * ampPeak ) { + amp90 = amp80 = amp50 = amp20 = -1.0; + } + if ( amp80 < 0.0 ) { + if ( amp <= 0.8 * ampPeak ) { amp80 = amp; idx80 = rel; } + } + else if ( amp > 0.8 * ampPeak ) { + amp80 = amp50 = amp20 = -1.0; + } + if ( amp50 < 0.0 ) { + if ( amp <= 0.5 * ampPeak ) { amp50 = amp; idx50 = rel; } + } + else if ( amp > 0.5 * ampPeak ) { + amp50 = amp20 = -1.0; + } + if ( amp20 < 0.0 ) { + if ( amp <= 0.2 * ampPeak ) { + amp20 = amp; idx20 = rel; + duration = durationFromLevels(idx90, idx80, idx50, idx20, + deltaTime, _cfg.durationFloor); + } + } + else if ( amp > 0.2 * ampPeak ) { + amp20 = -1.0; + } + + // Terminate once below the S/N or peak ratio (after min dur). + if ( rel > minDurSamp && + ( amp / ampNoise < _cfg.snT0End || + amp / ampPeak < _cfg.peakRatioT0End ) ) { + break; + } + } + + // Terminate if well past twice the established duration. + if ( duration > 0.0 && amp20 > 0.0 && + rel > static_cast(2.0 * duration * fsamp + 0.5) && + rel > smooth2 ) { + break; + } + } + + if ( duration <= 0.0 ) { + // T0 not resolved within the window: fall back to the available + // post-pick length (capped), as Early-est does before T0 completes. + duration = (n - iPick) * deltaTime; + } + } + + if ( duration > _cfg.maxDuration ) { + duration = _cfg.maxDuration; + } + + // ===================================================================== + // 3) Displacement integral at T0 (greater of the pos/neg lobes). + // ===================================================================== + int idxDur = static_cast((duration + _cfg.analysisPreP) / deltaTime + 0.5); + if ( idxDur >= nAcc ) { + idxDur = nAcc - 1; + } + if ( idxDur < 1 ) { + setStatus(Error, 3); + return false; + } + + double amplitudeIntegral = std::max(intPos[idxDur], intNeg[idxDur]); // [m*s] + if ( amplitudeIntegral <= 0.0 ) { + setStatus(Error, 4); + return false; + } + + // Emit the integral in nm*s (as Mwp emits nm); carry T0 as the period + // (the base divides period by fsamp, so multiply by fsamp here). + amplitude->value = amplitudeIntegral * 1.0e9; + *period = duration * fsamp; + *snr = 1000000.0; // T0 S/N gating already applied above + + dt->index = iPick; + dt->begin = iStart - iPick; + dt->end = idxDur + iStart - iPick; + + SEISCOMP_DEBUG("%s.%s.%s: ampInt=%g nm*s T0=%.1fs (pos=%g neg=%g) gain=%g", + _environment.networkCode.c_str(), + _environment.stationCode.c_str(), + _environment.locationCode.c_str(), + amplitude->value, duration, + intPos[idxDur] * 1.0e9, intNeg[idxDur] * 1.0e9, gain); + + return true; +} + + +} +} +} diff --git a/plugins/magnitudes/mwpd/config.cpp b/plugins/magnitudes/mwpd/config.cpp new file mode 100644 index 000000000..4989dbb73 --- /dev/null +++ b/plugins/magnitudes/mwpd/config.cpp @@ -0,0 +1,118 @@ +/*************************************************************************** + * SeisComP duration-amplitude moment-magnitude plugin (mwpd) * + * * + * Shared configuration reader and the Early-est constants/corrections * + * (moment constant, INGV_EE distance correction, PREM step depth * + * correction). * + * * + * GNU Affero General Public License Usage - see LICENSE. * + ***************************************************************************/ + + +#define SEISCOMP_COMPONENT Mwpd + +#include + +#include + +#include "mwpd.h" + + +namespace Seiscomp { +namespace Magnitudes { +namespace Mwpd { + + +// PREM depth correction table (depth_corr_mwpd.h), depth[km] -> delta-magnitude, +// 0..600 km. Step lookup: the correction of the largest table depth <= h. +namespace { + +const int NUM_DEPTH_CORR = 11; +const double DEPTH_CORR[NUM_DEPTH_CORR][2] = { + { 0.0, 0.00 }, { 71.0, 0.00 }, { 80.0, 0.00 }, {171.0, -0.01 }, + {220.0, 0.05 }, {271.0, 0.06 }, {371.0, 0.07 }, {400.0, 0.12 }, + {471.0, 0.15 }, {571.0, 0.18 }, {600.0, 0.22 } +}; + +} + + +double mwpdMomentConstant(const MwpdConfig &cfg) { + // Early-est MWP_CONST (Tsuboi 1995): + // 4 pi * rho * Vp^3 * FP * (10000/90 deg->km) * 1000 (km->m) + return 4.0 * M_PI * cfg.rho * cfg.vp * cfg.vp * cfg.vp * cfg.fp + * (10000.0 / 90.0) * 1000.0; +} + + +double mwpdDistanceCorrection(double deltaDeg, double depthKm) { + // calculate_Mwp_correction_INGV_EE (20150312 coefficients). + if ( deltaDeg < 0.0 || depthKm > 100.0 ) { + return 0.0; + } + return -1.32e-6 * deltaDeg * deltaDeg * deltaDeg + + 2.40e-4 * deltaDeg * deltaDeg + - 0.0146 * deltaDeg + + 0.314; +} + + +double mwpdDepthCorrection(double depthKm) { + // get_depth_corr_mwpd_prem: largest table depth <= h; -999 if below row 0. + int index = NUM_DEPTH_CORR - 1; + while ( index >= 0 && DEPTH_CORR[index][0] > depthKm ) { + --index; + } + return ( index < 0 ) ? -999.0 : DEPTH_CORR[index][1]; +} + + +bool readMwpdConfig(const Processing::Settings &settings, + const std::string &prefix, MwpdConfig &out) { + // BRB-HP restitution + displacement integral. + settings.getValue(out.gainFrequency, prefix + ".gainFrequency"); + settings.getValue(out.hpOrder, prefix + ".highpassOrder"); + settings.getValue(out.analysisPreP, prefix + ".analysisPreP"); + + // HF envelope. + settings.getValue(out.hfFmin, prefix + ".hfFmin"); + settings.getValue(out.hfFmax, prefix + ".hfFmax"); + settings.getValue(out.hfOrder, prefix + ".hfOrder"); + settings.getValue(out.smoothHalfWidth, prefix + ".smoothHalfWidth"); + + // T0 estimation. + settings.getValue(out.minDuration, prefix + ".minDuration"); + settings.getValue(out.maxDuration, prefix + ".maxDuration"); + settings.getValue(out.snT0End, prefix + ".snT0End"); + settings.getValue(out.peakRatioT0End, prefix + ".peakRatioT0End"); + settings.getValue(out.fixedDuration, prefix + ".fixedDuration"); + settings.getValue(out.fixedDurationVal,prefix + ".fixedDurationValue"); + + // Magnitude formula + corrections. + settings.getValue(out.rho, prefix + ".density"); + settings.getValue(out.vp, prefix + ".vp"); + settings.getValue(out.fp, prefix + ".radiation"); + settings.getValue(out.useDistanceCorr, prefix + ".distanceCorrection"); + settings.getValue(out.useDepthCorr, prefix + ".depthCorrection"); + settings.getValue(out.useDurationRamp, prefix + ".durationRamp"); + settings.getValue(out.minDistanceDeg, prefix + ".minimumDistance"); + settings.getValue(out.maxDistanceDeg, prefix + ".maximumDistance"); + + if ( out.hfFmax <= out.hfFmin ) { + SEISCOMP_ERROR("%s: hfFmax (%f) must be > hfFmin (%f)", + prefix.c_str(), out.hfFmax, out.hfFmin); + return false; + } + if ( out.maxDuration <= out.minDuration ) { + SEISCOMP_ERROR("%s: maxDuration (%f) must be > minDuration (%f)", + prefix.c_str(), out.maxDuration, out.minDuration); + return false; + } + + return true; +} + + +} +} +} diff --git a/plugins/magnitudes/mwpd/descriptions/global_mwpd.xml b/plugins/magnitudes/mwpd/descriptions/global_mwpd.xml new file mode 100644 index 000000000..c756e0a00 --- /dev/null +++ b/plugins/magnitudes/mwpd/descriptions/global_mwpd.xml @@ -0,0 +1,98 @@ + + + + global + + Duration-amplitude moment magnitude Mwpd (Lomax & Michelini 2009), + ported from Early-est 1.2.9. The vertical broadband is restituted to + displacement, high-passed at the BRB-HP corner and integrated over the + source duration T0; T0 is estimated from the high-frequency envelope. + The amplitude processor emits the displacement integral (nm*s) and + carries T0 as the amplitude period; the magnitude processor forms M0 + and Mwpd with the distance, PREM depth and duration corrections. + + + + + + Measurement parameters for the Mwpd amplitude (displacement + integral over the source duration T0). + + + BRB-HP high-pass corner used for restitution to displacement (MWPD_GAIN_FREQUENCY). + + + Butterworth order of the BRB-HP high-pass filter. + + + Lead before P at which the displacement integration starts (START_ANALYSIS_BEFORE_P_BRB_HP). + + + Low edge of the high-frequency band used for the T0 envelope. + + + High edge of the high-frequency band used for the T0 envelope. + + + Butterworth order of the high-frequency band-pass. + + + Boxcar half-width that smooths the squared HF trace into the envelope (SMOOTHING_WINDOW_HALF_WIDTH_T50). + + + Earliest the T0 search may terminate (MIN_MWPD_DUR). + + + Cap on T0 and on the post-pick signal window (Early-est MAX_MWPD_DUR is 1200 s). + + + Envelope signal-to-noise ratio below which the T0 search terminates (SIGNAL_TO_NOISE_RATIO_T0_END). + + + Envelope-to-peak ratio below which the T0 search terminates (SIGNAL_TO_PEAK_RATIO_T0_END). + + + If true, use a fixed source duration instead of the HF-envelope estimate. + + + The fixed source duration used when fixedDuration is true. + + + + + + Moment-magnitude parameters and corrections for Mwpd. + + Density in the Tsuboi moment constant. + + + P velocity in the Tsuboi moment constant. + + + FP average radiation factor in the Tsuboi moment constant. + + + Apply the INGV_EE epicentral-distance correction. + + + Apply the PREM step depth correction (0-600 km). + + + Apply the >90 s duration ramp correction that boosts great/slow events (USE_MPWD_CORR). + + + Reject station magnitudes closer than this epicentral distance. + + + Reject station magnitudes beyond this epicentral distance. + + + Linear station correction a in a*Mwpd+b. Leave 1.0 for none. + + + Constant station correction b in a*Mwpd+b. Leave 0.0 for none. + + + + + diff --git a/plugins/magnitudes/mwpd/magnitude.cpp b/plugins/magnitudes/mwpd/magnitude.cpp new file mode 100644 index 000000000..dcc7c7afe --- /dev/null +++ b/plugins/magnitudes/mwpd/magnitude.cpp @@ -0,0 +1,130 @@ +/*************************************************************************** + * SeisComP duration-amplitude moment-magnitude plugin (mwpd) * + * * + * Magnitude processor: displacement integral over T0 -> M0 -> Mwpd, with * + * the INGV_EE distance correction, the PREM step depth correction and the * + * >90 s duration ramp. Faithful to Early-est calculate_Raw_Mwpd_Mag + * + * calculate_corrected_Mwpd_Mag. * + * * + * GNU Affero General Public License Usage - see LICENSE. * + ***************************************************************************/ + + +#define SEISCOMP_COMPONENT Mwpd + +#include + +#include +#include + +#include "mwpd.h" + + +namespace Seiscomp { +namespace Magnitudes { +namespace Mwpd { + + +REGISTER_MAGNITUDEPROCESSOR(MagnitudeProcessor_Mwpd, MWPD_TYPE); + + +MagnitudeProcessor_Mwpd::MagnitudeProcessor_Mwpd() +: Processing::MagnitudeProcessor(MWPD_TYPE) { + _minimumDistanceDeg = _cfg.minDistanceDeg; + _maximumDistanceDeg = _cfg.maxDistanceDeg; +} + + +bool MagnitudeProcessor_Mwpd::setup(const Processing::Settings &settings) { + if ( !Processing::MagnitudeProcessor::setup(settings) ) { + return false; + } + + _cfg = MwpdConfig(); + if ( !readMwpdConfig(settings, std::string("magnitudes.") + type(), _cfg) ) { + return false; + } + + _minimumDistanceDeg = _cfg.minDistanceDeg; + _maximumDistanceDeg = _cfg.maxDistanceDeg; + + SEISCOMP_DEBUG("%s: dist=%.1f-%.1f deg distCorr=%d depthCorr=%d durRamp=%d", + type().c_str(), _cfg.minDistanceDeg, _cfg.maxDistanceDeg, + _cfg.useDistanceCorr, _cfg.useDepthCorr, _cfg.useDurationRamp); + return true; +} + + +MagnitudeProcessor_Mwpd::Status +MagnitudeProcessor_Mwpd::computeMagnitude( + double amplitude, const std::string &unit, + double period, double /*snr*/, + double delta, double depth, + const DataModel::Origin *, + const DataModel::SensorLocation *, + const DataModel::Amplitude *, + const Locale *, + double &value) { + + if ( amplitude <= 0.0 ) { + return AmplitudeOutOfRange; + } + + // The displacement integral is carried in nm*s (as Mwp carries nm). + double ampNmS = amplitude; + if ( !convertAmplitude(ampNmS, unit, MWPD_AMP_UNIT) ) { + return InvalidAmplitudeUnit; + } + + // T0 (source duration) arrives in the amplitude period (seconds). + const double duration = period; + + if ( depth < 0.0 ) { + depth = 0.0; + } + + // --- raw Mwpd (calculate_Raw_Mwpd_Mag) -------------------------------- + const double amplitudeIntegral = ampNmS * 1.0e-9; // nm*s -> m*s + double moment = mwpdMomentConstant(_cfg) * amplitudeIntegral * delta; + if ( moment <= FLT_MIN ) { + return Error; + } + + double raw = (2.0 / 3.0) * (std::log10(moment) - 9.1); + if ( _cfg.useDistanceCorr ) { + raw -= mwpdDistanceCorrection(delta, depth); + } + + // --- corrected Mwpd (calculate_corrected_Mwpd_Mag) -------------------- + double corr = raw; + + if ( _cfg.useDepthCorr ) { + const double dc = mwpdDepthCorrection(depth); + if ( dc > -998.0 ) { // -999 marks an invalid (too-shallow) lookup + corr += dc; + } + } + + if ( _cfg.useDurationRamp && duration > _cfg.durRampLow ) { + double ramp = (duration - _cfg.durRampLow) + / (_cfg.durRampHigh - _cfg.durRampLow); + if ( ramp > 1.0 ) { + ramp = 1.0; + } + corr += ramp * (raw - _cfg.magCutoff) * _cfg.rampPow; + } + + value = corr; + + SEISCOMP_DEBUG("%s: ampInt=%g nm*s T0=%.1fs delta=%.2f depth=%.1f " + "-> logM0=%.2f raw=%.2f Mwpd=%.2f", + type().c_str(), ampNmS, duration, delta, depth, + std::log10(moment), raw, value); + + return OK; +} + + +} +} +} diff --git a/plugins/magnitudes/mwpd/mwpd.h b/plugins/magnitudes/mwpd/mwpd.h new file mode 100644 index 000000000..714086963 --- /dev/null +++ b/plugins/magnitudes/mwpd/mwpd.h @@ -0,0 +1,162 @@ +/*************************************************************************** + * SeisComP duration-amplitude moment-magnitude plugin (mwpd) * + * * + * Per-station moment magnitude Mwpd (Lomax & Michelini 2009), porting * + * Early-est 1.2.9. The displacement is integrated over the source * + * duration T0 (estimated from the high-frequency envelope) rather than * + * taking the running-integral peak as Mwp does. * + * * + * GNU Affero General Public License Usage - see LICENSE. * + ***************************************************************************/ + + +#ifndef SEISCOMP_MAGNITUDES_MWPD_PLUGIN_H +#define SEISCOMP_MAGNITUDES_MWPD_PLUGIN_H + + +#include +#include +#include +#include + + +namespace Seiscomp { +namespace Magnitudes { +namespace Mwpd { + + +//! Registered amplitude/magnitude type string. +#define MWPD_TYPE "Mwpd" + +//! Amplitude unit: the displacement integral over T0, carried in nm*s (as Mwp). +#define MWPD_AMP_UNIT "nm*s" + + +/** + * Configuration shared by the amplitude and magnitude processors. Defaults + * reproduce the hard-coded Early-est 1.2.9 constants + * (timedomain_processing.c / timedomain_processing_data.c). + */ +struct MwpdConfig { + // --- BRB-HP restitution + displacement integral (amplitude side) ------ + double gainFrequency = 0.15; //!< [Hz] MWPD_GAIN_FREQUENCY: BRB high-pass corner + int hpOrder = 4; //!< Butterworth high-pass order for the BRB-HP trace + double analysisPreP = 1.0; //!< [s] START_ANALYSIS_BEFORE_P_BRB_HP + + // --- HF envelope (T0 estimator) --------------------------------------- + double hfFmin = 1.0; //!< [Hz] HF band low edge (filter_bp_bu_co_1_5_n_4) + double hfFmax = 5.0; //!< [Hz] HF band high edge + int hfOrder = 4; //!< HF band-pass order + double smoothHalfWidth = 5.0; //!< [s] SMOOTHING_WINDOW_HALF_WIDTH_T50 boxcar half-width + + // --- T0 source-duration estimation ------------------------------------ + double minDuration = 20.0; //!< [s] MIN_MWPD_DUR: earliest the T0 search may terminate + double maxDuration = 300.0; //!< [s] cap on T0 / integration window (<= MAX_MWPD_DUR=1200) + double durationFloor = 0.2; //!< [s] MINIMUN_DURATION + double snT0End = 3.0; //!< SIGNAL_TO_NOISE_RATIO_T0_END + double peakRatioT0End = 0.025; //!< SIGNAL_TO_PEAK_RATIO_T0_END + bool fixedDuration = false; //!< use a fixed T0 instead of the HF-envelope estimate + double fixedDurationVal= 60.0; //!< [s] the fixed T0 when fixedDuration is true + + // --- magnitude formula + corrections ---------------------------------- + double rho = 3400.0; //!< [kg/m^3] density in MWP_CONST + double vp = 7900.0; //!< [m/s] P velocity in MWP_CONST + double fp = 2.0; //!< FP average radiation factor in MWP_CONST + bool useDistanceCorr = true; //!< apply calculate_Mwp_correction (INGV_EE) + bool useDepthCorr = true; //!< apply get_depth_corr_mwpd_prem (PREM step) + bool useDurationRamp = true; //!< USE_MPWD_CORR: >90 s duration ramp + double durRampLow = 90.0; //!< [s] MWPD_MOMENT_CORR_DUR_CUTOFF_LOW + double durRampHigh = 110.0; //!< [s] MWPD_MOMENT_CORR_DUR_CUTOFF_HIGH + double magCutoff = 7.2; //!< MWPD_MOMENT_CORR_MAG_CUTOFF + double rampPow = 0.45; //!< MWPD_MOMENT_CORR_POW + double minDistanceDeg = 5.0; //!< accept station magnitudes from this distance + double maxDistanceDeg = 105.0; //!< ...up to this distance +}; + + +/** Reads MwpdConfig from a binding. @p prefix is "amplitudes.Mwpd" or + * "magnitudes.Mwpd". Missing keys keep their (Early-est) defaults. */ +bool readMwpdConfig(const Processing::Settings &settings, + const std::string &prefix, MwpdConfig &out); + + +/** Tsuboi (1995) moment constant, reproduced from Early-est: + * 4 pi * rho * Vp^3 * FP * (10000/90) deg->km * 1000 km->m. */ +double mwpdMomentConstant(const MwpdConfig &cfg); + +/** INGV_EE distance correction (subtracted from the raw magnitude), + * calculate_Mwp_correction_INGV_EE: 0 if delta<0 or depth>100 km. */ +double mwpdDistanceCorrection(double deltaDeg, double depthKm); + +/** PREM step depth correction get_depth_corr_mwpd_prem (returns -999 if + * the depth is below the first table row). */ +double mwpdDepthCorrection(double depthKm); + + +// --------------------------------------------------------------------------- +// Amplitude processor (registered as "Mwpd"). Vertical broadband only. From +// the raw window it builds (a) the BRB-HP displacement and its running +// integral, separated into positive/negative displacement lobes, and (b) the +// high-frequency envelope from which the source duration T0 is estimated. +// Emits the displacement integral over T0 (nm*s) and carries T0 as the +// amplitude "period". +// --------------------------------------------------------------------------- +class SC_SYSTEM_CLIENT_API AmplitudeProcessor_Mwpd : public Processing::AmplitudeProcessor { + public: + AmplitudeProcessor_Mwpd(); + + public: + bool setup(const Processing::Settings &settings) override; + const DoubleArray *processedData(Component comp) const override; + + protected: + bool computeAmplitude(const DoubleArray &data, + size_t i1, size_t i2, + size_t si1, size_t si2, + double offset, + AmplitudeIndex *dt, + AmplitudeValue *amplitude, + double *period, double *snr) override; + + private: + void applyConfig(); + + private: + MwpdConfig _cfg; + DoubleArray _processedData; +}; + + +// --------------------------------------------------------------------------- +// Magnitude processor (registered as "Mwpd"). Turns the displacement +// integral into M0 and Mwpd, applying the distance, PREM depth and duration +// corrections. The source duration T0 arrives in the amplitude "period". +// --------------------------------------------------------------------------- +class SC_SYSTEM_CLIENT_API MagnitudeProcessor_Mwpd : public Processing::MagnitudeProcessor { + public: + MagnitudeProcessor_Mwpd(); + + public: + void setDefaults() override {} + bool setup(const Processing::Settings &settings) override; + + Status computeMagnitude(double amplitude, const std::string &unit, + double period, double snr, + double delta, double depth, + const DataModel::Origin *hypocenter, + const DataModel::SensorLocation *receiver, + const DataModel::Amplitude *, + const Locale *, + double &value) override; + + private: + MwpdConfig _cfg; +}; + + +} +} +} + + +#endif diff --git a/plugins/magnitudes/mwpd/plugin.cpp b/plugins/magnitudes/mwpd/plugin.cpp new file mode 100644 index 000000000..6da853919 --- /dev/null +++ b/plugins/magnitudes/mwpd/plugin.cpp @@ -0,0 +1,22 @@ +/*************************************************************************** + * SeisComP duration-amplitude moment-magnitude plugin (mwpd) * + * * + * Plugin entry point. Registers the Mwpd amplitude and magnitude * + * processors (a port of Early-est 1.2.9's Mwpd, Lomax & Michelini 2009). * + * * + * GNU Affero General Public License Usage - see LICENSE. * + ***************************************************************************/ + + +#include + +#include "version.h" + + +ADD_SC_PLUGIN( + "Duration-amplitude moment magnitude Mwpd: per-station moment magnitude " + "from the integral of the displacement over the source duration T0 " + "(port of Early-est 1.2.9, Lomax & Michelini 2009).", + "Early-est port", + MWPD_VERSION_MAJOR, MWPD_VERSION_MINOR, MWPD_VERSION_PATCH +) diff --git a/plugins/magnitudes/mwpd/version.h b/plugins/magnitudes/mwpd/version.h new file mode 100644 index 000000000..9d3dd77b0 --- /dev/null +++ b/plugins/magnitudes/mwpd/version.h @@ -0,0 +1,14 @@ +/*************************************************************************** + * SeisComP duration-amplitude moment-magnitude plugin (mwpd) * + ***************************************************************************/ + +#ifndef SEISCOMP_MAGNITUDES_MWPD_VERSION_H +#define SEISCOMP_MAGNITUDES_MWPD_VERSION_H + +#define MWPD_VERSION_MAJOR 0 +#define MWPD_VERSION_MINOR 1 +#define MWPD_VERSION_PATCH 0 + +#define MWPD_VERSION "0.1.0" + +#endif From de4a13e4ea88fb3fb3b527cb374e06cc4b007f11 Mon Sep 17 00:00:00 2001 From: Mustafa Comoglu Date: Tue, 23 Jun 2026 17:48:50 +1000 Subject: [PATCH 2/8] [magnitudes] Mwpd: S-P-capped full-window integration, T0 estimator, progressive updates Reworks the Mwpd amplitude/magnitude processors after offline + real-time playback testing against Mwp/mb/CMT: - Source-duration T0 estimated on the SQUARED (power) HF envelope via the 90/80/50/20%-of-peak last-crossing logic (Lomax & Michelini 2009, Fig. 2); envelope band ~1 Hz. - Integration over min(maxDuration, S-P): the displacement double-integral is accumulated in positive/negative lobes and read at the window end, with the window capped at the theoretical S-P time (libtau/iasp91) so it excludes S/surface-wave energy. Matches Early-est's MAX_MWPD_DUR window behaviour; the eager short-T0 cut under-integrated and read ~0.4 mag low. - Completeness gate: emit only once data covers the integration window; incomplete stations are skipped rather than reported on a partial window. - Progressive updates (setUpdateEnabled) so the value is computed incrementally as data streams; finalizes when the window is complete. - Moment scaling gated on magnitude (Mwpd += 0.45*(raw-7.2) for raw>7.2), eq (5a), instead of T0>90 s. - S-P cap via a configurable travel-time table (libtau/iasp91). On a teleseismic M~7.3 test this gives Mwpd 7.2, consistent with Mwp 7.3 / mb 7.2. Constant remains Early-est's Tsuboi form; absolute calibration vs GCMT to follow. --- plugins/magnitudes/mwpd/amplitude.cpp | 148 ++++++++++++++---- plugins/magnitudes/mwpd/config.cpp | 5 + .../mwpd/descriptions/global_mwpd.xml | 9 ++ plugins/magnitudes/mwpd/magnitude.cpp | 15 +- plugins/magnitudes/mwpd/mwpd.h | 24 ++- 5 files changed, 157 insertions(+), 44 deletions(-) diff --git a/plugins/magnitudes/mwpd/amplitude.cpp b/plugins/magnitudes/mwpd/amplitude.cpp index c5a412b53..79655f4b6 100644 --- a/plugins/magnitudes/mwpd/amplitude.cpp +++ b/plugins/magnitudes/mwpd/amplitude.cpp @@ -23,6 +23,8 @@ #include #include +#include +#include #include #include @@ -100,6 +102,11 @@ AmplitudeProcessor_Mwpd::AmplitudeProcessor_Mwpd() : Processing::AmplitudeProcessor(MWPD_TYPE) { setUsedComponent(Vertical); setUnit(MWPD_AMP_UNIT); + // Compute progressively as data streams (Early-est style): the processor + // emits a growing Mwpd and finalizes as soon as T0 resolves/terminates, + // rather than waiting the full (long) signal window. maxDuration is just + // the upper bound on how long we keep looking. + setUpdateEnabled(true); applyConfig(); } @@ -131,13 +138,53 @@ bool AmplitudeProcessor_Mwpd::setup(const Processing::Settings &settings) { applyConfig(); - SEISCOMP_DEBUG("%s: gainFreq=%.2fHz HF=%.1f-%.1fHz preP=%.1fs maxDur=%.0fs", + // Travel-time table for the S-P window cap (graceful if unavailable). + _ttt = nullptr; + if ( _cfg.useSpCap ) { + _ttt = Seiscomp::TravelTimeTableInterface::Create(_cfg.tttBackend.c_str()); + if ( !_ttt || !_ttt->setModel(_cfg.tttModel) ) { + SEISCOMP_WARNING("%s: travel-time table '%s'/'%s' unavailable; " + "S-P window cap disabled", + type().c_str(), _cfg.tttBackend.c_str(), + _cfg.tttModel.c_str()); + _ttt = nullptr; + } + } + + SEISCOMP_DEBUG("%s: gainFreq=%.2fHz HF=%.1f-%.1fHz preP=%.1fs maxDur=%.0fs spCap=%d", type().c_str(), _cfg.gainFrequency, _cfg.hfFmin, _cfg.hfFmax, - _cfg.analysisPreP, _cfg.maxDuration); + _cfg.analysisPreP, _cfg.maxDuration, _ttt != nullptr); return true; } +double AmplitudeProcessor_Mwpd::computeSPSeconds() const { + if ( !_ttt || !_environment.hypocenter || !_environment.receiver ) { + return -1.0; + } + try { + const double slat = _environment.hypocenter->latitude().value(); + const double slon = _environment.hypocenter->longitude().value(); + double sdep = 0.0; + try { sdep = _environment.hypocenter->depth().value(); } + catch ( ... ) {} + const double rlat = _environment.receiver->latitude(); + const double rlon = _environment.receiver->longitude(); + double relev = 0.0; + try { relev = _environment.receiver->elevation(); } + catch ( ... ) {} + + const double tP = _ttt->computeTime("P", slat, slon, sdep, rlat, rlon, relev); + const double tS = _ttt->computeTime("S", slat, slon, sdep, rlat, rlon, relev); + if ( tP > 0.0 && tS > 0.0 && tS > tP ) { + return tS - tP; + } + } + catch ( ... ) {} + return -1.0; +} + + const DoubleArray *AmplitudeProcessor_Mwpd::processedData(Component comp) const { return comp == targetComponent() ? &_processedData : nullptr; } @@ -170,7 +217,9 @@ bool AmplitudeProcessor_Mwpd::computeAmplitude( const int preP = static_cast(_cfg.analysisPreP * fsamp + 0.5); const int iStart = iPick - preP; // integration start if ( iStart < 0 || n > static_cast(data.size()) || n - iPick < 16 ) { - setStatus(Error, 2); + // Not enough data past the pick yet. With incremental updates this is a + // "keep waiting" state, NOT an error: leave the status InProgress so the + // base keeps feeding. (A terminal status here would kill the processor.) return false; } @@ -212,12 +261,17 @@ bool AmplitudeProcessor_Mwpd::computeAmplitude( } // ===================================================================== - // 2) High-frequency envelope and the source duration T0. + // 2) High-frequency envelope and the source duration T0 (durRaw). // ===================================================================== - double duration; + double durRaw; // source-duration estimate [s] (used for the ramp) + bool t0Resolved = false; + bool t0Terminated = false; // T0 search hit a termination criterion (final) + double peakRelSec = -1.0; // time of the envelope peak after P (debug) if ( _cfg.fixedDuration ) { - duration = _cfg.fixedDurationVal; + durRaw = _cfg.fixedDurationVal; + t0Resolved = true; + t0Terminated = true; } else { std::vector env(n); @@ -231,9 +285,10 @@ bool AmplitudeProcessor_Mwpd::computeAmplitude( } const int smoothHW = static_cast(_cfg.smoothHalfWidth * fsamp + 0.5); boxcarSmooth(env, smoothHW); - for ( int i = 0; i < n; ++i ) { - env[i] = std::sqrt(std::max(0.0, env[i])); - } + // NOTE: env stays as the squared (power) envelope -- Early-est's + // data_float_t50 is squared-then-smoothed and is NOT square-rooted; the + // 90/80/50/20% level tracking below runs on power, so a "20% of peak" + // crossing is at 0.2 in power (= ~0.45 in amplitude). // Level tracking from the pick onward (Early-est T0 loop). double ampNoise = env[iPick]; @@ -241,12 +296,12 @@ bool AmplitudeProcessor_Mwpd::computeAmplitude( ampNoise = DBL_MIN; } double ampPeak = -1.0; + int idxPeak = 0; double amp90 = -1.0, amp80 = -1.0, amp50 = -1.0, amp20 = -1.0; int idx90 = 0, idx80 = 0, idx50 = 0, idx20 = 0; const int minDurSamp = static_cast(_cfg.minDuration * fsamp + 0.5); const int smooth2 = static_cast(2.0 * _cfg.smoothHalfWidth * fsamp + 0.5); - const double T0_INVALID = -1.0; - duration = T0_INVALID; + durRaw = -1.0; for ( int i = iPick; i < n; ++i ) { const double amp = env[i]; @@ -254,6 +309,7 @@ bool AmplitudeProcessor_Mwpd::computeAmplitude( if ( amp > ampPeak ) { // new peak: unset all levels ampPeak = amp; + idxPeak = rel; amp90 = amp80 = amp50 = amp20 = -1.0; } else { @@ -278,8 +334,9 @@ bool AmplitudeProcessor_Mwpd::computeAmplitude( if ( amp20 < 0.0 ) { if ( amp <= 0.2 * ampPeak ) { amp20 = amp; idx20 = rel; - duration = durationFromLevels(idx90, idx80, idx50, idx20, - deltaTime, _cfg.durationFloor); + durRaw = durationFromLevels(idx90, idx80, idx50, idx20, + deltaTime, _cfg.durationFloor); + t0Resolved = true; } } else if ( amp > 0.2 * ampPeak ) { @@ -290,62 +347,89 @@ bool AmplitudeProcessor_Mwpd::computeAmplitude( if ( rel > minDurSamp && ( amp / ampNoise < _cfg.snT0End || amp / ampPeak < _cfg.peakRatioT0End ) ) { + t0Terminated = true; break; } } // Terminate if well past twice the established duration. - if ( duration > 0.0 && amp20 > 0.0 && - rel > static_cast(2.0 * duration * fsamp + 0.5) && + if ( durRaw > 0.0 && amp20 > 0.0 && + rel > static_cast(2.0 * durRaw * fsamp + 0.5) && rel > smooth2 ) { + t0Terminated = true; break; } } - if ( duration <= 0.0 ) { - // T0 not resolved within the window: fall back to the available - // post-pick length (capped), as Early-est does before T0 completes. - duration = (n - iPick) * deltaTime; - } + peakRelSec = idxPeak * deltaTime; + (void)t0Terminated; // computed for diagnostics; not used to finalize } - if ( duration > _cfg.maxDuration ) { - duration = _cfg.maxDuration; + if ( durRaw > _cfg.maxDuration ) { + durRaw = _cfg.maxDuration; } // ===================================================================== - // 3) Displacement integral at T0 (greater of the pos/neg lobes). + // 3) Integration window (Early-est) + completeness requirement. // ===================================================================== - int idxDur = static_cast((duration + _cfg.analysisPreP) / deltaTime + 0.5); + // Early-est integrates over MAX_MWPD_DUR (here maxDuration) and only + // shortens to T0 when T0 is robustly resolved (timedomain_processing.c + // ~1762). The window is also capped at the S-P time so the integral never + // includes S/surface-wave energy. Our envelope T0 estimate is not reliable + // enough to shorten the window, so we integrate over the full window + // (S-P capped), which captures the running displacement integral up to S. + const double sp = computeSPSeconds(); + double windowDur = _cfg.maxDuration; + if ( sp > 0.0 && windowDur > sp ) { + windowDur = sp; + } + + // Completeness: the data must cover the full integration window. While it + // does not, keep waiting (return false, stay InProgress). If the window is + // never covered (data ends short), the base finalizes a skip at progress + // >= 100 -- i.e. an incomplete station is skipped, not emitted on a partial + // window (Early-est flag_complete_mwpd / MWPD_INVALID behaviour). + const double availDur = (n - iPick) * deltaTime; + if ( availDur < windowDur - 1.0 ) { + return false; + } + + double integDur = windowDur; + int idxDur = static_cast((integDur + _cfg.analysisPreP) / deltaTime + 0.5); if ( idxDur >= nAcc ) { idxDur = nAcc - 1; } if ( idxDur < 1 ) { - setStatus(Error, 3); return false; } double amplitudeIntegral = std::max(intPos[idxDur], intNeg[idxDur]); // [m*s] if ( amplitudeIntegral <= 0.0 ) { - setStatus(Error, 4); return false; } - // Emit the integral in nm*s (as Mwp emits nm); carry T0 as the period - // (the base divides period by fsamp, so multiply by fsamp here). + // Emit the integral in nm*s (as Mwp emits nm). Carry the source duration as + // the period (for the magnitude side / tsunami indicator): the resolved T0 + // if available, otherwise the integration window. The base divides period + // by fsamp, so multiply here. + const double t0Report = ( durRaw > 0.0 ) ? durRaw : integDur; amplitude->value = amplitudeIntegral * 1.0e9; - *period = duration * fsamp; - *snr = 1000000.0; // T0 S/N gating already applied above + *period = t0Report * fsamp; + *snr = 1000000.0; dt->index = iPick; dt->begin = iStart - iPick; dt->end = idxDur + iStart - iPick; - SEISCOMP_DEBUG("%s.%s.%s: ampInt=%g nm*s T0=%.1fs (pos=%g neg=%g) gain=%g", + // The integration window is complete -> finalize (stop further updates). + setStatus(Finished, 100.0); + SEISCOMP_DEBUG("%s.%s.%s: Mwpd FINAL ampInt=%g nm*s T0raw=%.1fs%s peak@%.1fs " + "S-P=%.1fs window=%.1fs win=%.0fs (pos=%g neg=%g) gain=%g", _environment.networkCode.c_str(), _environment.stationCode.c_str(), _environment.locationCode.c_str(), - amplitude->value, duration, + amplitude->value, durRaw, durRaw > 0.0 ? "" : "(unresolved)", + peakRelSec, sp, integDur, availDur, intPos[idxDur] * 1.0e9, intNeg[idxDur] * 1.0e9, gain); return true; diff --git a/plugins/magnitudes/mwpd/config.cpp b/plugins/magnitudes/mwpd/config.cpp index 4989dbb73..3df33e5af 100644 --- a/plugins/magnitudes/mwpd/config.cpp +++ b/plugins/magnitudes/mwpd/config.cpp @@ -98,6 +98,11 @@ bool readMwpdConfig(const Processing::Settings &settings, settings.getValue(out.minDistanceDeg, prefix + ".minimumDistance"); settings.getValue(out.maxDistanceDeg, prefix + ".maximumDistance"); + // S-P window cap. + settings.getValue(out.useSpCap, prefix + ".spWindowCap"); + settings.getValue(out.tttBackend, prefix + ".tttBackend"); + settings.getValue(out.tttModel, prefix + ".tttModel"); + if ( out.hfFmax <= out.hfFmin ) { SEISCOMP_ERROR("%s: hfFmax (%f) must be > hfFmin (%f)", prefix.c_str(), out.hfFmax, out.hfFmin); diff --git a/plugins/magnitudes/mwpd/descriptions/global_mwpd.xml b/plugins/magnitudes/mwpd/descriptions/global_mwpd.xml index c756e0a00..6d608a495 100644 --- a/plugins/magnitudes/mwpd/descriptions/global_mwpd.xml +++ b/plugins/magnitudes/mwpd/descriptions/global_mwpd.xml @@ -57,6 +57,15 @@ The fixed source duration used when fixedDuration is true. + + Cap the displacement-integration window at the theoretical S-P time, as Early-est does, so the integral excludes S/surface-wave energy. The reported source duration T0 (and its ramp correction) is not capped. + + + Travel-time table backend used to compute the S-P cap. + + + Travel-time model used to compute the S-P cap. + diff --git a/plugins/magnitudes/mwpd/magnitude.cpp b/plugins/magnitudes/mwpd/magnitude.cpp index dcc7c7afe..0d49a5539 100644 --- a/plugins/magnitudes/mwpd/magnitude.cpp +++ b/plugins/magnitudes/mwpd/magnitude.cpp @@ -105,13 +105,14 @@ MagnitudeProcessor_Mwpd::computeMagnitude( } } - if ( _cfg.useDurationRamp && duration > _cfg.durRampLow ) { - double ramp = (duration - _cfg.durRampLow) - / (_cfg.durRampHigh - _cfg.durRampLow); - if ( ramp > 1.0 ) { - ramp = 1.0; - } - corr += ramp * (raw - _cfg.magCutoff) * _cfg.rampPow; + // Moment scaling for large interplate-thrust / tsunami events, Lomax & + // Michelini (2009) eq (5a): M0pd = M0*(M0/M0cutoff)^0.45 for M0 >= M0cutoff + // (Mw ~ 7.2), i.e. in magnitude terms Mwpd = raw + 0.45*(raw - 7.2). The + // function is continuous at the cutoff. The paper restricts this to + // interplate-thrust/tsunami events; event-type classification is not + // available here, so it is applied to all large events (configurable). + if ( _cfg.useDurationRamp && raw > _cfg.magCutoff ) { + corr += (raw - _cfg.magCutoff) * _cfg.rampPow; } value = corr; diff --git a/plugins/magnitudes/mwpd/mwpd.h b/plugins/magnitudes/mwpd/mwpd.h index 714086963..cce2b7607 100644 --- a/plugins/magnitudes/mwpd/mwpd.h +++ b/plugins/magnitudes/mwpd/mwpd.h @@ -18,6 +18,7 @@ #include #include #include +#include namespace Seiscomp { @@ -44,14 +45,19 @@ struct MwpdConfig { double analysisPreP = 1.0; //!< [s] START_ANALYSIS_BEFORE_P_BRB_HP // --- HF envelope (T0 estimator) --------------------------------------- - double hfFmin = 1.0; //!< [Hz] HF band low edge (filter_bp_bu_co_1_5_n_4) - double hfFmax = 5.0; //!< [Hz] HF band high edge - int hfOrder = 4; //!< HF band-pass order - double smoothHalfWidth = 5.0; //!< [s] SMOOTHING_WINDOW_HALF_WIDTH_T50 boxcar half-width + // Lomax & Michelini (2009) use a narrow ~1.0 Hz Gaussian filter for the + // duration envelope (their Fig. 2). A narrow band centred on 1 Hz gives a + // broad, slowly-decaying envelope and hence the long apparent durations + // (40-200 s) in their Table 1. (Early-est's operational code instead uses a + // 1-5 Hz Butterworth, which yields much shorter T0.) + double hfFmin = 0.5; //!< [Hz] envelope band low edge (~1 Hz centre) + double hfFmax = 1.5; //!< [Hz] envelope band high edge + int hfOrder = 4; //!< envelope band-pass order + double smoothHalfWidth = 5.0; //!< [s] envelope boxcar smoothing half-width // --- T0 source-duration estimation ------------------------------------ double minDuration = 20.0; //!< [s] MIN_MWPD_DUR: earliest the T0 search may terminate - double maxDuration = 300.0; //!< [s] cap on T0 / integration window (<= MAX_MWPD_DUR=1200) + double maxDuration = 300.0; //!< [s] integration / signal-window length (capped at S-P); Early-est integrates over this window unless a robust T0 shortens it double durationFloor = 0.2; //!< [s] MINIMUN_DURATION double snT0End = 3.0; //!< SIGNAL_TO_NOISE_RATIO_T0_END double peakRatioT0End = 0.025; //!< SIGNAL_TO_PEAK_RATIO_T0_END @@ -71,6 +77,11 @@ struct MwpdConfig { double rampPow = 0.45; //!< MWPD_MOMENT_CORR_POW double minDistanceDeg = 5.0; //!< accept station magnitudes from this distance double maxDistanceDeg = 105.0; //!< ...up to this distance + + // --- S-P window cap (Early-est limits the integral to the S-P time) --- + bool useSpCap = true; //!< cap the displacement integral at the S-P time + std::string tttBackend = "libtau"; //!< travel-time backend for S-P + std::string tttModel = "iasp91"; //!< travel-time model for S-P }; @@ -120,10 +131,13 @@ class SC_SYSTEM_CLIENT_API AmplitudeProcessor_Mwpd : public Processing::Amplitud private: void applyConfig(); + //! Theoretical S-P time [s] at the current source/receiver, or -1. + double computeSPSeconds() const; private: MwpdConfig _cfg; DoubleArray _processedData; + Seiscomp::TravelTimeTableInterfacePtr _ttt; }; From 5ff6f6a972ebbc42d017176d4319a77cfc30ca1a Mon Sep 17 00:00:00 2001 From: Mustafa Comoglu Date: Wed, 24 Jun 2026 18:08:02 +1000 Subject: [PATCH 3/8] [magnitudes] Mwpd: fix BRB-HP corner (0.005 Hz) and use T0-based integration Calibration against GCMT (and Lomax & Michelini 2009, Table 1) showed Mwpd reading increasingly low with magnitude (saturation). Root cause, confirmed from the Early-est source: the displacement high-pass is filter_hp_bu_co_0_005_n_2 = Butterworth 0.005 Hz, order 2 -- not 0.15 Hz (MWPD_GAIN_FREQUENCY is only the gain-reference frequency, not a filter). A 0.15 Hz high-pass removes periods >7 s and strips the long-period moment that dominates great-event integrals. Changes: - highpassCorner 0.005 Hz / order 2 (was 0.15 Hz / 4); config key renamed gainFrequency -> highpassCorner. - HF envelope band restored to 1-5 Hz (filter_bp_bu_co_1_5_n_4). - Integrate the displacement over min(T0, S-P, MAX_MWPD_DUR=1200 s) instead of a fixed window; finalize once the T0 search terminates or the window is full (progressive updates), else keep waiting / drop unresolved (MWPD_INVALID). - Moment scaling switched to Early-est's active duration-gated form (T0>90 s ramp 90->110 s) * (raw-7.2) * 0.45. Validated against GCMT: big events (M7.6-8.4) mean -0.15 vs CMT with no saturation (e.g. M8.4 7.33->8.28); full run mean ~-0.05, sigma ~0.16, slope ~1.0 (no high-M droop). --- plugins/magnitudes/mwpd/amplitude.cpp | 70 +++++++++---------- plugins/magnitudes/mwpd/config.cpp | 2 +- .../mwpd/descriptions/global_mwpd.xml | 10 +-- plugins/magnitudes/mwpd/magnitude.cpp | 19 ++--- plugins/magnitudes/mwpd/mwpd.h | 20 +++--- 5 files changed, 59 insertions(+), 62 deletions(-) diff --git a/plugins/magnitudes/mwpd/amplitude.cpp b/plugins/magnitudes/mwpd/amplitude.cpp index 79655f4b6..18d0ac445 100644 --- a/plugins/magnitudes/mwpd/amplitude.cpp +++ b/plugins/magnitudes/mwpd/amplitude.cpp @@ -152,7 +152,7 @@ bool AmplitudeProcessor_Mwpd::setup(const Processing::Settings &settings) { } SEISCOMP_DEBUG("%s: gainFreq=%.2fHz HF=%.1f-%.1fHz preP=%.1fs maxDur=%.0fs spCap=%d", - type().c_str(), _cfg.gainFrequency, _cfg.hfFmin, _cfg.hfFmax, + type().c_str(), _cfg.highpassCorner, _cfg.hfFmin, _cfg.hfFmax, _cfg.analysisPreP, _cfg.maxDuration, _ttt != nullptr); return true; } @@ -236,7 +236,7 @@ bool AmplitudeProcessor_Mwpd::computeAmplitude( vel[i] = (raw[i] - offset) / gain; } - ButterworthHighpass hp(_cfg.hpOrder, _cfg.gainFrequency, fsamp); + ButterworthHighpass hp(_cfg.hpOrder, _cfg.highpassCorner, fsamp); hp.apply(n, vel); // Running single integral (displacement) and double integral split into @@ -362,39 +362,38 @@ bool AmplitudeProcessor_Mwpd::computeAmplitude( } peakRelSec = idxPeak * deltaTime; - (void)t0Terminated; // computed for diagnostics; not used to finalize + } + + // ===================================================================== + // 3) S-P-capped integration over the source duration T0. + // ===================================================================== + // Early-est integrates the displacement over min(T0, S-P, MAX_MWPD_DUR) + // (calculate_Raw_Mwpd_Mag / timedomain_processing.c ~1762). Under progressive + // updates we only finalize once T0 is stable -- its search terminated + // (t0Terminated) or the full window has streamed -- otherwise the value would + // be locked on a transient early T0. Until then, keep waiting (InProgress); + // if T0 never resolves by window end the base drops the station (MWPD_INVALID). + if ( durRaw <= 0.0 ) { + return false; // T0 not resolved yet -> wait + } + const double availDur = (n - iPick) * deltaTime; + const bool windowFull = availDur >= _cfg.maxDuration - 1.0; + if ( !t0Terminated && !windowFull ) { + return false; // T0 still provisional -> wait } if ( durRaw > _cfg.maxDuration ) { durRaw = _cfg.maxDuration; } - - // ===================================================================== - // 3) Integration window (Early-est) + completeness requirement. - // ===================================================================== - // Early-est integrates over MAX_MWPD_DUR (here maxDuration) and only - // shortens to T0 when T0 is robustly resolved (timedomain_processing.c - // ~1762). The window is also capped at the S-P time so the integral never - // includes S/surface-wave energy. Our envelope T0 estimate is not reliable - // enough to shorten the window, so we integrate over the full window - // (S-P capped), which captures the running displacement integral up to S. const double sp = computeSPSeconds(); - double windowDur = _cfg.maxDuration; - if ( sp > 0.0 && windowDur > sp ) { - windowDur = sp; + double integDur = durRaw; + if ( sp > 0.0 && integDur > sp ) { + integDur = sp; // S-P cap on the integration window } - - // Completeness: the data must cover the full integration window. While it - // does not, keep waiting (return false, stay InProgress). If the window is - // never covered (data ends short), the base finalizes a skip at progress - // >= 100 -- i.e. an incomplete station is skipped, not emitted on a partial - // window (Early-est flag_complete_mwpd / MWPD_INVALID behaviour). - const double availDur = (n - iPick) * deltaTime; - if ( availDur < windowDur - 1.0 ) { - return false; + if ( availDur < integDur - 1.0 ) { + return false; // data must cover the window -> wait } - double integDur = windowDur; int idxDur = static_cast((integDur + _cfg.analysisPreP) / deltaTime + 0.5); if ( idxDur >= nAcc ) { idxDur = nAcc - 1; @@ -408,28 +407,23 @@ bool AmplitudeProcessor_Mwpd::computeAmplitude( return false; } - // Emit the integral in nm*s (as Mwp emits nm). Carry the source duration as - // the period (for the magnitude side / tsunami indicator): the resolved T0 - // if available, otherwise the integration window. The base divides period - // by fsamp, so multiply here. - const double t0Report = ( durRaw > 0.0 ) ? durRaw : integDur; + // Emit the integral in nm*s (as Mwp emits nm); carry the source-duration T0 + // as the period (the base divides period by fsamp, so multiply here). amplitude->value = amplitudeIntegral * 1.0e9; - *period = t0Report * fsamp; + *period = durRaw * fsamp; *snr = 1000000.0; dt->index = iPick; dt->begin = iStart - iPick; dt->end = idxDur + iStart - iPick; - // The integration window is complete -> finalize (stop further updates). - setStatus(Finished, 100.0); - SEISCOMP_DEBUG("%s.%s.%s: Mwpd FINAL ampInt=%g nm*s T0raw=%.1fs%s peak@%.1fs " - "S-P=%.1fs window=%.1fs win=%.0fs (pos=%g neg=%g) gain=%g", + setStatus(Finished, 100.0); // T0 stable -> finalize + SEISCOMP_DEBUG("%s.%s.%s: Mwpd FINAL ampInt=%g nm*s T0raw=%.1fs peak@%.1fs " + "S-P=%.1fs integDur=%.1fs win=%.0fs (pos=%g neg=%g) gain=%g", _environment.networkCode.c_str(), _environment.stationCode.c_str(), _environment.locationCode.c_str(), - amplitude->value, durRaw, durRaw > 0.0 ? "" : "(unresolved)", - peakRelSec, sp, integDur, availDur, + amplitude->value, durRaw, peakRelSec, sp, integDur, availDur, intPos[idxDur] * 1.0e9, intNeg[idxDur] * 1.0e9, gain); return true; diff --git a/plugins/magnitudes/mwpd/config.cpp b/plugins/magnitudes/mwpd/config.cpp index 3df33e5af..12c1500a1 100644 --- a/plugins/magnitudes/mwpd/config.cpp +++ b/plugins/magnitudes/mwpd/config.cpp @@ -70,7 +70,7 @@ double mwpdDepthCorrection(double depthKm) { bool readMwpdConfig(const Processing::Settings &settings, const std::string &prefix, MwpdConfig &out) { // BRB-HP restitution + displacement integral. - settings.getValue(out.gainFrequency, prefix + ".gainFrequency"); + settings.getValue(out.highpassCorner, prefix + ".highpassCorner"); settings.getValue(out.hpOrder, prefix + ".highpassOrder"); settings.getValue(out.analysisPreP, prefix + ".analysisPreP"); diff --git a/plugins/magnitudes/mwpd/descriptions/global_mwpd.xml b/plugins/magnitudes/mwpd/descriptions/global_mwpd.xml index 6d608a495..1fa6de7c9 100644 --- a/plugins/magnitudes/mwpd/descriptions/global_mwpd.xml +++ b/plugins/magnitudes/mwpd/descriptions/global_mwpd.xml @@ -18,10 +18,10 @@ Measurement parameters for the Mwpd amplitude (displacement integral over the source duration T0). - - BRB-HP high-pass corner used for restitution to displacement (MWPD_GAIN_FREQUENCY). + + BRB-HP high-pass corner for the displacement trace (Early-est filter_hp_bu_co_0_005_n_2). Keep low (~0.005 Hz) to preserve the long-period moment of great events. - + Butterworth order of the BRB-HP high-pass filter. @@ -42,8 +42,8 @@ Earliest the T0 search may terminate (MIN_MWPD_DUR). - - Cap on T0 and on the post-pick signal window (Early-est MAX_MWPD_DUR is 1200 s). + + MAX_MWPD_DUR: cap on T0 and on the post-pick signal/integration window. Envelope signal-to-noise ratio below which the T0 search terminates (SIGNAL_TO_NOISE_RATIO_T0_END). diff --git a/plugins/magnitudes/mwpd/magnitude.cpp b/plugins/magnitudes/mwpd/magnitude.cpp index 0d49a5539..40077dc68 100644 --- a/plugins/magnitudes/mwpd/magnitude.cpp +++ b/plugins/magnitudes/mwpd/magnitude.cpp @@ -105,14 +105,17 @@ MagnitudeProcessor_Mwpd::computeMagnitude( } } - // Moment scaling for large interplate-thrust / tsunami events, Lomax & - // Michelini (2009) eq (5a): M0pd = M0*(M0/M0cutoff)^0.45 for M0 >= M0cutoff - // (Mw ~ 7.2), i.e. in magnitude terms Mwpd = raw + 0.45*(raw - 7.2). The - // function is continuous at the cutoff. The paper restricts this to - // interplate-thrust/tsunami events; event-type classification is not - // available here, so it is applied to all large events (configurable). - if ( _cfg.useDurationRamp && raw > _cfg.magCutoff ) { - corr += (raw - _cfg.magCutoff) * _cfg.rampPow; + // Moment scaling, Early-est calculate_corrected_Mwpd_Mag (USE_MPWD_CORR): + // DURATION-gated ramp -- only for T0 > 90 s (great/slow events), ramped + // linearly 90->110 s, then add (raw - 7.2) * 0.45. (Early-est's pure + // magnitude-gated form, eq 5a, is USE_MOMENT_CORR and is disabled there.) + if ( _cfg.useDurationRamp && duration > _cfg.durRampLow ) { + double ramp = (duration - _cfg.durRampLow) + / (_cfg.durRampHigh - _cfg.durRampLow); + if ( ramp > 1.0 ) { + ramp = 1.0; + } + corr += ramp * (raw - _cfg.magCutoff) * _cfg.rampPow; } value = corr; diff --git a/plugins/magnitudes/mwpd/mwpd.h b/plugins/magnitudes/mwpd/mwpd.h index cce2b7607..052f206a1 100644 --- a/plugins/magnitudes/mwpd/mwpd.h +++ b/plugins/magnitudes/mwpd/mwpd.h @@ -40,24 +40,24 @@ namespace Mwpd { */ struct MwpdConfig { // --- BRB-HP restitution + displacement integral (amplitude side) ------ - double gainFrequency = 0.15; //!< [Hz] MWPD_GAIN_FREQUENCY: BRB high-pass corner - int hpOrder = 4; //!< Butterworth high-pass order for the BRB-HP trace + // Early-est high-passes the displacement trace with filter_hp_bu_co_0_005_n_2 + // = Butterworth HP 0.005 Hz, order 2 (mkfilter -Bu -Hp -o 2 -a 2.5e-4). + // (MWPD_GAIN_FREQUENCY=0.15 is only the gain-reference frequency, NOT a + // filter. A 0.15 Hz HP removes periods >7 s and guts great-event moment.) + double highpassCorner = 0.005; //!< [Hz] BRB-HP corner (filter_hp_bu_co_0_005_n_2) + int hpOrder = 2; //!< Butterworth high-pass order for the BRB-HP trace double analysisPreP = 1.0; //!< [s] START_ANALYSIS_BEFORE_P_BRB_HP // --- HF envelope (T0 estimator) --------------------------------------- - // Lomax & Michelini (2009) use a narrow ~1.0 Hz Gaussian filter for the - // duration envelope (their Fig. 2). A narrow band centred on 1 Hz gives a - // broad, slowly-decaying envelope and hence the long apparent durations - // (40-200 s) in their Table 1. (Early-est's operational code instead uses a - // 1-5 Hz Butterworth, which yields much shorter T0.) - double hfFmin = 0.5; //!< [Hz] envelope band low edge (~1 Hz centre) - double hfFmax = 1.5; //!< [Hz] envelope band high edge + // Early-est uses filter_bp_bu_co_1_5_n_4 = Butterworth band-pass 1-5 Hz o4. + double hfFmin = 1.0; //!< [Hz] envelope band low edge + double hfFmax = 5.0; //!< [Hz] envelope band high edge int hfOrder = 4; //!< envelope band-pass order double smoothHalfWidth = 5.0; //!< [s] envelope boxcar smoothing half-width // --- T0 source-duration estimation ------------------------------------ double minDuration = 20.0; //!< [s] MIN_MWPD_DUR: earliest the T0 search may terminate - double maxDuration = 300.0; //!< [s] integration / signal-window length (capped at S-P); Early-est integrates over this window unless a robust T0 shortens it + double maxDuration = 1200.0; //!< [s] MAX_MWPD_DUR: T0 search / integration cap double durationFloor = 0.2; //!< [s] MINIMUN_DURATION double snT0End = 3.0; //!< SIGNAL_TO_NOISE_RATIO_T0_END double peakRatioT0End = 0.025; //!< SIGNAL_TO_PEAK_RATIO_T0_END From be9ec2273389e62531d941c99fac7de3a6417579 Mon Sep 17 00:00:00 2001 From: Mustafa Comoglu Date: Wed, 24 Jun 2026 19:45:16 +1000 Subject: [PATCH 4/8] [magnitudes] Mwpd: add documentation (global_mwpd.rst) Method, amplitude/magnitude processing, the 0.005 Hz BRB-HP and T0-based integration, configuration notes, the GCMT calibration result (slope ~1.02, sigma ~0.15, no saturation) and references (Lomax & Michelini 2009; Tsuboi 1995). --- .../mwpd/descriptions/global_mwpd.rst | 113 ++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 plugins/magnitudes/mwpd/descriptions/global_mwpd.rst diff --git a/plugins/magnitudes/mwpd/descriptions/global_mwpd.rst b/plugins/magnitudes/mwpd/descriptions/global_mwpd.rst new file mode 100644 index 000000000..f0a99fff5 --- /dev/null +++ b/plugins/magnitudes/mwpd/descriptions/global_mwpd.rst @@ -0,0 +1,113 @@ +:math:`M_{wpd}` is a per-station **duration--amplitude moment magnitude** for +large earthquakes, determined from teleseismic *P* waveforms. It integrates the +broad-band *P*-wave ground displacement over the apparent source duration +:math:`T_0`, after Lomax & Michelini (2009), and is a port of the Mwpd +implementation in Early-est (A. Lomax). Because it integrates over the whole +source duration rather than taking the peak (as :math:`M_{wp}` does), it does +**not saturate** for great earthquakes. + +The plugin contributes both an amplitude processor and a magnitude processor of +type ``Mwpd``. Both use the vertical broad-band component only. + +Method +====== + +Given the far-field *P* displacement :math:`u(t)` for a source of duration +:math:`T_0`, the scalar seismic moment is (Tsuboi et al. 1995; Lomax & +Michelini 2009) + +.. math:: + + M_0 = C_M \int_{t_P}^{t_P + T_0} u(t)\, \mathrm{d}t , + +where :math:`t_P` is the *P*-arrival time. The implementation accumulates the +running displacement integral separately over its **positive and negative +lobes** (to separate the direct *P* wave from later reflected/secondary phases +of opposite polarity, eq. 3 of the paper) and uses the larger of the two at +:math:`T_0`. The moment magnitude follows the standard relation + +.. math:: + + M_{wpd}^{\mathrm{raw}} = \tfrac{2}{3}\left(\log_{10} M_0 - 9.1\right) + - C_\Delta(\Delta, h) , + +with a distance correction :math:`C_\Delta` (INGV/Early-est, subtracted; zero +for :math:`h>100` km), then a PREM step depth correction :math:`C_h(h)` and a +moment-scaling term for great/slow events: + +.. math:: + + M_{wpd} = M_{wpd}^{\mathrm{raw}} + C_h(h) + + r\,(M_{wpd}^{\mathrm{raw}} - 7.2)\cdot 0.45 , + \qquad r = \mathrm{clip}\!\left(\tfrac{T_0-90}{110-90},\,0,\,1\right). + +The duration ramp :math:`r` engages only for :math:`T_0 > 90` s (the moment +scaling for large interplate-thrust / tsunamigenic events, eq. 5a). + +Amplitude +========= + +For each *P* pick on the vertical broad-band, the amplitude processor: + +#. restitutes counts to ground velocity (sensitivity gain) and high-passes with + a Butterworth filter at a **0.005 Hz** corner (the Early-est BRB-HP filter); + a low corner is essential to retain the long-period displacement that + carries the moment of great earthquakes; +#. single-integrates to displacement and accumulates the running double + integral into positive/negative lobes; +#. estimates the **apparent source duration** :math:`T_0` from the + high-frequency envelope: the velocity is band-passed 1--5 Hz, squared and + boxcar-smoothed, and :math:`T_0` is derived from the times at which this + envelope last drops below 90/80/50/20 % of its peak; +#. integrates over :math:`\min(T_0,\ t_S-t_P,\ \mathtt{maxDuration})` --- the + :math:`S\!-\!P` cap (from a travel-time table) keeps the integral free of + *S* and surface-wave energy. + +The amplitude carries the displacement integral (unit ``nm*s``); :math:`T_0` is +carried as the amplitude period. Computation is progressive: the value is +updated as data stream in and finalised once :math:`T_0` is resolved. + +Magnitude +========= + +The magnitude processor reads the displacement integral (``nm*s``) and +:math:`T_0` (period) and applies the relations above, with the moment constant + +.. math:: + + C_M = 4\pi\,\rho\,V_p^{3}\,F_p \cdot \tfrac{10000}{90}\cdot 1000 + \approx 4.68\times10^{21} + +(Tsuboi constant; :math:`\rho=3400`, :math:`V_p=7900`, :math:`F_p=2`). As +:math:`M_{wpd}` is already a moment magnitude, the network estimation is the +identity; the network magnitude is a robust (median/trimmed) average. + +Calibration +=========== + +Validated against GCMT moment magnitudes over ~1000 events (M 6.0--8.8, 2015--): +:math:`M_{wpd}` tracks :math:`M_w^{\mathrm{CMT}}` with a slope of ~1.02, mean +difference ~+0.05 and :math:`\sigma\approx0.15`, with **no saturation** across +the magnitude range and no significant depth dependence --- consistent with +Lomax & Michelini (2009) and with operational Early-est. + +Configuration +============= + +Add ``mwpd`` to the ``plugins`` parameter and enable the ``Mwpd`` amplitude and +magnitude in :ref:`scamp` / :ref:`scmag` (or :ref:`scolv`). The defaults +reproduce Early-est; the most important amplitude parameter is +``amplitudes.Mwpd.highpassCorner`` (0.005 Hz --- keep low). See the binding +parameter descriptions for the full list. Because :math:`M_{wpd}` integrates +over the source duration, it requires a long post-*P* window (up to +``maxDuration``), so the final value has higher latency than :math:`M_{wp}`. + +References +========== + +* Lomax, A. & Michelini, A. (2009). :math:`M_{wpd}`: a duration--amplitude + procedure for rapid determination of earthquake magnitude and tsunamigenic + potential from *P* waveforms. *Geophys. J. Int.* **176**, 200--214, + doi:10.1111/j.1365-246X.2008.03974.x +* Tsuboi, S. et al. (1995). Rapid determination of :math:`M_w` from broadband + *P* waveforms. *Bull. Seismol. Soc. Am.* **85**, 606--613. From f0e9e910dcce03db5df0a7f5f0c5802f74ff0600 Mon Sep 17 00:00:00 2001 From: Mustafa Comoglu Date: Wed, 24 Jun 2026 19:49:03 +1000 Subject: [PATCH 5/8] [magnitudes] Mwpd: add GCMT calibration result (figure + table) to the docs Embeds the validation against GCMT (972 events, Mw 6.0-8.8): Mwpd-vs-Mw scatter figure plus per-magnitude and per-depth difference tables (slope 1.02, mean +0.05, sigma 0.15, no saturation), in global_mwpd.rst. --- .../mwpd/descriptions/global_mwpd.rst | 43 ++++++++++++++++-- .../mwpd/descriptions/mwpd_calibration.png | Bin 0 -> 140861 bytes 2 files changed, 38 insertions(+), 5 deletions(-) create mode 100644 plugins/magnitudes/mwpd/descriptions/mwpd_calibration.png diff --git a/plugins/magnitudes/mwpd/descriptions/global_mwpd.rst b/plugins/magnitudes/mwpd/descriptions/global_mwpd.rst index f0a99fff5..a0b42a99c 100644 --- a/plugins/magnitudes/mwpd/descriptions/global_mwpd.rst +++ b/plugins/magnitudes/mwpd/descriptions/global_mwpd.rst @@ -85,11 +85,44 @@ identity; the network magnitude is a robust (median/trimmed) average. Calibration =========== -Validated against GCMT moment magnitudes over ~1000 events (M 6.0--8.8, 2015--): -:math:`M_{wpd}` tracks :math:`M_w^{\mathrm{CMT}}` with a slope of ~1.02, mean -difference ~+0.05 and :math:`\sigma\approx0.15`, with **no saturation** across -the magnitude range and no significant depth dependence --- consistent with -Lomax & Michelini (2009) and with operational Early-est. +The implementation was validated against GCMT moment magnitudes for 972 events +(:math:`M_w` 6.0--8.8, 2015--2026), processed through this algorithm with +broad-band stations from global networks. :math:`M_{wpd}` tracks +:math:`M_w^{\mathrm{CMT}}` along the 1:1 line with **no saturation** and no +significant depth dependence. + +.. figure:: mwpd_calibration.png + :width: 16cm + :align: center + + :math:`M_{wpd}` (this plugin) versus GCMT :math:`M_w` for 972 events, + coloured by source depth. Overall slope 1.02, mean difference +0.05, + :math:`\sigma = 0.15`, correlation r = 0.95. + +Mean difference :math:`M_{wpd} - M_w^{\mathrm{CMT}}` by magnitude band: + +============= ====== ===== ==== +:math:`M_w` mean sigma N +============= ====== ===== ==== +6.0 -- 7.0 +0.07 0.14 831 +7.0 -- 7.5 -0.05 0.13 94 +7.5 -- 8.0 -0.04 0.20 40 +8.0 -- 9.5 -0.09 0.16 7 +============= ====== ===== ==== + +and by source depth: + +================ ====== ===== ==== +depth (km) mean sigma N +================ ====== ===== ==== +0 -- 70 +0.07 0.16 702 +70 -- 300 -0.02 0.13 175 +300 -- 800 +0.01 0.10 95 +================ ====== ===== ==== + +These results are consistent with operational Early-est (slope ~1.01, +:math:`\pm 0.13`) and with Lomax & Michelini (2009), which reports +:math:`M_{wpd}` matching :math:`M_w^{\mathrm{CMT}}` within :math:`\pm 0.2`. Configuration ============= diff --git a/plugins/magnitudes/mwpd/descriptions/mwpd_calibration.png b/plugins/magnitudes/mwpd/descriptions/mwpd_calibration.png new file mode 100644 index 0000000000000000000000000000000000000000..0ef332a17fbe195bd4f8f20aae88860f1dfa9864 GIT binary patch literal 140861 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%0Du67t1ghangLKD#I*wcPz$akMC&Me<$+s+ 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 Date: Wed, 24 Jun 2026 23:14:14 +1000 Subject: [PATCH 6/8] [magnitudes] Mwpd: keep the plugin's symbols out of the dynamic symbol table Per review (gempa-jabe): the plugin's own classes and helper functions were exported (16 global symbols) although nothing outside the plugin uses them -- the loader needs only createSCPlugin and the processors register via static factories. Give the cross-object-file symbols (readMwpdConfig, the moment/ distance/depth corrections, and the two processor classes) hidden visibility via a small MWPD_LOCAL attribute; single-TU helpers were already in anonymous namespaces. Result: zero exported Mwpd symbols, createSCPlugin unchanged, plugin still loads and registers. --- plugins/magnitudes/mwpd/mwpd.h | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/plugins/magnitudes/mwpd/mwpd.h b/plugins/magnitudes/mwpd/mwpd.h index 052f206a1..fcbaae05a 100644 --- a/plugins/magnitudes/mwpd/mwpd.h +++ b/plugins/magnitudes/mwpd/mwpd.h @@ -33,6 +33,19 @@ namespace Mwpd { #define MWPD_AMP_UNIT "nm*s" +// All of this plugin's own symbols are used only inside the plugin (the loader +// needs only createSCPlugin; the processors register via static factories), so +// keep them out of the shared library's dynamic symbol table. Single-TU helpers +// live in anonymous namespaces in the .cpp files; symbols shared across object +// files (the config reader, the corrections, the processor classes) get hidden +// visibility here. +#if defined(__GNUC__) || defined(__clang__) + #define MWPD_LOCAL __attribute__((visibility("hidden"))) +#else + #define MWPD_LOCAL +#endif + + /** * Configuration shared by the amplitude and magnitude processors. Defaults * reproduce the hard-coded Early-est 1.2.9 constants @@ -87,21 +100,21 @@ struct MwpdConfig { /** Reads MwpdConfig from a binding. @p prefix is "amplitudes.Mwpd" or * "magnitudes.Mwpd". Missing keys keep their (Early-est) defaults. */ -bool readMwpdConfig(const Processing::Settings &settings, +MWPD_LOCAL bool readMwpdConfig(const Processing::Settings &settings, const std::string &prefix, MwpdConfig &out); /** Tsuboi (1995) moment constant, reproduced from Early-est: * 4 pi * rho * Vp^3 * FP * (10000/90) deg->km * 1000 km->m. */ -double mwpdMomentConstant(const MwpdConfig &cfg); +MWPD_LOCAL double mwpdMomentConstant(const MwpdConfig &cfg); /** INGV_EE distance correction (subtracted from the raw magnitude), * calculate_Mwp_correction_INGV_EE: 0 if delta<0 or depth>100 km. */ -double mwpdDistanceCorrection(double deltaDeg, double depthKm); +MWPD_LOCAL double mwpdDistanceCorrection(double deltaDeg, double depthKm); /** PREM step depth correction get_depth_corr_mwpd_prem (returns -999 if * the depth is below the first table row). */ -double mwpdDepthCorrection(double depthKm); +MWPD_LOCAL double mwpdDepthCorrection(double depthKm); // --------------------------------------------------------------------------- @@ -112,7 +125,7 @@ double mwpdDepthCorrection(double depthKm); // Emits the displacement integral over T0 (nm*s) and carries T0 as the // amplitude "period". // --------------------------------------------------------------------------- -class SC_SYSTEM_CLIENT_API AmplitudeProcessor_Mwpd : public Processing::AmplitudeProcessor { +class MWPD_LOCAL AmplitudeProcessor_Mwpd : public Processing::AmplitudeProcessor { public: AmplitudeProcessor_Mwpd(); @@ -146,7 +159,7 @@ class SC_SYSTEM_CLIENT_API AmplitudeProcessor_Mwpd : public Processing::Amplitud // integral into M0 and Mwpd, applying the distance, PREM depth and duration // corrections. The source duration T0 arrives in the amplitude "period". // --------------------------------------------------------------------------- -class SC_SYSTEM_CLIENT_API MagnitudeProcessor_Mwpd : public Processing::MagnitudeProcessor { +class MWPD_LOCAL MagnitudeProcessor_Mwpd : public Processing::MagnitudeProcessor { public: MagnitudeProcessor_Mwpd(); From c94620f5747fb403180eb39c81554d9949b10287 Mon Sep 17 00:00:00 2001 From: Mustafa Comoglu Date: Wed, 24 Jun 2026 23:24:48 +1000 Subject: [PATCH 7/8] [magnitudes] Mwpd: remove unused variable and fix a debug label Drop the now-unused t0Resolved flag (resolution is tested via durRaw>0), which also clears a -Wunused-but-set-variable warning, and correct the setup debug label from "gainFreq" to "HPcorner". --- plugins/magnitudes/mwpd/amplitude.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/plugins/magnitudes/mwpd/amplitude.cpp b/plugins/magnitudes/mwpd/amplitude.cpp index 18d0ac445..1ebb3d71e 100644 --- a/plugins/magnitudes/mwpd/amplitude.cpp +++ b/plugins/magnitudes/mwpd/amplitude.cpp @@ -151,7 +151,7 @@ bool AmplitudeProcessor_Mwpd::setup(const Processing::Settings &settings) { } } - SEISCOMP_DEBUG("%s: gainFreq=%.2fHz HF=%.1f-%.1fHz preP=%.1fs maxDur=%.0fs spCap=%d", + SEISCOMP_DEBUG("%s: HPcorner=%.3fHz HF=%.1f-%.1fHz preP=%.1fs maxDur=%.0fs spCap=%d", type().c_str(), _cfg.highpassCorner, _cfg.hfFmin, _cfg.hfFmax, _cfg.analysisPreP, _cfg.maxDuration, _ttt != nullptr); return true; @@ -264,13 +264,11 @@ bool AmplitudeProcessor_Mwpd::computeAmplitude( // 2) High-frequency envelope and the source duration T0 (durRaw). // ===================================================================== double durRaw; // source-duration estimate [s] (used for the ramp) - bool t0Resolved = false; bool t0Terminated = false; // T0 search hit a termination criterion (final) double peakRelSec = -1.0; // time of the envelope peak after P (debug) if ( _cfg.fixedDuration ) { durRaw = _cfg.fixedDurationVal; - t0Resolved = true; t0Terminated = true; } else { @@ -336,7 +334,6 @@ bool AmplitudeProcessor_Mwpd::computeAmplitude( amp20 = amp; idx20 = rel; durRaw = durationFromLevels(idx90, idx80, idx50, idx20, deltaTime, _cfg.durationFloor); - t0Resolved = true; } } else if ( amp > 0.2 * ampPeak ) { From d33a6afda3a02040a379807a052969f47d99f2e7 Mon Sep 17 00:00:00 2001 From: Mustafa Comoglu Date: Wed, 24 Jun 2026 23:40:19 +1000 Subject: [PATCH 8/8] [magnitudes] Mwpd: refine documentation per author (A. Lomax) feedback - Clarify no-saturation applies to long-rupture events (tsunami / great quakes). - Cite "Lomax & Michelini 2009" explicitly for eq. 3 and eq. 5a. - Reword the progressive-computation note for real-time application. - Replace the SeisComP "estimateMw identity" jargon with a plain statement that no further Mw conversion is applied and the network value is a robust average of station Mwpd. - Note Mwpd(RT) (Lomax & Michelini 2013) as a lower-latency real-time variant and add the reference. --- .../mwpd/descriptions/global_mwpd.rst | 27 +++++++++++++------ 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/plugins/magnitudes/mwpd/descriptions/global_mwpd.rst b/plugins/magnitudes/mwpd/descriptions/global_mwpd.rst index a0b42a99c..989979860 100644 --- a/plugins/magnitudes/mwpd/descriptions/global_mwpd.rst +++ b/plugins/magnitudes/mwpd/descriptions/global_mwpd.rst @@ -4,7 +4,8 @@ broad-band *P*-wave ground displacement over the apparent source duration :math:`T_0`, after Lomax & Michelini (2009), and is a port of the Mwpd implementation in Early-est (A. Lomax). Because it integrates over the whole source duration rather than taking the peak (as :math:`M_{wp}` does), it does -**not saturate** for great earthquakes. +**not saturate** for events with long rupture duration, such as tsunami +earthquakes and great earthquakes. The plugin contributes both an amplitude processor and a magnitude processor of type ``Mwpd``. Both use the vertical broad-band component only. @@ -23,7 +24,7 @@ Michelini 2009) where :math:`t_P` is the *P*-arrival time. The implementation accumulates the running displacement integral separately over its **positive and negative lobes** (to separate the direct *P* wave from later reflected/secondary phases -of opposite polarity, eq. 3 of the paper) and uses the larger of the two at +of opposite polarity, eq. 3 of Lomax & Michelini 2009) and uses the larger of the two at :math:`T_0`. The moment magnitude follows the standard relation .. math:: @@ -42,7 +43,8 @@ moment-scaling term for great/slow events: \qquad r = \mathrm{clip}\!\left(\tfrac{T_0-90}{110-90},\,0,\,1\right). The duration ramp :math:`r` engages only for :math:`T_0 > 90` s (the moment -scaling for large interplate-thrust / tsunamigenic events, eq. 5a). +scaling for large interplate-thrust / tsunamigenic events, eq. 5a in Lomax & +Michelini 2009). Amplitude ========= @@ -64,8 +66,9 @@ For each *P* pick on the vertical broad-band, the amplitude processor: *S* and surface-wave energy. The amplitude carries the displacement integral (unit ``nm*s``); :math:`T_0` is -carried as the amplitude period. Computation is progressive: the value is -updated as data stream in and finalised once :math:`T_0` is resolved. +carried as the amplitude period. In real-time application, the computation is +progressive: the processing is updated as new data arrives and finalised once +:math:`T_0` is resolved. Magnitude ========= @@ -78,9 +81,11 @@ The magnitude processor reads the displacement integral (``nm*s``) and C_M = 4\pi\,\rho\,V_p^{3}\,F_p \cdot \tfrac{10000}{90}\cdot 1000 \approx 4.68\times10^{21} -(Tsuboi constant; :math:`\rho=3400`, :math:`V_p=7900`, :math:`F_p=2`). As -:math:`M_{wpd}` is already a moment magnitude, the network estimation is the -identity; the network magnitude is a robust (median/trimmed) average. +(Tsuboi constant; :math:`\rho=3400`, :math:`V_p=7900`, :math:`F_p=2`). Since +:math:`M_{wpd}` is already a moment magnitude, no further :math:`M_w` conversion +is applied (SeisComP's per-station ``estimateMw`` step is the identity here); +the network magnitude is a robust (median / trimmed-mean) average of the station +:math:`M_{wpd}` values. Calibration =========== @@ -134,6 +139,10 @@ reproduce Early-est; the most important amplitude parameter is parameter descriptions for the full list. Because :math:`M_{wpd}` integrates over the source duration, it requires a long post-*P* window (up to ``maxDuration``), so the final value has higher latency than :math:`M_{wp}`. +For faster tsunami early warning, Lomax & Michelini (2013) describe +:math:`M_{wpd}\mathrm{(RT)}`, a real-time variant that uses a smaller minimum +station distance and avoids some of the duration estimation and re-scaling; +it is not implemented in this plugin. References ========== @@ -142,5 +151,7 @@ References procedure for rapid determination of earthquake magnitude and tsunamigenic potential from *P* waveforms. *Geophys. J. Int.* **176**, 200--214, doi:10.1111/j.1365-246X.2008.03974.x +* Lomax, A. & Michelini, A. (2013). Tsunami early warning within five minutes. + *Pure Appl. Geophys.* **170**, 1385--1395, doi:10.1007/s00024-012-0512-6 * Tsuboi, S. et al. (1995). Rapid determination of :math:`M_w` from broadband *P* waveforms. *Bull. Seismol. Soc. Am.* **85**, 606--613.