Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,30 @@ and this project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.ht
that negated codameter output to get physical dv/v must remove that
negation.

- **The stretching-family trial-epsilon search now resamples `current`, not
`reference`.** `stretching_cc`, `measure_stretching_trailing`, and
`measure_wts` previously interpolated the *reference* waveform at trial
positions `t/(1+eps)` and held `current` fixed; they now interpolate
*current* at `(1+eps)*t` and hold `reference` fixed, matching the field's
usual convention (the reference is the stable, often multi-day-averaged
anchor; the current trace is the one being tested against it). **The exact
conversion `dv/v = -eps/(1+eps)` is unchanged** — both conventions give
the identical exact map (see the derivation in the PR), so this is not a
second sign-convention flip; it is an internal numerics change with a
small (single-digit-percent) shift in finite-sample results, since a
different (per-day, typically noisier) trace is now the one being
resampled. Added `synthetic_demo.dvv_to_epsilon` (the exact inverse of
`eps_to_dvv`) and `synthetic_demo._stretch_window`, a common
valid-support window shared across the whole epsilon grid so no trial
epsilon is silently extrapolated and every candidate is scored on an
identical sample count (warns and shrinks the window if the requested
one would need extrapolation at the edges of `eps_max`; none of the
packaged `use_cases.py` configs hit this).
`tests/data/golden/manifest.json` regenerated against the new numerics
(`golden.MANIFEST_VERSION` bumped 2 → 3 so stale per-user caches
regenerate); a hidden/private golden corpus built with `private_golden.py`
before this change should be regenerated too.

### Added

- `synthetic_demo.eps_to_dvv`: the exact stretch-to-velocity map.
Expand All @@ -43,13 +67,14 @@ and this project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.ht
the estimators whose band usage is that one linear filter (stretching, WCC,
DTW, MWCS — the wavelet estimators raise).
- **`measure_stretching_trailing`** — vectorized stretching against a trailing
(moving) reference. The stretched sample positions `t/(1+eps)` are
(moving) reference. The stretched sample positions `(1+eps)*t` are
data-independent, so the interpolation gather indices/weights are computed
once per epsilon and applied to all days at once; trailing references come
from a cumulative sum and the band-pass runs once over the whole matrix.
`deviations._moving_reference` dispatches to it for the stretching
estimator (~3x on the 3-year volcano synthetic, observed 3-4.5x across
repeated runs), keeping the generic per-day loop for the other estimators.
(Updated below: the resampled trace is `current`, not `reference`.)

### Changed

Expand Down
Binary file modified literature/figs/demo_10_deviations.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified literature/figs/demo_11_multiverse.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified literature/figs/demo_12_bayes.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified literature/figs/demo_13_branch_asymmetry.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified literature/figs/demo_14_network_pairs.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified literature/figs/demo_15_window_envelope.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added literature/figs/demo_16_band_sensitivity.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added literature/figs/demo_17_reference_schemes.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added literature/figs/demo_18_stack_coherence.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified literature/figs/demo_1_methods.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified literature/figs/demo_2_aggregation.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified literature/figs/demo_3_uncertainty.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified literature/figs/demo_4_frequency_depth.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified literature/figs/demo_5_window_band.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified literature/figs/demo_6_stacking.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified literature/figs/demo_7_reference.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified literature/figs/demo_8_artifacts.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified literature/figs/demo_9_multiverse.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added literature/figs/realdata_1_validation.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added literature/figs/realdata_2_interferograms.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added literature/figs/realdata_3_warmup.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
861 changes: 562 additions & 299 deletions paper/manuscript_marine.qmd

Large diffs are not rendered by default.

1,184 changes: 769 additions & 415 deletions paper/manuscript_marine.tex

Large diffs are not rendered by default.

160 changes: 160 additions & 0 deletions paper/references.bib
Original file line number Diff line number Diff line change
@@ -1,3 +1,19 @@
@article{poupinet84,
author = {Poupinet, G. and Ellsworth, W. L. and Frechet, J.},
title = {Monitoring velocity variations in the crust using earthquake doublets: An application to the {Calaveras} Fault, {California}},
journal = {Journal of Geophysical Research: Solid Earth},
volume = {89}, number = {B7}, pages = {5719--5731}, year = {1984},
doi = {10.1029/jb089ib07p05719}
}

