Seismic velocity changes as Bayesian stress & strain meters
In one sentencecodameter turns a noisy \(\delta v/v\) time series into depth-resolved stress with a full posterior, carrying uncertainty from measurement noise and material-property priors through to the interpreted stress rather than reporting a single number.
codameter is a research method and open-source package — the executable companion to Denolle (in prep, JGR Solid Earth). It reads a relative seismic-velocity-change (\(\delta v/v\)) time series plus the environmental forcings that drive it (temperature, precipitation, earthquakes, surface load) and returns:
depth-resolved stress estimates with propagated uncertainties,
water-table / saturation inversions (v0.2+),
coupling diagnostics that flag when linear superposition fails, and
anomaly flags for residual signal the physics does not explain.
This site is the narrative companion to the API docs: it shows the reasoning — the theory, the equations, and the life of each figure — not just the function signatures.
Overview
Two ideas motivate the whole project.
1 · Reproducibility, turned into uncertainty quantification. Turning cross-correlations into a \(\delta v/v\) series takes a long sequence of signal-processing choices — estimator, frequency band, coda window, reference, stacking, coherence gating — made ad hoc and seldom reported. Because reasonable analysts choose differently, the same data yields different \(\delta v/v\), and even different stated uncertainties: a reproducibility problem. Rather than crown one pipeline, codameter treats the choice as a nuisance parameter and marginalises it, so the spread across reasonable choices becomes a structured measurement covariance \(C_d\). The diversity of processing choices, usually a weakness, becomes the raw material for an honest, propagatable uncertainty.
2 · Making \(\delta v/v\) interpretable — which stress, and what rheology. A \(\delta v/v\) value is only useful once it is tied to a mechanism. codameter propagates \(C_d\) through depth-sensitivity kernels to a profile of shear-velocity change, then through a petrophysical model to stress, so one can ask which component of the stress explains the observations. Along the way it tests whether the rheology behaves linearly — the forcings superpose and a closed-form posterior holds — or nonlinearly, where drainage and damage couple and the inference must be sampled. The connection is the acoustoelastic bridge relation\(\Delta\sigma_{ij}(z,t)=\beta_{ij}(z)\,\delta V_S/V_S\), which links the stress and strain representations of \(\delta v/v\) and lets a velocity change be read as a named, depth-resolved stress or strain component.
How to read this site
There are two distinct halves, and they are written in two different voices.
① The uncertainty arc in four steps
The theory pages lay out the core contribution: a forward chain that carries uncertainty from the raw measurement to stress at depth and its attribution. Each step consumes the previous step’s covariance.
1 · Measurement — the marginal error in \(\delta v/v\). The error in the measurement itself, marginalised over processing choices (method, window, stacking, gating, and the reference, including the Brenguier (2014) all-to-all scheme). Two pages: first the marginal errors, and how they differ — the within-method floor, the methodological spread, temporal correlation, and reference choice; then turning them into a Bayesian measurement — a posterior \(\delta v/v(t)\) and the structured data covariance \(C_d\).
2 · Depth — \(\delta v/v \to \delta V_S(z)/V_S\). Invert the per-band \(C_d\) through sensitivity kernels for a profile of shear-velocity change \(\delta V_S/V_S(z)\) and, in partially saturated ground, a density change \(\delta\rho/\rho(z)\) that needs a petrophysical model to separate. See propagating to depth.
3 · Stress meter — \(\delta v/v\) as a stress meter. Push the depth posterior through layered acoustoelastic priors to stress and strain at depth, \(\Delta\sigma_{ij}(z,t)=\beta_{ij}(z)\,\delta V_S/V_S\), with a posterior. See stress meter; the companion inference UQ page holds the Bayesian machinery.
4 · Attribution — which forcing drives it. Decompose the stress into the physical terms that can each act in isolation (thermoelastic, poroelastic, damage, tectonic) and quantify each share with uncertainty. See process attribution; the forward physics and the module live in the companion coupling-framework project.
A dynamic, runnable walkthrough that follows the scientific arc from completely decoupled forcings — thermoelastic, hydrological, loading, damage, each treated as an independent stress source — to identifying coupled mechanisms where that independence breaks down. Every figure on these pages is generated live from the package.
The whole project runs along one axis: how strongly are the stress sources coupled? On the left, the forcings add linearly and a closed-form Gaussian posterior is exact. On the right, pore pressure, damage, and saturation feed back on each other, the posterior goes non-Gaussian, and we need the coupled MCMC machinery.
Code
flowchart LR A["<b>Decoupled regime</b><br/>thermoelastic ⟂ hydrological ⟂ damage<br/>Eq. 6 linear superposition"] B["<b>Coupling diagnostics</b><br/>drainage Péclet number<br/>β<sub>eff</sub>(ω)"] C["<b>Coupled regime</b><br/>state-dependent forward operator<br/>Eq. 19 · MCMC posterior"] A -- "Pe<sub>d</sub> safe" --> D["Linear-Gaussian<br/>posterior (exact)"] A -- "Pe<sub>d</sub> marginal" --> B B -- "escalate" --> C C --> E["Non-Gaussian<br/>posterior (sampled)"] D --> F["Stress at depth<br/>+ full uncertainty"] E --> F style A fill:#ede7f6,stroke:#5e35b1 style C fill:#fce4ec,stroke:#c62828 style F fill:#e8f5e9,stroke:#2e7d32
flowchart LR
A["<b>Decoupled regime</b><br/>thermoelastic ⟂ hydrological ⟂ damage<br/>Eq. 6 linear superposition"]
B["<b>Coupling diagnostics</b><br/>drainage Péclet number<br/>β<sub>eff</sub>(ω)"]
C["<b>Coupled regime</b><br/>state-dependent forward operator<br/>Eq. 19 · MCMC posterior"]
A -- "Pe<sub>d</sub> safe" --> D["Linear-Gaussian<br/>posterior (exact)"]
A -- "Pe<sub>d</sub> marginal" --> B
B -- "escalate" --> C
C --> E["Non-Gaussian<br/>posterior (sampled)"]
D --> F["Stress at depth<br/>+ full uncertainty"]
E --> F
style A fill:#ede7f6,stroke:#5e35b1
style C fill:#fce4ec,stroke:#c62828
style F fill:#e8f5e9,stroke:#2e7d32
Both regimes funnel into the same destination — stress at depth with a quantified posterior — which is exactly what makes the Bayesian framing the unifying idea of the whole package.
Status — v0.1
Phase
What it does
v0.1
0
Data ingestion + QC
✅
1
Site characterisation; depth–frequency table
✅
2
Coupling diagnostics — Tier 1 (poroelastic)
✅
3
Linear-superposition design matrix (Eq. 6)
✅
4
Linear inversion (WLS, closed-form Gaussian posterior)
✅
5
Anomaly detection (posterior predictive checks)
✅
6
β-bridge stress at depth (uncertainty propagated)
✅
4
Coupled inversion (MCMC)
v0.2
6
Water-table inversion
v0.2
2
Tiers 2–4 (damage, saturation, thermo-capillary)
v0.3
NoteReproducing this site locally
pixi installpixi run quarto render quarto/# open quarto/_site/index.html
Every code cell runs against the installed codameter package, so the figures regenerate from source.
---title: "codameter"subtitle: "Seismic velocity changes as **Bayesian** stress & strain meters"toc: false---::: {.keyidea}[In one sentence]{.k-title}`codameter` turns a noisy $\delta v/v$ time series into **depth-resolved stresswith a full posterior**, carrying uncertainty from measurement noise andmaterial-property priors through to the interpreted stress rather than reporting asingle number.:::`codameter` is a research method and open-source package — the executablecompanion to **Denolle (in prep, *JGR Solid Earth*)**. It reads a relativeseismic-velocity-change ($\delta v/v$) time series plus the environmental forcingsthat drive it (temperature, precipitation, earthquakes, surface load) and returns:- depth-resolved **stress** estimates with *propagated* uncertainties,- **water-table / saturation** inversions (v0.2+),- **coupling diagnostics** that flag when linear superposition fails, and- **anomaly flags** for residual signal the physics does not explain.This site is the *narrative* companion to the API docs: it shows the**reasoning** — the theory, the equations, and the life of each figure — not justthe function signatures.## OverviewTwo ideas motivate the whole project.**1 · Reproducibility, turned into uncertainty quantification.** Turningcross-correlations into a $\delta v/v$ series takes a long sequence ofsignal-processing choices — estimator, frequency band, coda window, reference,stacking, coherence gating — made *ad hoc* and seldom reported. Because reasonableanalysts choose differently, the same data yields different $\delta v/v$, and evendifferent *stated* uncertainties: a reproducibility problem. Rather than crown onepipeline, codameter treats the choice as a nuisance parameter and **marginalises**it, so the spread across reasonable choices becomes a structured measurementcovariance $C_d$. The diversity of processing choices, usually a weakness, becomesthe raw material for an honest, propagatable uncertainty.**2 · Making $\delta v/v$ interpretable — which stress, and what rheology.** A$\delta v/v$ value is only useful once it is tied to a mechanism. codameterpropagates $C_d$ through depth-sensitivity kernels to a profile of shear-velocitychange, then through a petrophysical model to **stress**, so one can ask *whichcomponent* of the stress explains the observations. Along the way it tests whetherthe rheology behaves **linearly** — the forcings superpose and a closed-formposterior holds — or **nonlinearly**, where drainage and damage couple and theinference must be sampled. The connection is the acoustoelastic **bridge relation**$\Delta\sigma_{ij}(z,t)=\beta_{ij}(z)\,\delta V_S/V_S$, which links the *stress* and*strain* representations of $\delta v/v$ and lets a velocity change be read as anamed, depth-resolved stress or strain component.---## How to read this siteThere are two distinct halves, and they are written in two different voices.### ① The uncertainty arc in four stepsThe theory pages lay out the **core** contribution: a forward chain that carriesuncertainty from the raw measurement to stress at depth and its attribution. Eachstep consumes the previous step's covariance.- **1 · Measurement — the marginal error in $\delta v/v$.** The error in the measurement *itself*, marginalised over processing choices (method, window, stacking, gating, and the **reference**, including the Brenguier (2014) all-to-all scheme). Two pages: first[the marginal errors, and how they differ](theory-measurement-uq.qmd) — the within-method floor, the methodological spread, temporal correlation, and reference choice; then[turning them into a Bayesian measurement](theory-bayesian-measurement.qmd) — a posterior $\delta v/v(t)$ and the structured data covariance $C_d$.- **2 · Depth — $\delta v/v \to \delta V_S(z)/V_S$.** Invert the per-band $C_d$ through sensitivity kernels for a profile of shear-velocity change $\delta V_S/V_S(z)$ and, in partially saturated ground, a density change $\delta\rho/\rho(z)$ that needs a petrophysical model to separate. See[propagating to depth](theory-processing-depth.qmd).- **3 · Stress meter — $\delta v/v$ as a stress meter.** Push the depth posterior through layered acoustoelastic priors to stress and strain at depth, $\Delta\sigma_{ij}(z,t)=\beta_{ij}(z)\,\delta V_S/V_S$, with a posterior. See[stress meter](uncertainty-3-stress.qmd); the companion[inference UQ](theory-uq.qmd) page holds the Bayesian machinery.- **4 · Attribution — which forcing drives it.** Decompose the stress into the physical terms that can each act in isolation (thermoelastic, poroelastic, damage, tectonic) and quantify each share with uncertainty. See[process attribution](uncertainty-4-attribution.qmd); the forward physics and the module live in the companion[coupling-framework project](https://github.com/mdenolle/dvv-coupling-framework).> 👉 Read them in order: **[1 · Measurement](theory-measurement-uq.qmd)** →> **[2 · Depth](theory-processing-depth.qmd)** →> **[3 · Stress meter](uncertainty-3-stress.qmd)** →> **[4 · Attribution](uncertainty-4-attribution.qmd)**.### ② The implementation tutorialA dynamic, runnable walkthrough that follows the scientific arc from**completely decoupled** forcings — thermoelastic, hydrological, loading,damage, each treated as an independent stress source — to **identifyingcoupled mechanisms** where that independence breaks down. Every figure onthese pages is generated live from the package.| Step | Page | Phase ||---|---|---|| 1 |[Data & site readiness](tutorial-01-data.qmd)|<span class="phase-badge">0–1</span>|| 2 |[Decoupled forward models](tutorial-02-forward.qmd)|<span class="phase-badge">forward</span>|| 3 |[Linear superposition & inversion](tutorial-03-inversion.qmd)|<span class="phase-badge">3–4</span>|| 4 |[When decoupling breaks: coupling diagnostics](tutorial-04-coupling.qmd)|<span class="phase-badge">2</span>|| 5 |[Interpretation: stress at depth](tutorial-05-interpretation.qmd)|<span class="phase-badge">6</span>|| 6 |[End-to-end Parkfield walkthrough](tutorial-06-endtoend.qmd)|<span class="phase-badge">0–6</span>|---## The scientific arc in one figureThe whole project runs along one axis: **how strongly are the stresssources coupled?** On the left, the forcings add linearly and a closed-formGaussian posterior is exact. On the right, pore pressure, damage, andsaturation feed back on each other, the posterior goes non-Gaussian, and weneed the coupled MCMC machinery.```{mermaid}flowchart LR A["<b>Decoupled regime</b><br/>thermoelastic ⟂ hydrological ⟂ damage<br/>Eq. 6 linear superposition"] B["<b>Coupling diagnostics</b><br/>drainage Péclet number<br/>β<sub>eff</sub>(ω)"] C["<b>Coupled regime</b><br/>state-dependent forward operator<br/>Eq. 19 · MCMC posterior"] A -- "Pe<sub>d</sub> safe" --> D["Linear-Gaussian<br/>posterior (exact)"] A -- "Pe<sub>d</sub> marginal" --> B B -- "escalate" --> C C --> E["Non-Gaussian<br/>posterior (sampled)"] D --> F["Stress at depth<br/>+ full uncertainty"] E --> F style A fill:#ede7f6,stroke:#5e35b1 style C fill:#fce4ec,stroke:#c62828 style F fill:#e8f5e9,stroke:#2e7d32```Both regimes funnel into the same destination — **stress at depth with aquantified posterior** — which is exactly what makes the Bayesian framing theunifying idea of the whole package.---## Status — v0.1| Phase | What it does | v0.1 ||---|---|---|| 0 | Data ingestion + QC |<span class="pill-ok">✅</span>|| 1 | Site characterisation; depth–frequency table |<span class="pill-ok">✅</span>|| 2 | Coupling diagnostics — Tier 1 (poroelastic) |<span class="pill-ok">✅</span>|| 3 | Linear-superposition design matrix (Eq. 6) |<span class="pill-ok">✅</span>|| 4 | Linear inversion (WLS, closed-form Gaussian posterior) |<span class="pill-ok">✅</span>|| 5 | Anomaly detection (posterior predictive checks) |<span class="pill-ok">✅</span>|| 6 | β-bridge stress at depth (uncertainty propagated) |<span class="pill-ok">✅</span>|| 4 | Coupled inversion (MCMC) |<span class="pill-todo">v0.2</span>|| 6 | Water-table inversion |<span class="pill-todo">v0.2</span>|| 2 | Tiers 2–4 (damage, saturation, thermo-capillary) |<span class="pill-todo">v0.3</span>|---::: {.callout-note collapse="true"}## Reproducing this site locally```bashpixi installpixi run quarto render quarto/# open quarto/_site/index.html```Every code cell runs against the installed `codameter` package, so thefigures regenerate from source.:::