Real gravitational anomalies are rarely points — ore bodies, voids, aquifers, anything extended. The same machinery handles them: replace the point-mass forward model with one that integrates the potential over a continuous profile. Here, a Gaussian density with three parameters — center \(\mu\), width \(\sigma\) (the profile’s own width here, not the observation noise from earlier pages), and peak amplitude \(A\) — and the identical particle filter on top.
The density demo. Left: true vs inferred density profile. Center: the clock rates both produce. Right: convergence of all three parameters.
A point mass vs Gaussian profiles of equal total mass at two widths. Spreading the mass flattens and broadens the dip in tick rates.
A new degeneracy
Look back at the demo figure’s left panel: the inferred profile and the true one disagree visibly — yet the center panel shows their clock rates matching almost perfectly. The center \(\mu\) localizes well, but \(\sigma\) and \(A\) trade off along a ridge: a wider, weaker profile and a narrower, denser one can produce nearly identical potentials at a handful of clock positions. This is the same inverse-problem pattern as the mass–distance degeneracy: different physical profiles map to nearly identical clock-rate data. The library’s covariance-shaped jitter mode exists for exactly this kind of correlated posterior — it lets the particle cloud slide along the ridge instead of scattering off it (the demo here uses the annealed default; covariance jitter is the specialist tool when the ridge is the whole story).
NoteWhere this could go
The repo’s someday-maybe list sketches the next steps: a special-relativity velocity term so SR and GR compete the way they do for real GPS satellites, an MCMC rejuvenation step to make the filter exactly posterior-preserving, and an in-browser interactive version — the inference engine is pure numpy/scipy, which Pyodide already supports. First, though, one last question: could you feel gravity?