@article{lobkis03,
author = {Lobkis, Oleg I. and Weaver, Richard L.},
title = {Coda-Wave Interferometry in Finite Solids: Recovery of {P}-to-{S} Conversion Rates in an Elastodynamic Billiard},
journal = {Physical Review Letters},
volume = {90}, number = {25}, pages = {254302}, year = {2003},
doi = {10.1103/PhysRevLett.90.254302}
}

@article{SensSchonfelder2006,
author = {Sens-Sch{\"o}nfelder, Christoph and Wegler, Ulrich},
title = {Passive image interferometry and seasonal variations of seismic velocities at {Merapi} Volcano, {Indonesia}},
Expand Down Expand Up @@ -203,6 +219,19 @@ @article{Okubo2024
doi = {10.1029/2023JB028084}
}

@article{Denolle25b,
author = {Denolle, Marine A. and Shi, Qibin and Clements, Tim and Viens, Lo{\"\i}c and Rodriguez-Tribaldos, Veronica and Cotton, Fabrice},
title = {Ambient field seismology in critical zone hydrological sciences},
journal = {Comptes Rendus. G\'eoscience},
pages = {425--451},
year = {2025},
publisher = {Acad\'emie des sciences, Paris},
volume = {357},
doi = {10.5802/crgeos.310},
language = {en}
}


@article{Kidiwela2026,
author = {Kidiwela, Maleen and Denolle, Marine A. and Wilcock, William S. D. and Feng, K. F.},
title = {Active protothrusts and fluid highways: Seismic noise reveals hidden subduction dynamics in Cascadia},
Expand All @@ -229,3 +258,134 @@ @book{Mavko2009
year = {2009},
doi = {10.1017/CBO9780511626753}
}

% Deployment examples cited narratively in the Introduction (not part of
% the 103-study processing-choice survey, so kept here rather than in the
% auto-generated survey.bib).
@article{CubukSabuncu2021,
author = {Cubuk-Sabuncu, Ye{\c s}im and J{\'o}nsd{\'o}ttir, Kristín and Caudron, Corentin and Lecocq, Thomas and Parks, Michelle and Geirsson, Halld{\'o}r and Mordret, Aur{\'e}lien},
title = {Temporal Seismic Velocity Changes During the 2020 Rapid Inflation at Mt. {\th}orbj{\"o}rn-Svartsengi, Iceland, Using Seismic Ambient Noise},
journal = {Geophysical Research Letters},
year = {2021},
volume = {48},
pages = {e2020GL092265},
doi = {10.1029/2020GL092265}
}

@article{Ouellet2022,
author = {Ouellet, Susanne M. and Dettmer, Jan and Olivier, Gerrit and de Wit, Tjaart and Lato, Matt},
title = {Advanced monitoring of tailings dam performance using seismic noise and stress models},
journal = {Communications Earth \& Environment},
year = {2022},
volume = {3},
pages = {301},
doi = {10.1038/s43247-022-00629-w}
}

@article{Planes2016,
author = {Plan{\`e}s, Thomas and Mooney, Michael A. and Rittgers, Jacob B. R. and Parekh, Malcolm L. and Behm, Michael and Snieder, Roel},
title = {Time-lapse monitoring of internal erosion in earthen dams and levees using ambient seismic noise},
journal = {G{\'e}otechnique},
year = {2016},
volume = {66},
number = {4},
pages = {301--312},
doi = {10.1680/jgeot.14.P.268}
}

@article{Tsuji2021,
author = {Tsuji, Takeshi and Ikeda, Tatsunori and Matsuura, Ryosuke and Mukumoto, Kota and Hutapea, Fernando Lawrens and Kimura, Tsunehisa and Yamaoka, Koshun and Shinohara, Masanao},
title = {Continuous monitoring system for safe managements of {CO2} storage and geothermal reservoirs},
journal = {Scientific Reports},
year = {2021},
volume = {11},
pages = {19120},
doi = {10.1038/s41598-021-97881-5}
}

@article{Rivet2014,
author = {Rivet, Diane and Brenguier, Florent and Clarke, Daniel and Shapiro, Nikola{\"i} M. and Peltier, Aline},
title = {Long-term dynamics of {Piton de la Fournaise} volcano from 13 years of seismic velocity change measurements and {GPS} observations},
journal = {Journal of Geophysical Research: Solid Earth},
volume = {119},
number = {10},
pages = {7654--7666},
year = {2014},
doi = {10.1002/2014JB011307}
}

@article{SensSchonfelder2014,
author = {Sens-Sch{\"o}nfelder, Christoph and Pomponi, Eraldo and Peltier, Aline},
title = {Dynamics of {Piton de la Fournaise} volcano observed by passive image interferometry with multiple references},
journal = {Journal of Volcanology and Geothermal Research},
volume = {276},
pages = {32--45},
year = {2014},
doi = {10.1016/j.jvolgeores.2014.02.012}
}

@article{James2017,
author = {James, S. R. and Knox, H. A. and Abbott, R. E. and Screaton, E. J.},
title = {Improved moving window cross-spectral analysis for resolving large temporal seismic velocity changes in permafrost},
journal = {Geophysical Research Letters},
volume = {44},
number = {9},
pages = {4018--4026},
year = {2017},
doi = {10.1002/2016GL072468}
}

@article{ZotzWilson2019,
author = {Zotz-Wilson, Reuben and Boerrigter, Thijs and Barnhoorn, Auke},
title = {Coda-wave monitoring of continuously evolving material properties and the precursory detection of yielding},
journal = {The Journal of the Acoustical Society of America},
volume = {145},
number = {2},
pages = {1060--1068},
year = {2019},
doi = {10.1121/1.5091012}
}

@article{Hadziioannou2011,
author = {Hadziioannou, C. and Larose, E. and Baig, A. and Roux, P. and Campillo, M.},
title = {Improving temporal resolution in ambient noise monitoring of seismic wave speed},
journal = {Journal of Geophysical Research: Solid Earth},
volume = {116},
number = {B7},
pages = {B07304},
year = {2011},
doi = {10.1029/2011JB008200}
}

@article{Moreau2017,
author = {Moreau, L. and Stehly, L. and Boué, P. and Lu, Y. and Larose, E. and Campillo, M.},
title = {Improving ambient noise correlation functions with an {SVD}-based {W}iener filter},
journal = {Geophysical Journal International},
volume = {211},
number = {1},
pages = {418--426},
year = {2017},
doi = {10.1093/gji/ggx306}
}

@article{Mao2019,
author = {Mao, Shujuan and Campillo, Michel and van der Hilst, Robert D. and Brenguier, Florent and Stehly, Laurent and Hillers, Gregor},
title = {High temporal resolution monitoring of small variations in crustal strain by dense seismic arrays},
journal = {Geophysical Research Letters},
volume = {46},
number = {1},
pages = {128--137},
year = {2019},
doi = {10.1029/2018GL079944}
}

@article{Viens2020,
author = {Viens, Loïc and Van Houtte, Chris},
title = {Denoising ambient seismic field correlation functions with convolutional autoencoders},
journal = {Geophysical Journal International},
volume = {220},
number = {3},
pages = {1521--1535},
year = {2020},
doi = {10.1093/gji/ggz509}
}
9 changes: 0 additions & 9 deletions paper/survey.bib
Original file line number Diff line number Diff line change
Expand Up @@ -772,15 +772,6 @@ @misc{Kristjansdottir2019
note = {dv/v monitoring study (Geothermal wastewater reinjection (water-volume / pore-pressure increase))}
}

@article{Hadziioannou2011,
author = {Hadziioannou, C. and Larose, E. and Baig, A. and Roux, P. and Campillo, M.},
title = {Improving temporal resolution in ambient noise monitoring of seismic wave speed},
journal = {Journal of Geophysical Research},
year = {2011},
volume = {116},
doi = {10.1029/2011jb008200}
}

@article{Daskalakis2016,
author = {Daskalakis, E. and Evangelidis, C.P. and Garnier, J. and Melis, N.S. and Papanicolaou, G. and Tsogka, C.},
title = {Robust seismic velocity change estimation using ambient noise recordings},
Expand Down
38 changes: 21 additions & 17 deletions src/codameter/deviations.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
YEAR_D,
C,
Synth,
_boost_fonts,
_days,
_trailing_stack,
daily_ccfs,
Expand Down Expand Up @@ -134,10 +135,11 @@ def run_pipeline(ccfs, t, fs, cfg, *, eps_max=0.05, return_cc=False, prefiltered

**Sign convention (v0.4.0, physical dv/v)**: a velocity *increase* is
positive. All estimators return ``dv/v = -eps / (1 + eps)`` where
``eps`` is the stretch factor that maps the reference onto the current
waveform (a coda that must be dilated to match means the medium slowed
down). Before v0.4.0 this function returned ``eps`` itself, labeled
dv/v — anticorrelated with the physical convention.
``eps`` is the stretch factor that resamples the *current* waveform to
match the fixed reference (a current trace that must be dilated to
match means the medium slowed down). Before v0.4.0 this function
returned ``eps`` itself, labeled dv/v — anticorrelated with the
physical convention.

Returns ``(dvv, valid)``: the per-day series and a boolean mask of epochs the
pipeline actually produced (moving/inversion references have a warm-up gap;
Expand Down Expand Up @@ -410,9 +412,9 @@ def fig_deviation_ranking(rows=None):
xlabel="RMS error vs truth (dv/v, %, log)",
title="(a) Bias injected by each deviation",
)
ax[0].set_yticklabels(labels, fontsize=8.5)
ax[0].set_yticklabels(labels, fontsize=10.5)
ax[0].invert_yaxis()
ax[0].legend(fontsize=8.5, frameon=False, loc="lower right")
ax[0].legend(fontsize=10.5, frameon=False, loc="lower right")
drop = [r.drop_err * PCT for r in items]
ax[1].barh(y, drop, color=cols)
ax[1].axvline(0, color=C["truth"], lw=1)
Expand All @@ -424,13 +426,15 @@ def fig_deviation_ranking(rows=None):
title="(b) Distortion of the drop",
)
ax[1].invert_yaxis()
_boost_fonts(ax[0], ax[1], tick=10.5, label=12, title=13)
fig.tight_layout()
return fig


def fig_multiverse_full(mv=None):
"""The ultimate multiverse: every pipeline + the variance attribution."""
import matplotlib.pyplot as plt
from matplotlib.colors import Normalize

if mv is None:
mv = multiverse()
Expand All @@ -444,7 +448,7 @@ def fig_multiverse_full(mv=None):
# (a) fan of pipelines, coloured by RMS error with a colourblind-safe,
# perceptually uniform sequential map (dark = accurate, bright = biased).
order = np.argsort(-np.nan_to_num(rms))
norm = plt.Normalize(np.nanpercentile(rms, 5), np.nanpercentile(rms, 95))
norm = Normalize(np.nanpercentile(rms, 5), np.nanpercentile(rms, 95))
cmap = plt.cm.viridis_r
for i in order:
ax[0].plot(yrs, curves[i] * PCT, color=cmap(norm(rms[i])), lw=0.3, alpha=0.16)
Expand All @@ -463,28 +467,27 @@ def fig_multiverse_full(mv=None):
)
ax[0].plot(yrs, truth * PCT, color=C["truth"], lw=2.6, label="ground truth")
ax[0].axvline(2.0, color="0.6", ls="--", lw=1)
# Clip tightly to the truth scale; the cycle-skipping pipelines run off-axis
# (that is the point the colourbar flags them) but would otherwise swamp the
# Fixed, symmetric range: the cycle-skipping pipelines run off-axis (that is
# the point -- the colourbar flags them) but would otherwise swamp the
# signal and make the panel unreadable.
span = (np.nanmax(truth) - np.nanmin(truth)) * PCT
ax[0].set_ylim(
(np.nanmin(truth) * PCT - 0.35 * span, np.nanmax(truth) * PCT + 0.35 * span)
)
ax[0].set_ylim((-0.8, 0.8))
ax[0].set(
xlabel="time (years)",
ylabel="dv/v (%)",
title=f"(a) {mv['n_pipelines']} pipelines (colour = RMS error)",
)
leg = ax[0].legend(fontsize=8.5, loc="lower left", frameon=True)
leg = ax[0].legend(fontsize=10.5, loc="lower left", frameon=True)
leg.get_frame().set_facecolor("white")
leg.get_frame().set_alpha(0.9)
leg.get_frame().set_edgecolor("0.7")
fig.colorbar(
cbar = fig.colorbar(
plt.cm.ScalarMappable(norm=norm, cmap=cmap),
ax=ax[0],
fraction=0.046,
label="RMS vs truth",
)
cbar.set_label("RMS vs truth", fontsize=12)
cbar.ax.tick_params(labelsize=10.5)

# (b) first-order variance attribution.
axes = mv["axes"]
Expand All @@ -498,8 +501,9 @@ def fig_multiverse_full(mv=None):
ylabel="first-order variance fraction",
title="(b) Which choice controls the answer",
)
ax[1].set_xticklabels(axes, rotation=30, ha="right", fontsize=8.5)
ax[1].legend(fontsize=8.5, frameon=False)
ax[1].set_xticklabels(axes, rotation=30, ha="right", fontsize=10.5)
ax[1].legend(fontsize=10.5, frameon=False)
_boost_fonts(ax[0], ax[1], tick=10.5, label=12, title=13)
fig.tight_layout()
return fig

Expand Down
Loading