bilby-laplace 0.2.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. bilby_laplace-0.2.0/.gitignore +51 -0
  2. bilby_laplace-0.2.0/CHANGELOG.md +112 -0
  3. bilby_laplace-0.2.0/CITATION.cff +21 -0
  4. bilby_laplace-0.2.0/LICENSE +21 -0
  5. bilby_laplace-0.2.0/MANIFEST.in +6 -0
  6. bilby_laplace-0.2.0/PKG-INFO +131 -0
  7. bilby_laplace-0.2.0/README.md +92 -0
  8. bilby_laplace-0.2.0/docs/background/theory.md +93 -0
  9. bilby_laplace-0.2.0/docs/changelog.md +1 -0
  10. bilby_laplace-0.2.0/docs/examples.md +51 -0
  11. bilby_laplace-0.2.0/docs/guide/covariance.md +154 -0
  12. bilby_laplace-0.2.0/docs/guide/how-it-works.md +71 -0
  13. bilby_laplace-0.2.0/docs/guide/resampling.md +76 -0
  14. bilby_laplace-0.2.0/docs/index.md +38 -0
  15. bilby_laplace-0.2.0/docs/installation.md +44 -0
  16. bilby_laplace-0.2.0/docs/javascripts/mathjax.js +19 -0
  17. bilby_laplace-0.2.0/docs/quickstart.md +63 -0
  18. bilby_laplace-0.2.0/docs/reference/api.md +45 -0
  19. bilby_laplace-0.2.0/pyproject.toml +77 -0
  20. bilby_laplace-0.2.0/setup.cfg +4 -0
  21. bilby_laplace-0.2.0/src/bilby_laplace/__init__.py +9 -0
  22. bilby_laplace-0.2.0/src/bilby_laplace/_version.py +24 -0
  23. bilby_laplace-0.2.0/src/bilby_laplace/comparison.py +980 -0
  24. bilby_laplace-0.2.0/src/bilby_laplace/gw_fisher.py +268 -0
  25. bilby_laplace-0.2.0/src/bilby_laplace/laplace.py +1379 -0
  26. bilby_laplace-0.2.0/src/bilby_laplace/sampler.py +5165 -0
  27. bilby_laplace-0.2.0/src/bilby_laplace.egg-info/PKG-INFO +131 -0
  28. bilby_laplace-0.2.0/src/bilby_laplace.egg-info/SOURCES.txt +59 -0
  29. bilby_laplace-0.2.0/src/bilby_laplace.egg-info/dependency_links.txt +1 -0
  30. bilby_laplace-0.2.0/src/bilby_laplace.egg-info/entry_points.txt +2 -0
  31. bilby_laplace-0.2.0/src/bilby_laplace.egg-info/requires.txt +15 -0
  32. bilby_laplace-0.2.0/src/bilby_laplace.egg-info/scm_file_list.json +71 -0
  33. bilby_laplace-0.2.0/src/bilby_laplace.egg-info/scm_version.json +8 -0
  34. bilby_laplace-0.2.0/src/bilby_laplace.egg-info/top_level.txt +1 -0
  35. bilby_laplace-0.2.0/tests/conftest.py +109 -0
  36. bilby_laplace-0.2.0/tests/test_checkpoint_resume.py +71 -0
  37. bilby_laplace-0.2.0/tests/test_comparison.py +265 -0
  38. bilby_laplace-0.2.0/tests/test_constraint_priors.py +177 -0
  39. bilby_laplace-0.2.0/tests/test_cov_scaling.py +69 -0
  40. bilby_laplace-0.2.0/tests/test_emcee.py +544 -0
  41. bilby_laplace-0.2.0/tests/test_evidence_use_ratio.py +124 -0
  42. bilby_laplace-0.2.0/tests/test_laplace.py +377 -0
  43. bilby_laplace-0.2.0/tests/test_map_periodic.py +68 -0
  44. bilby_laplace-0.2.0/tests/test_map_search.py +200 -0
  45. bilby_laplace-0.2.0/tests/test_map_spike_guard.py +247 -0
  46. bilby_laplace-0.2.0/tests/test_metrics.py +96 -0
  47. bilby_laplace-0.2.0/tests/test_mixture_proposal.py +307 -0
  48. bilby_laplace-0.2.0/tests/test_mode_mixture.py +1200 -0
  49. bilby_laplace-0.2.0/tests/test_nlikelihood.py +108 -0
  50. bilby_laplace-0.2.0/tests/test_periodic_proposal.py +103 -0
  51. bilby_laplace-0.2.0/tests/test_pool.py +83 -0
  52. bilby_laplace-0.2.0/tests/test_prior_floor.py +149 -0
  53. bilby_laplace-0.2.0/tests/test_prior_precision.py +146 -0
  54. bilby_laplace-0.2.0/tests/test_proposal_covariance.py +139 -0
  55. bilby_laplace-0.2.0/tests/test_proposals.py +178 -0
  56. bilby_laplace-0.2.0/tests/test_rejection_sampling.py +88 -0
  57. bilby_laplace-0.2.0/tests/test_resolve_sampling_cov.py +95 -0
  58. bilby_laplace-0.2.0/tests/test_smc_multimode.py +144 -0
  59. bilby_laplace-0.2.0/tests/test_smc_pool.py +229 -0
  60. bilby_laplace-0.2.0/tests/test_validate_covariance.py +153 -0
  61. bilby_laplace-0.2.0/tests/test_waveform_fisher.py +408 -0
@@ -0,0 +1,51 @@
1
+ # setuptools-scm auto-generated; do not commit
2
+ src/bilby_laplace/_version.py
3
+
4
+ # Build / packaging
5
+ dist/
6
+ build/
7
+ *.egg-info/
8
+ **/__pycache__/
9
+ *.py[cod]
10
+ *.so
11
+
12
+ # Common runtime outputs
13
+ outdir/
14
+ *.png
15
+ *.npz
16
+
17
+ # macOS
18
+ .DS_Store
19
+
20
+ # Vim
21
+ *.swp
22
+ *.swo
23
+
24
+ # Examples
25
+ *outdir*
26
+
27
+ # Paper working directory (studies, runs, figures) - kept out of the package repo
28
+ paper/
29
+
30
+ # MkDocs build output
31
+ site/
32
+
33
+ # Test / coverage artifacts
34
+ .coverage
35
+ .coverage.*
36
+ coverage.xml
37
+ htmlcov/
38
+ .pytest_cache/
39
+
40
+ # Claude Code guidance - local only, kept out of git history
41
+ CLAUDE.md
42
+ .claude/
43
+
44
+ # Run logs from `make <sampler> > x.log`
45
+ examples/**/*.log
46
+
47
+ # Editor settings
48
+ .vscode/
49
+
50
+ # Example outputs: `make compare` writes a results README and figures here
51
+ examples/*/README.md
@@ -0,0 +1,112 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
6
+ Versions correspond to git tags; version numbers follow
7
+ [Semantic Versioning](https://semver.org/).
8
+
9
+ ---
10
+
11
+ ## [Unreleased]
12
+
13
+ ## [0.2.0] — 2026-11-11
14
+
15
+ ### Added
16
+
17
+ - Resampling methods: `resample="smc"` (via [aspire](https://github.com/bilby-dev/aspire)),
18
+ `"inprior"` (draw from the proposal within the prior support, no reweighting) and `"emcee"`.
19
+ - Multimodal proposals: `n_modes`, with `mode_searches` (`"hypercube"`, `"symmetric"`,
20
+ `"symmetric-polish"`, `"multistart"`), `mode_search_nsamples`, `mode_search_subspace`,
21
+ `mode_separation_sigma`, `mode_symmetries`, `mode_symmetry_tol`, `mode_symmetry_polish_max`,
22
+ `mode_multistart_nstarts` and `mode_weights`. Candidates from all searches are pooled and ranked
23
+ by log-posterior before selection. The mixture is recorded in `meta_data["mode_mixture"]`,
24
+ including which search proposed each mode.
25
+ - `proposal_covariance`: `"diagonal"` (independent truncated normals) or `"full"` (the correlated
26
+ Gaussian restricted to the prior box). Recorded in `meta_data["proposal_covariance"]`.
27
+ - `fisher_method="waveform"`: the waveform Fisher matrix for gravitational-wave likelihoods,
28
+ including phase/time/distance-marginalised likelihoods (via the Schur complement, with
29
+ `marginalized_reference` on `LaplacePosteriorEstimator`) and detector-based sky frames.
30
+ - `map_restarts` (default 4): independent `differential_evolution` runs in the MAP search, keeping
31
+ the best.
32
+ - `map_spike_guard` (default True) and `map_spike_delta`: reject MAP candidates that sit on a
33
+ needle spike of the log-posterior.
34
+ - `map_vectorized` (default True): evaluate the `differential_evolution` population as one batch,
35
+ so the MAP search uses `npool`.
36
+ - `smc_prior_flow`, `smc_prior_fraction`, `smc_progress` and `smc_plot_every` for SMC runs.
37
+ - `sampling_cov`: supply a precomputed covariance.
38
+ - `cov_scaling` accepts a per-parameter dict.
39
+ - `jacobian_cap_scale`, `hessian_kwargs`, `use_unit_cube` and `max_iterations` options.
40
+ - Validation of the Hessian-derived covariance along its principal axes; directions wider than
41
+ the Gaussian predicts are inflated.
42
+ - Checkpoint and resume for the batched resampling methods and SMC.
43
+ - Parallel likelihood evaluation through `npool` / `pool`.
44
+ - `bilby_laplace.comparison`: JSD/EMD comparison of results against a reference, used by the
45
+ examples.
46
+ - Examples: gaussian, rosenbrock, BBH_HLV, BNS_3G and AntiGlitch.
47
+
48
+ ### Changed
49
+
50
+ - `resample="inprior"` uses `proposal_covariance="full"` by default; every other method uses
51
+ `"diagonal"`.
52
+ - The multiprocessing pool is created before the MAP search.
53
+ - A secondary mode with a higher log-posterior than the primary MAP logs a warning.
54
+ - `fail_on_error` defaults to True.
55
+ - Unit-cube Hessian defaults: `initial_step=0.001`, `step_factor=2`, `maxiter=10`; the unit-cube
56
+ precision is floored at the prior precision.
57
+ - Renamed to reflect that the estimated matrix is the posterior precision, not the Fisher
58
+ information: `matrix.py` → `laplace.py`, `FisherMatrixPosteriorEstimator` →
59
+ `LaplacePosteriorEstimator`, `calculate_FIM` → `calculate_posterior_precision`, `calculate_iFIM`
60
+ → `calculate_posterior_covariance`.
61
+ - The `sample_array`/`sample_dataframe` sentinel for the expansion point is `sample="MAP"` (was
62
+ `"maxL"`); other strings raise `ValueError`.
63
+
64
+ ### Fixed
65
+
66
+ - `Constraint` priors are applied in the MAP search, Hessian, mode search and Laplace evidence
67
+ (`log_prior` delegates to `PriorDict.ln_prob`; MAP starts use `sample_subset_constrained`).
68
+ - `log_evidence_laplace` includes bilby's constraint normalisation factor.
69
+ - `prior_parameters` substitution happens before the prior-support test in the SMC and in-prior
70
+ draws.
71
+ - Latin hypercube starts that violate a constraint are dropped from the mode search.
72
+ - The hypercube mode search keeps the best polish of a region, not the first.
73
+ - An exact symmetry mirror is not rejected as a duplicate of its own source by the separation gate.
74
+ - The waveform Fisher uses the injection as the marginalised-parameter reference only when
75
+ `use_injection_for_map=True`.
76
+ - Local MAP polishes wrap periodic parameters instead of treating their bounds as walls.
77
+ - `resample=None` reports the fraction of draws outside the prior support.
78
+ - The sampling seed reaches every stage, including SMC.
79
+
80
+ ### Removed
81
+
82
+ - The manual finite-difference Hessian fallback and `fd_eps`; `scipy>=1.15` is required.
83
+ - `get_maximum_likelihood_sample()`, an alias of `get_MAP_sample()`.
84
+ - The bounds arguments of `_pool_log_likelihood`; support is tested once per batch.
85
+ - The GW150914 example (needs a data download).
86
+
87
+ ---
88
+
89
+ ## [0.1.0] — 2026-03-02
90
+
91
+ Initial release.
92
+
93
+ ### Added
94
+
95
+ - `Fisher` sampler class — a Bilby plugin that registers as `bilby.laplace` /
96
+ `laplace` via the `bilby.samplers` entry-point group.
97
+ - `FisherMatrixPosteriorEstimator` — computes the MAP estimate and inverse Fisher
98
+ Information Matrix (iFIM) covariance for a given likelihood and prior.
99
+ - FIM calculation using `scipy.differentiate.hessian` (scipy ≥ 1.15) with automatic
100
+ finite-difference fallback for older scipy.
101
+ - Rejection sampling and importance sampling resampling modes.
102
+ - Batched sampling loop with a `tqdm` progress bar reporting per-batch efficiency.
103
+ - Optional corner diagnostic plot (`plot_diagnostic=True`) comparing the Gaussian
104
+ proposal with the resampled posterior.
105
+ - `result.meta_data["run_statistics"]` populated with sampling efficiency, likelihood
106
+ evaluation count, and wall-clock time.
107
+ - `examples/gaussian_example.py` — minimal runnable demo on a 2-D Gaussian likelihood.
108
+ - Version managed by `setuptools-scm` from git tags.
109
+
110
+ [Unreleased]: https://github.com/GregoryAshton/bilby-laplace/compare/v0.2.0...HEAD
111
+ [0.2.0]: https://github.com/GregoryAshton/bilby-laplace/compare/v0.1.0...v0.2.0
112
+ [0.1.0]: https://github.com/GregoryAshton/bilby-laplace/releases/tag/v0.1.0
@@ -0,0 +1,21 @@
1
+ cff-version: 1.2.0
2
+ message: "If you use this software, please cite it as below."
3
+ title: "bilby-laplace"
4
+ abstract: >-
5
+ A Bilby sampler plugin that builds a Laplace-approximation mixture (MAP
6
+ search, secondary-mode search, curvature at each mode) and uses it to seed
7
+ or correct stochastic sampling.
8
+ type: software
9
+ authors:
10
+ - family-names: Ashton
11
+ given-names: Gregory
12
+ license: MIT
13
+ repository-code: "https://github.com/GregoryAshton/bilby-laplace"
14
+ url: "https://gregoryashton.github.io/bilby-laplace/"
15
+ keywords:
16
+ - bayesian inference
17
+ - laplace approximation
18
+ - bilby
19
+ - gravitational waves
20
+ version: 0.2.0
21
+ date-released: 2026-11-11
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Gregory Ashton
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,6 @@
1
+ # setuptools-scm includes every tracked file in the sdist; keep it to the
2
+ # package, tests and docs. The example scripts stay in the repository and the
3
+ # Zenodo archive.
4
+ prune examples
5
+ prune .github
6
+ exclude .pre-commit-config.yaml .flake8 mkdocs.yml
@@ -0,0 +1,131 @@
1
+ Metadata-Version: 2.4
2
+ Name: bilby-laplace
3
+ Version: 0.2.0
4
+ Summary: Bilby sampler plugin: Laplace approximation with rejection/importance resampling
5
+ Author: Gregory Ashton
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/GregoryAshton/bilby-laplace
8
+ Project-URL: Documentation, https://gregoryashton.github.io/bilby-laplace/
9
+ Project-URL: Source, https://github.com/GregoryAshton/bilby-laplace
10
+ Project-URL: Issues, https://github.com/GregoryAshton/bilby-laplace/issues
11
+ Project-URL: Changelog, https://github.com/GregoryAshton/bilby-laplace/blob/main/CHANGELOG.md
12
+ Keywords: bayesian inference,laplace approximation,bilby,gravitational waves
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Intended Audience :: Science/Research
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Topic :: Scientific/Engineering :: Astronomy
21
+ Classifier: Topic :: Scientific/Engineering :: Physics
22
+ Requires-Python: >=3.10
23
+ Description-Content-Type: text/markdown
24
+ License-File: LICENSE
25
+ Requires-Dist: bilby>=2.7
26
+ Requires-Dist: numpy
27
+ Requires-Dist: scipy>=1.15
28
+ Requires-Dist: pandas
29
+ Requires-Dist: tqdm
30
+ Provides-Extra: docs
31
+ Requires-Dist: mkdocs<2; extra == "docs"
32
+ Requires-Dist: mkdocs-material; extra == "docs"
33
+ Requires-Dist: mkdocstrings[python]; extra == "docs"
34
+ Requires-Dist: pymdown-extensions; extra == "docs"
35
+ Provides-Extra: test
36
+ Requires-Dist: pytest; extra == "test"
37
+ Requires-Dist: pytest-cov; extra == "test"
38
+ Dynamic: license-file
39
+
40
+ # bilby-laplace
41
+
42
+ A [Bilby](https://bilby-dev.github.io/bilby/) sampler plugin that estimates posteriors
43
+ via the **Laplace approximation** — a Gaussian fitted at the maximum a posteriori (MAP)
44
+ point using the Hessian of the log-posterior — followed by optional resampling to
45
+ correct for non-Gaussianity.
46
+
47
+ The method is fast, scales well to moderate dimensions, and produces asymptotically
48
+ exact posterior samples when the true posterior is close to Gaussian. It is
49
+ useful as a cheap cross-check against nested sampling results.
50
+
51
+ > **Documentation:** full guides, the configuration/API reference, and background on
52
+ > the method are at **<https://gregoryashton.github.io/bilby-laplace/>**.
53
+
54
+ Originally derived from [bilby PR #933](https://github.com/bilby-dev/bilby/pull/933).
55
+
56
+ ## Installation
57
+
58
+ ```bash
59
+ pip install bilby-laplace
60
+ ```
61
+
62
+ Or from source:
63
+
64
+ ```bash
65
+ git clone https://github.com/GregoryAshton/bilby-laplace
66
+ cd bilby-laplace
67
+ pip install -e .
68
+ ```
69
+
70
+ Bilby discovers the sampler automatically via its plugin entry-point system — no
71
+ further configuration is needed.
72
+
73
+ ## Quick start
74
+
75
+ ```python
76
+ import bilby
77
+
78
+ result = bilby.run_sampler(
79
+ likelihood=likelihood,
80
+ priors=priors,
81
+ sampler="laplace",
82
+ outdir="outdir",
83
+ label="my_run",
84
+ )
85
+
86
+ result.plot_corner()
87
+ print(result.posterior)
88
+ ```
89
+
90
+ ## Features
91
+
92
+ - Several resampling strategies to correct for non-Gaussianity: `rejection`,
93
+ `importance`, `inprior`, `smc` (via [aspire](https://github.com/bilby-dev/aspire)),
94
+ or none.
95
+ - Two covariance routes: the numerical Hessian (`fisher_method="hessian"`, any
96
+ likelihood) or the genuine waveform Fisher matrix (`fisher_method="waveform"`, for
97
+ gravitational-wave likelihoods).
98
+ - Supply a precomputed covariance via `sampling_cov` (e.g. from gwfast / GWFish).
99
+ - Multimodal posteriors via SMC with `n_modes > 1`.
100
+ - Laplace log-evidence always available; rejection and SMC add independent estimates.
101
+
102
+ See the [documentation](https://gregoryashton.github.io/bilby-laplace/) for the full list
103
+ of options and guidance on choosing between them.
104
+
105
+ ## Examples
106
+
107
+ Runnable examples are in [`examples/`](https://github.com/GregoryAshton/bilby-laplace/tree/main/examples) (gaussian, rosenbrock, BBH, BNS).
108
+ Each has a `Makefile`:
109
+
110
+ ```bash
111
+ cd examples/gaussian
112
+ make laplace
113
+ make compare
114
+ ```
115
+
116
+ ## Citing
117
+
118
+ If you use `bilby-laplace`, please cite the software release; citation metadata
119
+ is in [`CITATION.cff`](https://github.com/GregoryAshton/bilby-laplace/blob/main/CITATION.cff) (GitHub's "Cite this repository" button
120
+ reads it).
121
+
122
+ ## License
123
+
124
+ MIT; see [`LICENSE`](https://github.com/GregoryAshton/bilby-laplace/blob/main/LICENSE).
125
+
126
+ ## Documentation development
127
+
128
+ ```bash
129
+ pip install -e ".[docs]"
130
+ mkdocs serve
131
+ ```
@@ -0,0 +1,92 @@
1
+ # bilby-laplace
2
+
3
+ A [Bilby](https://bilby-dev.github.io/bilby/) sampler plugin that estimates posteriors
4
+ via the **Laplace approximation** — a Gaussian fitted at the maximum a posteriori (MAP)
5
+ point using the Hessian of the log-posterior — followed by optional resampling to
6
+ correct for non-Gaussianity.
7
+
8
+ The method is fast, scales well to moderate dimensions, and produces asymptotically
9
+ exact posterior samples when the true posterior is close to Gaussian. It is
10
+ useful as a cheap cross-check against nested sampling results.
11
+
12
+ > **Documentation:** full guides, the configuration/API reference, and background on
13
+ > the method are at **<https://gregoryashton.github.io/bilby-laplace/>**.
14
+
15
+ Originally derived from [bilby PR #933](https://github.com/bilby-dev/bilby/pull/933).
16
+
17
+ ## Installation
18
+
19
+ ```bash
20
+ pip install bilby-laplace
21
+ ```
22
+
23
+ Or from source:
24
+
25
+ ```bash
26
+ git clone https://github.com/GregoryAshton/bilby-laplace
27
+ cd bilby-laplace
28
+ pip install -e .
29
+ ```
30
+
31
+ Bilby discovers the sampler automatically via its plugin entry-point system — no
32
+ further configuration is needed.
33
+
34
+ ## Quick start
35
+
36
+ ```python
37
+ import bilby
38
+
39
+ result = bilby.run_sampler(
40
+ likelihood=likelihood,
41
+ priors=priors,
42
+ sampler="laplace",
43
+ outdir="outdir",
44
+ label="my_run",
45
+ )
46
+
47
+ result.plot_corner()
48
+ print(result.posterior)
49
+ ```
50
+
51
+ ## Features
52
+
53
+ - Several resampling strategies to correct for non-Gaussianity: `rejection`,
54
+ `importance`, `inprior`, `smc` (via [aspire](https://github.com/bilby-dev/aspire)),
55
+ or none.
56
+ - Two covariance routes: the numerical Hessian (`fisher_method="hessian"`, any
57
+ likelihood) or the genuine waveform Fisher matrix (`fisher_method="waveform"`, for
58
+ gravitational-wave likelihoods).
59
+ - Supply a precomputed covariance via `sampling_cov` (e.g. from gwfast / GWFish).
60
+ - Multimodal posteriors via SMC with `n_modes > 1`.
61
+ - Laplace log-evidence always available; rejection and SMC add independent estimates.
62
+
63
+ See the [documentation](https://gregoryashton.github.io/bilby-laplace/) for the full list
64
+ of options and guidance on choosing between them.
65
+
66
+ ## Examples
67
+
68
+ Runnable examples are in [`examples/`](https://github.com/GregoryAshton/bilby-laplace/tree/main/examples) (gaussian, rosenbrock, BBH, BNS).
69
+ Each has a `Makefile`:
70
+
71
+ ```bash
72
+ cd examples/gaussian
73
+ make laplace
74
+ make compare
75
+ ```
76
+
77
+ ## Citing
78
+
79
+ If you use `bilby-laplace`, please cite the software release; citation metadata
80
+ is in [`CITATION.cff`](https://github.com/GregoryAshton/bilby-laplace/blob/main/CITATION.cff) (GitHub's "Cite this repository" button
81
+ reads it).
82
+
83
+ ## License
84
+
85
+ MIT; see [`LICENSE`](https://github.com/GregoryAshton/bilby-laplace/blob/main/LICENSE).
86
+
87
+ ## Documentation development
88
+
89
+ ```bash
90
+ pip install -e ".[docs]"
91
+ mkdocs serve
92
+ ```
@@ -0,0 +1,93 @@
1
+ # Fisher, Hessian & precision
2
+
3
+ A common point of confusion: the matrix the default route computes is **not** the
4
+ Fisher information matrix, even though such code is often loosely called "the Fisher
5
+ matrix". This page makes the distinction precise, because it explains both the
6
+ naming in the code and why the `"waveform"` route can give a better-behaved result.
7
+
8
+ ## The decomposition
9
+
10
+ For a Gaussian likelihood with mean \( \mu(\theta) \), data \( d \), and noise
11
+ covariance \( C \), write the residual \( r = d - \mu(\theta) \). The second
12
+ derivative of the log-likelihood splits cleanly:
13
+
14
+ \[
15
+ -\partial_i \partial_j \log L
16
+ = \underbrace{(\partial_i \mu)^{\mathsf T} C^{-1} (\partial_j \mu)}_{\textstyle F_{ij}\ \text{(Fisher)}}
17
+ \;-\; \underbrace{r^{\mathsf T} C^{-1} (\partial_i \partial_j \mu)}_{\textstyle \text{residual}\times\text{curvature}}
18
+ \]
19
+
20
+ For gravitational waves the noise-weighted inner product
21
+ \( (a\mid b) = 4\,\mathrm{Re}\int a^* b / S_n\, \mathrm{d}f \) **is** \( a^{\mathsf T} C^{-1} b \),
22
+ so with \( \mu \to h(\theta) \):
23
+
24
+ \[
25
+ -\partial_i \partial_j \log L = (\partial_i h \mid \partial_j h) - (r \mid \partial_i \partial_j h).
26
+ \]
27
+
28
+ Three distinct objects appear:
29
+
30
+ | Object | Definition | Properties |
31
+ |---|---|---|
32
+ | **Fisher information** \( F \) | \( \mathbb{E}[-\partial^2 \log L] = (\partial_i h\mid\partial_j h) \) | expectation; model + noise only; positive semi-definite; data-independent |
33
+ | **Observed information** \( J \) | \( -\partial^2 \log L \) at a point | single realisation; \( = F - (r\mid\partial^2 h) \); can be indefinite |
34
+ | **Posterior precision** | \( -\partial^2 \log(L\pi) = J + (-\partial^2\log\pi) \) | what the Laplace approximation actually uses |
35
+
36
+ ## Why the routes differ
37
+
38
+ - **`fisher_method="hessian"`** numerically estimates the *posterior precision* —
39
+ the third row, including the prior. It is the observed information plus the prior
40
+ curvature.
41
+ - **`fisher_method="waveform"`** computes \( F \) directly — the first term only —
42
+ plus a diagonal prior precision.
43
+
44
+ The two agree **in expectation**: at the true parameters the residual is pure noise,
45
+ \( \mathbb{E}[(r\mid X)] = 0 \), so \( \mathbb{E}[-\partial^2\log L] = F \). This is
46
+ the Fisher information identity, and the basis of the Cramér–Rao bound.
47
+
48
+ For a **single** dataset they differ by the residual–curvature term, which is
49
+ zero-mean but has nonzero variance, is **not sign-definite**, and shrinks roughly
50
+ like \( \mathcal{O}(1/\mathrm{SNR}) \). Dropping it is the *linear-signal
51
+ approximation*. Evaluating at the MAP does not remove it: the gradient vanishes
52
+ there, but the residual still has a component off the signal manifold that projects
53
+ onto \( \partial_i\partial_j h \).
54
+
55
+ ## Consequences in practice
56
+
57
+ 1. The Hessian route computes the **noisy** object: even with perfect
58
+ differentiation, \( J \) includes the indefinite residual–curvature term, which is
59
+ why the inversion needs eigenvalue flooring. The waveform route computes the clean
60
+ PSD \( F \).
61
+ 2. The Hessian route differentiates a **scalar** to get a *second* derivative — the
62
+ accuracy ceiling is roughly \( \sqrt{\varepsilon_f} \). The Fisher needs only
63
+ *first* derivatives of \( h \), then a Gram product — better conditioned and
64
+ positive semi-definite for free.
65
+
66
+ A subtlety worth stating: for a *specific* dataset, the inverse observed information
67
+ \( J^{-1} \) is actually the better local Gaussian fit to the realised posterior (the
68
+ Laplace approximation *is* a Taylor expansion of the realised log-posterior). Tools
69
+ like [gwfast](https://github.com/CosmoStatGW/gwfast) and
70
+ [GWFish](https://github.com/janosch314/GWFish) compute \( F \) because they are doing
71
+ *forecasting* (expected errors, Cramér–Rao). Here we only need a **proposal**
72
+ covariance — and \( F \) is a clean, PSD, well-conditioned surrogate that equals
73
+ \( J \) in expectation, so it is usually the better engineering choice when available.
74
+
75
+ ## Conditioning
76
+
77
+ GW Fisher matrices are notoriously ill-conditioned — condition numbers of
78
+ \( 10^{10} \)–\( 10^{20} \) from strong degeneracies (distance–inclination, the
79
+ masses, sky position). Inverting in double precision loses about
80
+ \( \log_{10}(\kappa) \) digits, so a poorly-conditioned matrix can be inverted to
81
+ *zero* correct digits.
82
+
83
+ Two independent sources contribute:
84
+
85
+ - **Scale-driven** conditioning (parameters span many orders of magnitude). Removed
86
+ by **diagonal preconditioning** — rescaling by \( \sqrt{\mathrm{diag}} \) before
87
+ inversion. This is the shared trick used by both GWFish and gwfast.
88
+ - **Correlation-driven** conditioning (genuine parameter degeneracies). Preconditioning
89
+ cannot help here; only a better parameterisation or the Fisher form does.
90
+
91
+ The unit-cube Hessian path already normalises scales via the prior CDF transform, so
92
+ its residual conditioning is correlation-driven; the parameter-space and
93
+ waveform-Fisher paths benefit much more from preconditioning.
@@ -0,0 +1 @@
1
+ --8<-- "CHANGELOG.md"
@@ -0,0 +1,51 @@
1
+ # Examples
2
+
3
+ Runnable example scripts live in the [`examples/`](https://github.com/GregoryAshton/bilby-laplace/tree/main/examples)
4
+ directory. Each script supports multiple samplers and a `--compare` mode that prints
5
+ a summary table and a corner plot overlaying the methods.
6
+
7
+ Each example directory has a `Makefile`; run targets from within it:
8
+
9
+ ```bash
10
+ cd examples/gaussian
11
+ make laplace # raw Laplace (no resampling)
12
+ make rejection # rejection resampling
13
+ make rejection-user # rejection with a user-supplied sampling_cov
14
+ make smc # SMC resampling
15
+ make dynesty # nested-sampling reference
16
+ make compare # load all results, print evidence table, plot
17
+ ```
18
+
19
+ ## Available examples
20
+
21
+ | Example | What it demonstrates |
22
+ |---|---|
23
+ | `examples/gaussian` | 2-D correlated Gaussian — the Laplace approximation is exact here, so it is the cleanest correctness check. Includes a `rejection-user` variant that feeds the known covariance via `sampling_cov`. |
24
+ | `examples/rosenbrock` | A strongly non-Gaussian, curved target — a stress test where `resample="smc"` matters. |
25
+ | `examples/BBH_HLV` | A simulated binary-black-hole injection in an H–L–V network (no data download needed). A realistic high-dimensional GW problem. |
26
+ | `examples/BNS_3G` | A binary-neutron-star injection in a 3rd-generation network. |
27
+ | `examples/AntiGlitch` | A simulated anti-glitch in Gaussian noise. |
28
+
29
+ ## A minimal script
30
+
31
+ ```python
32
+ import bilby
33
+
34
+ likelihood = ... # any bilby Likelihood
35
+ priors = ... # a bilby PriorDict
36
+
37
+ result = bilby.run_sampler(
38
+ likelihood=likelihood,
39
+ priors=priors,
40
+ sampler="laplace",
41
+ resample="rejection",
42
+ target_nsamples=5000,
43
+ plot_diagnostic=True,
44
+ outdir="outdir",
45
+ label="example",
46
+ )
47
+ result.plot_corner()
48
+ ```
49
+
50
+ See the [gaussian example](https://github.com/GregoryAshton/bilby-laplace/blob/main/examples/gaussian/run.py)
51
+ for a complete, self-contained script including the likelihood definition.