binference 0.1.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.
- binference-0.1.0/.gitignore +109 -0
- binference-0.1.0/CHANGELOG.md +342 -0
- binference-0.1.0/CITATION.cff +53 -0
- binference-0.1.0/LICENSE +21 -0
- binference-0.1.0/PKG-INFO +130 -0
- binference-0.1.0/README.md +69 -0
- binference-0.1.0/notes/review/README.md +39 -0
- binference-0.1.0/notes/review/audit/README.md +38 -0
- binference-0.1.0/pyproject.toml +115 -0
- binference-0.1.0/src/binference/__init__.py +85 -0
- binference-0.1.0/src/binference/_kernels.py +252 -0
- binference-0.1.0/src/binference/_quadrature.py +202 -0
- binference-0.1.0/src/binference/_simplex.py +54 -0
- binference-0.1.0/src/binference/_utils.py +139 -0
- binference-0.1.0/src/binference/_version.py +1 -0
- binference-0.1.0/src/binference/basis.py +314 -0
- binference-0.1.0/src/binference/bins.py +645 -0
- binference-0.1.0/src/binference/density.py +323 -0
- binference-0.1.0/src/binference/diagnostics.py +400 -0
- binference-0.1.0/src/binference/estimator.py +197 -0
- binference-0.1.0/src/binference/inference.py +368 -0
- binference-0.1.0/src/binference/io.py +309 -0
- binference-0.1.0/src/binference/likelihoods.py +1684 -0
- binference-0.1.0/src/binference/measure.py +246 -0
- binference-0.1.0/src/binference/model.py +833 -0
- binference-0.1.0/src/binference/plotting.py +538 -0
- binference-0.1.0/src/binference/priors/__init__.py +47 -0
- binference-0.1.0/src/binference/priors/base.py +248 -0
- binference-0.1.0/src/binference/priors/dirichlet.py +640 -0
- binference-0.1.0/src/binference/priors/hyper.py +240 -0
- binference-0.1.0/src/binference/priors/logistic.py +676 -0
- binference-0.1.0/src/binference/priors/rates.py +139 -0
- binference-0.1.0/src/binference/response.py +539 -0
- binference-0.1.0/src/binference/results.py +2271 -0
- binference-0.1.0/src/binference/samplers/__init__.py +19 -0
- binference-0.1.0/src/binference/samplers/_curvature.py +67 -0
- binference-0.1.0/src/binference/samplers/_nuts_core.py +284 -0
- binference-0.1.0/src/binference/samplers/base.py +118 -0
- binference-0.1.0/src/binference/samplers/bootstrap.py +136 -0
- binference-0.1.0/src/binference/samplers/gibbs.py +287 -0
- binference-0.1.0/src/binference/samplers/laplace.py +200 -0
- binference-0.1.0/src/binference/samplers/nuts.py +681 -0
- binference-0.1.0/src/binference/samplers/optimize.py +488 -0
- binference-0.1.0/src/binference/samplers/vb.py +118 -0
- binference-0.1.0/src/binference/selection.py +621 -0
- binference-0.1.0/src/binference/simulate.py +720 -0
- binference-0.1.0/src/binference/validation.py +477 -0
- binference-0.1.0/src/binference/warnings.py +48 -0
- binference-0.1.0/tests/__init__.py +0 -0
- binference-0.1.0/tests/conftest.py +84 -0
- binference-0.1.0/tests/data/matrix_reference.json +566 -0
- binference-0.1.0/tests/test_api.py +108 -0
- binference-0.1.0/tests/test_api_docs.py +59 -0
- binference-0.1.0/tests/test_auto.py +210 -0
- binference-0.1.0/tests/test_basis.py +271 -0
- binference-0.1.0/tests/test_benchmark_matrix.py +16 -0
- binference-0.1.0/tests/test_best_loo.py +140 -0
- binference-0.1.0/tests/test_binning_bias.py +78 -0
- binference-0.1.0/tests/test_bins.py +116 -0
- binference-0.1.0/tests/test_constructors.py +151 -0
- binference-0.1.0/tests/test_correlated.py +102 -0
- binference-0.1.0/tests/test_density.py +130 -0
- binference-0.1.0/tests/test_derived_rates.py +91 -0
- binference-0.1.0/tests/test_diagnostics.py +144 -0
- binference-0.1.0/tests/test_engines.py +602 -0
- binference-0.1.0/tests/test_explainers.py +190 -0
- binference-0.1.0/tests/test_gibbs_fixes.py +101 -0
- binference-0.1.0/tests/test_hygiene.py +142 -0
- binference-0.1.0/tests/test_injections.py +311 -0
- binference-0.1.0/tests/test_joint_response.py +228 -0
- binference-0.1.0/tests/test_likelihoods.py +347 -0
- binference-0.1.0/tests/test_map_fixes.py +170 -0
- binference-0.1.0/tests/test_matrix_regression.py +77 -0
- binference-0.1.0/tests/test_measures_masks.py +221 -0
- binference-0.1.0/tests/test_model.py +228 -0
- binference-0.1.0/tests/test_model_fixes.py +173 -0
- binference-0.1.0/tests/test_nuts_fixes.py +111 -0
- binference-0.1.0/tests/test_plotting_io.py +137 -0
- binference-0.1.0/tests/test_prior_fixes.py +221 -0
- binference-0.1.0/tests/test_priors.py +475 -0
- binference-0.1.0/tests/test_response.py +156 -0
- binference-0.1.0/tests/test_results.py +219 -0
- binference-0.1.0/tests/test_results_audit.py +396 -0
- binference-0.1.0/tests/test_results_outputs.py +112 -0
- binference-0.1.0/tests/test_review_regressions.py +316 -0
- binference-0.1.0/tests/test_samples.py +173 -0
- binference-0.1.0/tests/test_sbc_cases.py +91 -0
- binference-0.1.0/tests/test_selection.py +169 -0
- binference-0.1.0/tests/test_simplex.py +51 -0
- binference-0.1.0/tests/test_simulate_validation.py +317 -0
- binference-0.1.0/tests/test_slow.py +319 -0
- binference-0.1.0/tests/test_values.py +206 -0
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
*.egg-info/
|
|
24
|
+
.installed.cfg
|
|
25
|
+
*.egg
|
|
26
|
+
MANIFEST
|
|
27
|
+
|
|
28
|
+
# PyInstaller
|
|
29
|
+
# Usually these files are written by a python script from a template
|
|
30
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
31
|
+
*.manifest
|
|
32
|
+
*.spec
|
|
33
|
+
|
|
34
|
+
# Installer logs
|
|
35
|
+
pip-log.txt
|
|
36
|
+
pip-delete-this-directory.txt
|
|
37
|
+
|
|
38
|
+
# Unit test / coverage reports
|
|
39
|
+
htmlcov/
|
|
40
|
+
.tox/
|
|
41
|
+
.coverage
|
|
42
|
+
.coverage.*
|
|
43
|
+
.cache
|
|
44
|
+
nosetests.xml
|
|
45
|
+
coverage.xml
|
|
46
|
+
*.cover
|
|
47
|
+
.hypothesis/
|
|
48
|
+
.pytest_cache/
|
|
49
|
+
|
|
50
|
+
# Translations
|
|
51
|
+
*.mo
|
|
52
|
+
*.pot
|
|
53
|
+
|
|
54
|
+
# Django stuff:
|
|
55
|
+
*.log
|
|
56
|
+
local_settings.py
|
|
57
|
+
db.sqlite3
|
|
58
|
+
|
|
59
|
+
# Flask stuff:
|
|
60
|
+
instance/
|
|
61
|
+
.webassets-cache
|
|
62
|
+
|
|
63
|
+
# Scrapy stuff:
|
|
64
|
+
.scrapy
|
|
65
|
+
|
|
66
|
+
# Sphinx documentation
|
|
67
|
+
docs/_build/
|
|
68
|
+
|
|
69
|
+
# PyBuilder
|
|
70
|
+
target/
|
|
71
|
+
|
|
72
|
+
# Jupyter Notebook
|
|
73
|
+
.ipynb_checkpoints
|
|
74
|
+
|
|
75
|
+
# pyenv
|
|
76
|
+
.python-version
|
|
77
|
+
|
|
78
|
+
# celery beat schedule file
|
|
79
|
+
celerybeat-schedule
|
|
80
|
+
|
|
81
|
+
# SageMath parsed files
|
|
82
|
+
*.sage.py
|
|
83
|
+
|
|
84
|
+
# Environments
|
|
85
|
+
.env
|
|
86
|
+
.venv
|
|
87
|
+
env/
|
|
88
|
+
venv/
|
|
89
|
+
ENV/
|
|
90
|
+
env.bak/
|
|
91
|
+
venv.bak/
|
|
92
|
+
|
|
93
|
+
# Spyder project settings
|
|
94
|
+
.spyderproject
|
|
95
|
+
.spyproject
|
|
96
|
+
|
|
97
|
+
# Rope project settings
|
|
98
|
+
.ropeproject
|
|
99
|
+
|
|
100
|
+
# mkdocs documentation
|
|
101
|
+
/site
|
|
102
|
+
|
|
103
|
+
# mypy
|
|
104
|
+
.mypy_cache/
|
|
105
|
+
|
|
106
|
+
# Sphinx autosummary output and notebook execution cache
|
|
107
|
+
docs/reference/api/generated/
|
|
108
|
+
docs/jupyter_execute/
|
|
109
|
+
.jupyter_cache/
|
|
@@ -0,0 +1,342 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to binference are recorded here. The format follows
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and versions follow
|
|
5
|
+
[Semantic Versioning](https://semver.org/) (with the usual 0.x caveat that minor
|
|
6
|
+
releases may break the API).
|
|
7
|
+
|
|
8
|
+
## [0.1.0] - 2026-10-29
|
|
9
|
+
|
|
10
|
+
First release.
|
|
11
|
+
|
|
12
|
+
### Changed (landing on `main`)
|
|
13
|
+
|
|
14
|
+
- Renamed from `pastry` to `binference` (package, import and PyPI name; DECISIONS #45).
|
|
15
|
+
The warning base class is `BinferenceWarning` and the environment variables start
|
|
16
|
+
with `BINFERENCE_`.
|
|
17
|
+
|
|
18
|
+
- Python ≥ 3.13, NumPy ≥ 2.1, SciPy ≥ 1.14.1, matplotlib ≥ 3.9.2 (DECISIONS #41, #61).
|
|
19
|
+
- CI runs the pre-commit hooks, the fast suite on three systems with Python 3.13 and
|
|
20
|
+
3.14, minimum dependencies, the README and user-guide code, the docs build and a
|
|
21
|
+
clean-wheel import; pushes to `main` publish the docs to GitHub Pages.
|
|
22
|
+
- Releases: a tag `vX.Y.Z` on `main` publishes to PyPI by trusted publishing
|
|
23
|
+
(DECISIONS #104, #105).
|
|
24
|
+
- Development process: issue and pull-request templates and the rules in `CLAUDE.md` and
|
|
25
|
+
`CONTRIBUTING.md`.
|
|
26
|
+
- The prior base class is now `binference.priors.PopulationPrior` (was `Prior`).
|
|
27
|
+
- On log bins, the default base measures of `Dirichlet.from_base_measure` and
|
|
28
|
+
`PolyaTree`, the default mean of the logistic priors and the "flat" interim prior
|
|
29
|
+
are flat in log z (they were flat in z; DECISIONS #63).
|
|
30
|
+
- Results (audit O-1–O-21, DECISIONS #82): a result keeps its selection through `save`,
|
|
31
|
+
`load` and `attach`, which refuses other bins or another selection;
|
|
32
|
+
`result_to_dict` is what `save` writes (`meta` plus arrays, `label_draws` apart from
|
|
33
|
+
the bin labels); `check()` also flags tail ESS, E-BFMI, one-chain R-hat and
|
|
34
|
+
unconverged optimisers and raises `DiagnosticsError` when strict; `summary` reports
|
|
35
|
+
the mixing of the quantity it summarises; `which=` takes `"fraction(s)"`/`"rate(s)"`
|
|
36
|
+
everywhere, including `functional`, `rebin`, `cov`, `corr`, `plot_corner` and
|
|
37
|
+
`plot_trace`; `method="em"` runs EM on the simplex, and an explicit
|
|
38
|
+
`MAP(algorithm=)` raises where it cannot run instead of falling back to L-BFGS
|
|
39
|
+
(#100); `sample_assignments`, `sample_values` and `realized_counts` default to 500
|
|
40
|
+
draws; `binference.plotting` and `binference.io` load on first use;
|
|
41
|
+
`result.plot_individual`; `PopulationEstimator` works with
|
|
42
|
+
scikit-learn model selection (`Likelihoods.shape`); the xarray export uses ArviZ's
|
|
43
|
+
statistic names, numeric bin centres and hyperparameter draws.
|
|
44
|
+
- `infer` defaults to `method="auto"` (was `"nuts"`; DECISIONS #14, #88): Gibbs for
|
|
45
|
+
joint conjugate models and for conjugate priors with at most 0.98 missing
|
|
46
|
+
information (run long enough for a bulk ESS of about 400), else Laplace when its
|
|
47
|
+
importance check passes with an ESS of at least 400, else NUTS. The choice and
|
|
48
|
+
reason are in `result.info["auto_method"]` and `["auto_reason"]`. The rules are one
|
|
49
|
+
engine, `binference.inference.Auto`, whose thresholds (`target_ess`,
|
|
50
|
+
`gibbs_max_missing`, `nnz_limit`) are options; `PopulationEstimator` defaults to it
|
|
51
|
+
too. Pass `method="nuts"` for the previous behaviour. Without `n_samples`, a Gibbs run
|
|
52
|
+
chosen by auto is extended until its ESS and R-hat pass, or gives way to the next
|
|
53
|
+
engine beyond `max_gibbs_draws` (DECISIONS #89). Laplace draws that auto keeps
|
|
54
|
+
without passing its check (on very large inputs, or as the last candidate) are flagged
|
|
55
|
+
`approximate`.
|
|
56
|
+
- `Laplace` finds its mode and curvature once per engine (and `step`), not on every
|
|
57
|
+
`run`.
|
|
58
|
+
- `PopulationResult.log_predictive` works through the objects `chunk` at a time (a new
|
|
59
|
+
`chunk` argument, 4096 by default, as `predict_proba` and
|
|
60
|
+
`assignment_probabilities` already did), so its memory no longer grows with the
|
|
61
|
+
number of objects times the number of draws.
|
|
62
|
+
|
|
63
|
+
- Names (DECISIONS #90): `sbc` and `coverage` take `progress=` (was `progress_bar=`);
|
|
64
|
+
`CoverageResult.coverage_rates()` (was `rates()`); `Likelihoods.with_weights(
|
|
65
|
+
fractional_weights=)` (was `fractional=`); `simulate.mock_unfolding(n_objects=)` (was
|
|
66
|
+
`n_events=`). Plots label rates `lambda[k]`, as SBC names them (was `rate[k]`). The
|
|
67
|
+
`"se"` kernel alias and the rename hints for the old selection modes are gone.
|
|
68
|
+
- `Gibbs` and `MeanFieldVB` raise `ValueError` (was `TypeError`) for a model they cannot
|
|
69
|
+
run, with the reason `Engine.unsupported(model)` gives.
|
|
70
|
+
- `PopulationModel.stack()` is removed; `likelihoods.stack()` is the one stacking.
|
|
71
|
+
- Engines declare `Engine.markov` (draws are Markov chains, checked by R-hat and ESS)
|
|
72
|
+
and `Engine.unsupported(model)`; `PopulationResult(kind=)` defaults to the model's
|
|
73
|
+
kind; `diagnostics.importance_ess(weights)` is Kish's effective sample size.
|
|
74
|
+
- The chunked kernels work through 4096 dense rows at a time (was 65,536): Gibbs drew
|
|
75
|
+
labels as fast at either size (N = 2·10⁴ to 2·10⁵, K = 20 to 80) with 16 times less
|
|
76
|
+
memory per block. Sparse rows are sampled all at once, since slicing CSR rows per chunk
|
|
77
|
+
cost time (0.030 s per label draw, from 0.035 s, at N = 2·10⁵, K = 200, 2% filled).
|
|
78
|
+
- Faster: Laplace's importance step evaluates its proposals in blocks (5.3 s, from
|
|
79
|
+
28.4 s, for 8000 proposals at N = 10⁵, K = 50, one thread); EM computes `L·ρ` once per
|
|
80
|
+
point; leave-one-out smooths all objects' weights together (3.1 s, from 7.4 s, at
|
|
81
|
+
N = 2·10⁴ with 2000 draws); Gibbs draws labels in place (35 ms, from 47 ms, per draw
|
|
82
|
+
at N = 10⁵, K = 50). `method="auto"` keeps the MAP it computed as `result.best` when that raised no
|
|
83
|
+
warning.
|
|
84
|
+
- Plot colours follow the active matplotlib style instead of fixed hex colours; new
|
|
85
|
+
`sample_color` argument on `plot_population` and `plot_individual`; `color` defaults to
|
|
86
|
+
the style and is added to `plot_individual` and `plot_sbc`; 2-D maps and the corner
|
|
87
|
+
plot's 2-D histograms are drawn on ramps to the population colour (relative uncertainty
|
|
88
|
+
to the text colour) instead of viridis, magma and Blues; `POSTERIOR_COLOR`, `STACK_COLOR` and `INK` are removed (DECISIONS #98).
|
|
89
|
+
|
|
90
|
+
### Fixed (phase-wide review)
|
|
91
|
+
|
|
92
|
+
- PSIS compared weights with the cut as `log(exp(cut))`, so a weight tied with the cut
|
|
93
|
+
could enter the tail with no exceedance; with duplicated draws (resampled Laplace) the
|
|
94
|
+
fit divided by zero. The cut is compared in logs, as ArviZ does; k-hat changes slightly
|
|
95
|
+
where the old comparison included the cut weight.
|
|
96
|
+
- A degenerate generalised-Pareto fit gives k-hat = inf in `diagnostics.psis` (was NaN,
|
|
97
|
+
which compared False with any threshold), so leave-one-out flags such objects.
|
|
98
|
+
- Bootstrap and other resampling of a model with an inferred response kept each row's
|
|
99
|
+
measured bin from before rows were dropped.
|
|
100
|
+
- `attach` clears everything computed from the previous likelihoods (the total, the
|
|
101
|
+
missing information); a model with another prior than the fit's no longer stands in for
|
|
102
|
+
it in `best` and `binning_bias` (compared by a digest of the prior's arguments, saved
|
|
103
|
+
with the result, since its repr shortens arrays); a saved selection on a basis
|
|
104
|
+
re-attaches after load.
|
|
105
|
+
- `save` keeps the unconstrained draws, so `prior_information_ratio` is the same after
|
|
106
|
+
`load`.
|
|
107
|
+
- `PopulationResult.from_samples` refuses a model that infers its selection or response
|
|
108
|
+
unless their draws are given.
|
|
109
|
+
- Diagnostics of a jointly inferred response are named `*_response` (were `*_selection`).
|
|
110
|
+
- Posterior-sample mocks on unequal bins weighted every grid step alike, whatever its
|
|
111
|
+
width (with bins [0, 0.1, 3], half the samples fell in the narrow bin). Their grid is
|
|
112
|
+
now 50 equal steps per bin in the bins' measure (in log z on log bins; was in z).
|
|
113
|
+
- `Selection.draw` floors its Beta draws as Gibbs does, so none underflows to zero.
|
|
114
|
+
- Pickling likelihoods whose within-bin data cannot be pickled warns (they were dropped
|
|
115
|
+
silently).
|
|
116
|
+
|
|
117
|
+
### Added
|
|
118
|
+
|
|
119
|
+
- `benchmarks/matrix.py`: the benchmark matrix of scenario × prior × engine against
|
|
120
|
+
long reference runs (DECISIONS #42), with its results in `benchmarks/results/`.
|
|
121
|
+
|
|
122
|
+
- **Results** (DECISIONS #12, #41, #49, #53, #83): `result.selected` (the selected
|
|
123
|
+
population, also `which="selected"`), `realized_counts(full=True)` (with the missed
|
|
124
|
+
objects), `data_support` and the `support` summary column, `prior_information_ratio()`
|
|
125
|
+
(Efron's ratio), `check(support_min=)`, and `PointEstimate.check()` for the KKT gap.
|
|
126
|
+
- **Binning-bias check** (DECISIONS #6, #20, #86): `result.binning_bias()` refits the
|
|
127
|
+
data on linear B-spline components over the same bins (Gaussian inputs rebuild
|
|
128
|
+
themselves; others take `build`) and reports each bin's shift in posterior s.d. and,
|
|
129
|
+
for flagged bins, `n_crit`, the number of objects at which the binning bias equals
|
|
130
|
+
the statistical error.
|
|
131
|
+
- **Best fit and leave-one-out** (DECISIONS #35, #51, #52, #85): every result has
|
|
132
|
+
`result.best` (the MAP estimate, computed on first use) and per-object outputs at it
|
|
133
|
+
with a `_best` suffix; `assignment_probabilities_loo` gives leave-one-out posteriors
|
|
134
|
+
by Pareto-smoothed importance sampling, with the Pareto k-hat per object.
|
|
135
|
+
- **Value draws from within-bin information** (DECISIONS #50, #84): `sample_values`
|
|
136
|
+
resamples the samples of `from_samples` inside the drawn bin (`keep_samples=`),
|
|
137
|
+
evaluates `from_density` densities inside 1-D bins (interim divided out for
|
|
138
|
+
posteriors), and draws correlated Gaussians jointly by Gibbs sweeps (`n_sweeps=`);
|
|
139
|
+
tables, binned inputs, compressed rows, densities on grids or without a pdf, samples
|
|
140
|
+
not kept and density functions that could not be pickled fall back to flat within
|
|
141
|
+
the bin, with a warning naming the source.
|
|
142
|
+
|
|
143
|
+
- **Measures** (DECISIONS #21): each grid axis has a `Measure`, the coordinate
|
|
144
|
+
`u = T(z)` in which the population is flat within a bin: linear, log, a transform with
|
|
145
|
+
its inverse, or the cumulative integral of a positive density. `Bins.log` uses the log
|
|
146
|
+
measure; bin centres are midpoints in `u`; `Bins.from_centers` takes midpoints in `u`
|
|
147
|
+
(positive edges for log-spaced centres, I-16). Geometric hand-built edges warn.
|
|
148
|
+
- **Selection from injections** (DECISIONS #10, #30, #79, #80): `Selection.from_injections`
|
|
149
|
+
gives a completeness with Beta posteriors per bin, inferred jointly with the population
|
|
150
|
+
by Gibbs, NUTS, Laplace and `MAP(space="unconstrained")` (logit S as extra
|
|
151
|
+
coordinates); `smooth=τ` ties neighbouring bins by a random walk on logit S;
|
|
152
|
+
`at_mean()` fixes it for VB and the bootstrap.
|
|
153
|
+
- **Responses inferred with the population** (DECISIONS #28, #81): a response tallied
|
|
154
|
+
from events (`Response.from_counts`, `from_simulation`, `from_labelled`) has a
|
|
155
|
+
Dirichlet posterior per column (`prior=β`, default 1 per cell) and is inferred jointly
|
|
156
|
+
by Gibbs, NUTS, Laplace and unconstrained MAP; `response.fixed()` takes it as known.
|
|
157
|
+
- **Totals and rates from fractions** (DECISIONS #9, #78): every fractions result has
|
|
158
|
+
`total` (draws of Λ ~ Gamma(W, S·ρ), exact under a scale-free prior) and `rates`
|
|
159
|
+
(Λρ), with an absolute or no selection; point estimates give W/(S·ρ̂).
|
|
160
|
+
- **Mixture basis and internal resolution** (DECISIONS #4, #5, #47, #76):
|
|
161
|
+
`binference.Basis(bins, order=0|1, resolution=r)` fits components on the bins refined
|
|
162
|
+
`r` times, flat (`order=0`) or linear B-spline hats (`order=1`), and reports in the
|
|
163
|
+
bins. Every constructor takes a `Basis` for `bins` (`Likelihoods.on_basis` for
|
|
164
|
+
per-bin likelihoods); callable selections are averaged with each component as the
|
|
165
|
+
weight. Results report per bin and keep `component_draws`; save and load keep the
|
|
166
|
+
basis. `Bins.refine` is the counterpart of `coarsen`. `sample_values` on non-linear
|
|
167
|
+
measures now draws flat in `u` within a bin (it ignored `T'(z)`).
|
|
168
|
+
- `from_samples` stores likelihoods sparsely below 10% non-zero entries (was 30%; DECISIONS
|
|
169
|
+
#77).
|
|
170
|
+
- **Masked grids** (DECISIONS #19): `mask=` on `Bins`, `Bins.grid`, `Bins.linear` and
|
|
171
|
+
`Bins.log`; masked cells leave the support and the model. Saved and loaded with
|
|
172
|
+
results.
|
|
173
|
+
- `Bins` with edges `-0.0` and `0.0` now hash alike (I-12); `Bins.index` refuses
|
|
174
|
+
multi-column values for 1-D bins (I-22).
|
|
175
|
+
- **`Density`** (DECISIONS #26, #63): one fixed density over the bin coordinate for
|
|
176
|
+
interim priors, the Dirichlet base measure and simulation truth. `Density.flat()` is
|
|
177
|
+
flat in the measure coordinate. An array interim prior on unequal bins needs
|
|
178
|
+
`interim_representation`, so every constructor reads it the same way (I-1); a
|
|
179
|
+
callable on categories receives the labels (I-17).
|
|
180
|
+
- `Likelihoods.stack()` uses the interim prior the likelihoods were built with
|
|
181
|
+
(I-5) and raises on rows with no support under it (I-6).
|
|
182
|
+
- **Constructors by input form** (DECISIONS #32, #64): `Likelihoods.from_table` and
|
|
183
|
+
`Likelihoods.from_density` replace `from_posteriors`, `from_function` and
|
|
184
|
+
`from_distributions`; each needs `kind="likelihood"` or `interim=`. `interim_prior`
|
|
185
|
+
is now `interim` (also in `stack()` and `simulate.mock_1d`).
|
|
186
|
+
- **Adaptive quadrature** (DECISIONS #23): bin averages of functions and distributions
|
|
187
|
+
are refined to `tol` (default 1e-3), in the measure coordinate for likelihoods
|
|
188
|
+
(DECISIONS #21); `from_gaussian` averages in u on non-linear axes. Far tails no longer
|
|
189
|
+
underflow to empty rows (I-2, I-3).
|
|
190
|
+
- **Samples** (DECISIONS #31, #67): one estimator for every interim prior (per-sample
|
|
191
|
+
weights T'(z)/π(z); a per-bin prior is flat in u within bins), an opt-in Dirichlet
|
|
192
|
+
`floor` in pseudo-samples,
|
|
193
|
+
`n_eff` inside the bins with a warning on the share of noisy objects (I-23),
|
|
194
|
+
`Likelihoods.sample_variance` and a Monte Carlo variance check in `result.check()`;
|
|
195
|
+
`Measure.log_jacobian`.
|
|
196
|
+
- **Binned measurements** (DECISIONS #27, #29, #68): `binference.Response` holds
|
|
197
|
+
P(measured bin, observed | true bin) with real truth bins, from a matrix, tallies
|
|
198
|
+
(`Response.from_counts`), simulated events (`Response.from_simulation`) or a labelled
|
|
199
|
+
validation set (`Response.from_labelled`: open-ended score bins or a confusion matrix).
|
|
200
|
+
`Likelihoods.from_binned` replaces `from_response`; `from_classifier` is removed
|
|
201
|
+
(route A is `from_table` on categories, route C is `from_binned` with a labelled
|
|
202
|
+
response). `summary()` names the inputs, and `result.check()` runs a posterior
|
|
203
|
+
predictive test of the measured counts (`Response.predictive_pvalue`) that flags label
|
|
204
|
+
shift. `check()` raises `InputWarning` for problems with the inputs (this test and the
|
|
205
|
+
samples' Monte Carlo variance) and `ConvergenceWarning` for sampler problems. `simulate.mock_categorical` gains `temperature` and a labelled `mock.response`;
|
|
206
|
+
`simulate.mock_unfolding` returns `mock.response`.
|
|
207
|
+
- **Selection** (DECISIONS #7, #8, #10, #46, #47, #48, #69): the modes are
|
|
208
|
+
`"on_truth"` and `"on_measurement"` (the old names raise an error naming the new
|
|
209
|
+
ones); `Selection.combined(on_truth, on_measurement)` selects on both; a selection may
|
|
210
|
+
be a function of the true value, averaged over each bin (`Selection.from_function`,
|
|
211
|
+
or a callable `selection=`); values are detection probabilities in (0, 1] unless
|
|
212
|
+
declared `scale="exposure"` or `"relative"`, and rates refuse a relative selection
|
|
213
|
+
(audit G-4); an array that changes by more than a factor of two between neighbouring
|
|
214
|
+
bins raises an `InputWarning` (a `Selection` object or a callable is taken as averaged
|
|
215
|
+
within bins).
|
|
216
|
+
`simulate.mock_1d(measured_range=...)` simulates selection on the measurement, alone
|
|
217
|
+
or with `selection=` (combined). `sbc`/`coverage` name rates `lambda[k]` (G-10).
|
|
218
|
+
- **Model** (DECISIONS #15, #56, #57, #70): `PopulationModel.log_prob` and
|
|
219
|
+
`log_prob_and_grad` are renamed `log_density_unconstrained` and
|
|
220
|
+
`log_density_unconstrained_and_grad`; the theory page explains the two densities
|
|
221
|
+
and their modes. `kkt_gap` is infinite where an object is impossible and, for rates,
|
|
222
|
+
relative to the exposure (audit M-3, M-4); `missing_information` is correct with a
|
|
223
|
+
selection function and on the support, with `include_prior=` for the MAP EM (M-2).
|
|
224
|
+
Bootstrap replicates drop zero-weight objects in every engine, so EM no longer
|
|
225
|
+
resets to the prior's mode or collapses rates to zero (M-1); EM stops with a warning
|
|
226
|
+
where an object becomes impossible. The rates starting point is W ρ / S (M-7).
|
|
227
|
+
`LogisticGP()` works on two bins (M-14). `PopulationResult.log_prob` is now
|
|
228
|
+
`log_density_unconstrained` (old files still load); `MAP.run` no longer takes
|
|
229
|
+
`weights=`.
|
|
230
|
+
- **MAP** (DECISIONS #71): `tol` (default 1e-8, was 1e-10 on the objective) is the
|
|
231
|
+
tolerance on the KKT gap for every simplex algorithm and on the largest gradient over
|
|
232
|
+
`max(1, W)` for L-BFGS (mix-SQP bounds the gap of the problem it solves), and EM is
|
|
233
|
+
converged only when the gap is below it, or below `1e3 * tol` once the objective
|
|
234
|
+
stops improving (M-6, M-9).
|
|
235
|
+
`GammaRates` with shapes of at least one use mix-SQP, with the total rate profiled
|
|
236
|
+
out (M-6). `PointEstimate.log_posterior` is `model.log_posterior(value)` for every
|
|
237
|
+
algorithm (NaN for priors without a closed-form density); L-BFGS adds
|
|
238
|
+
`info["log_density_unconstrained"]` (M-8). mix-SQP drops its SVD and starts after
|
|
239
|
+
10 EM steps instead of 50, 2–3 times faster on large dense inputs (M-5); a failed
|
|
240
|
+
quadratic step hands over to EM instead of raising (M-13); Dirichlet priors
|
|
241
|
+
mixing concentrations of one and above one no longer warn (T-4). The rates KKT gap
|
|
242
|
+
is one-sided, so a rate EM drives towards zero no longer reads as a violation.
|
|
243
|
+
- **Priors** (DECISIONS #72): `LogisticRandomWalk(trend_scale=3.0)` is the standard
|
|
244
|
+
deviation of each unpenalised mode's root-mean-square size across the grid, so its
|
|
245
|
+
meaning no longer depends on K (was 10 in basis units, which tightened as 1/√K; P-6).
|
|
246
|
+
Arguments are checked when a prior is made: `DirichletTree` per-node alphas of
|
|
247
|
+
different lengths now work (P-4), `LogisticNormal(cov=)` must be a positive variance
|
|
248
|
+
or a matrix positive semi-definite on zero-sum vectors (P-8), `LogisticGP` `n_basis`
|
|
249
|
+
and `boundary_factor` are checked and `length_scale` takes an array (P-10, P-11),
|
|
250
|
+
`PolyaTree` needs two bins and a non-negative power (P-9), `GeneralizedDirichlet`
|
|
251
|
+
`a`, `b` and `order` are checked (P-22). Reprs show every argument (P-14); tree VB
|
|
252
|
+
draws have no exact zeros (P-12); `GammaRates` has a `prior_transform` (P-15).
|
|
253
|
+
`GeneralizedDirichlet` and `PolyaTree` are no longer subclasses of `DirichletTree`
|
|
254
|
+
(P-13). `LogisticRandomWalk(2).bind` at K = 1000 and 20,000 GP draws are about twice
|
|
255
|
+
as fast (P-20).
|
|
256
|
+
- **GP prior** (DECISIONS #73): `LogisticGP` is stationary in the measure coordinate
|
|
257
|
+
(log z on `Bins.log`; length scales are in that coordinate; P-1). Defaults:
|
|
258
|
+
`boundary_factor=3` (was 1.5; P-3), `n_basis` one per bin up to 1024 modes in all
|
|
259
|
+
(was at most 48 per axis), and a
|
|
260
|
+
length-scale prior whose lower 1% quantile is the shortest length scale that basis
|
|
261
|
+
resolves (P-2), or `LogNormal(log(range/2), 1)` on coarse grids (P-7). Partially
|
|
262
|
+
centred GP densities and gradients agree where scales underflow (P-5).
|
|
263
|
+
- **NUTS and Laplace** (DECISIONS #74): NUTS results (`x`, `log_density_unconstrained`,
|
|
264
|
+
`model`) and the positions `sample()` yields are in the model's own coordinates, not
|
|
265
|
+
the partly centred sampling ones (`info["centring"]` holds the weights; N-1, N-2).
|
|
266
|
+
`diagnostics.psis_threshold(n)` gives the k̂ threshold for n importance weights. Parallel workers receive the model
|
|
267
|
+
once, reuse one pool per run, never raise a BLAS thread limit already set, respect
|
|
268
|
+
CPU affinity, and errors from the model are raised instead of triggering a serial
|
|
269
|
+
rerun (N-3, N-7, N-13). `max_depth`, `n_warmup`, `jitter` and `init` are checked
|
|
270
|
+
(N-5); Laplace returns every draw asked for without importance resampling (N-4) and
|
|
271
|
+
judges k̂ against min(1 − 1/log10 S, 0.7) (N-6). Dense momentum draws use a
|
|
272
|
+
precomputed triangular factor (N-9).
|
|
273
|
+
- **Validation, Gibbs, bootstrap** (DECISIONS #75): SBC p-values and bands use the
|
|
274
|
+
expected count per rank bin (G-1) and `sbc` warns when the ESS is below `n_draws` (G-9);
|
|
275
|
+
`exact_posterior` integrates by stick-breaking Gauss–Legendre quadrature that resolves
|
|
276
|
+
the simplex boundary, also for concentrations below one, adds `log_density`, and bounds
|
|
277
|
+
its memory, with a default `n_grid` of 200 (G-3, G-5); weighted Gibbs on sparse
|
|
278
|
+
likelihoods draws counts over each row's nonzeros only (G-2); Gibbs checks `chunk`,
|
|
279
|
+
`store_labels` and `init`, and chains start apart, from counts that include missed
|
|
280
|
+
objects (G-6, G-7); SBC rejects `n_bins` above `n_draws + 1`; `Bootstrap(kind=)` is now
|
|
281
|
+
`scheme=`, non-converged replicates are counted and the base fit warns (G-8).
|
|
282
|
+
- **Correlated Gaussians** (DECISIONS #2, #25, #66): `from_gaussian(..., cov=)` takes full
|
|
283
|
+
per-object covariances, averaged over N-D bins by adaptive cubature in log space.
|
|
284
|
+
- `weights` are integer multiplicities; non-integer weights need `fractional_weights=True`
|
|
285
|
+
and warn that the result is a pseudo-likelihood (DECISIONS #1, #65). Stored arrays
|
|
286
|
+
are read-only (I-14); `compress()` keeps sparse storage and is fast on it (I-7, I-19);
|
|
287
|
+
warnings point at the caller's line; clearer errors for bad `rtol`, Gaussian shapes,
|
|
288
|
+
zero objects and 2-D arrays passed to `Bins.grid` (I-8, I-10, I-11, I-20); broad
|
|
289
|
+
Gaussians keep full precision near the mean (I-15).
|
|
290
|
+
- Each object's likelihood mass outside the bins is recorded in
|
|
291
|
+
`meta["outside_fraction"]`, with a warning when many objects lose most of it
|
|
292
|
+
(DECISIONS #18).
|
|
293
|
+
|
|
294
|
+
- **Inputs.** `Bins` (linear, log, from centres, N-D grids, categories) and
|
|
295
|
+
`Likelihoods` with constructors for:
|
|
296
|
+
- likelihood matrices (density or mass representation, dense or sparse,
|
|
297
|
+
log-space input);
|
|
298
|
+
- Gaussian measurements;
|
|
299
|
+
- per-object posteriors with their interim prior;
|
|
300
|
+
- posterior samples;
|
|
301
|
+
- SciPy distributions and arbitrary likelihood functions;
|
|
302
|
+
- response matrices (unfolding) and classifier outputs (quantification).
|
|
303
|
+
- **Selection.** `Selection` functions with explicit `"observed"` and `"true"`
|
|
304
|
+
modes, attached to the data or passed to the model.
|
|
305
|
+
- **Model.** `PopulationModel` for bin fractions or Poisson rates, with
|
|
306
|
+
log-density and gradient in unconstrained coordinates, expected counts,
|
|
307
|
+
responsibilities, an optimality (KKT) gap and the missing-information fraction.
|
|
308
|
+
- **Priors.**
|
|
309
|
+
- Simplex: `Dirichlet` (with reference, count-based and base-measure
|
|
310
|
+
constructors), `GeneralizedDirichlet`, `DirichletTree`, `PolyaTree`.
|
|
311
|
+
- Smoothness: `LogisticNormal`, `LogisticRandomWalk` and `LogisticGP`
|
|
312
|
+
(Hilbert-space GP) on N-D grids, with inferred hyperparameters.
|
|
313
|
+
- Rates: `GammaRates`.
|
|
314
|
+
- **Engines.**
|
|
315
|
+
- `NUTS` (default): multinomial NUTS with windowed metric adaptation.
|
|
316
|
+
Smoothness priors get partial non-centring (where the data constrain
|
|
317
|
+
their scales) and a curvature-based dense metric. Chains are resumable
|
|
318
|
+
and can run in parallel processes, which share the cores' BLAS threads
|
|
319
|
+
(via `threadpoolctl`) rather than oversubscribing them.
|
|
320
|
+
- Data-augmentation `Gibbs` for conjugate priors, with selection augmentation.
|
|
321
|
+
- `MAP` with an optimality certificate: mix-SQP for Dirichlet priors
|
|
322
|
+
(including maximum likelihood under selection), SQUAREM-accelerated EM
|
|
323
|
+
for the other conjugate priors, L-BFGS otherwise.
|
|
324
|
+
- `Laplace` with PSIS importance correction.
|
|
325
|
+
- `MeanFieldVB` (flagged as approximate) and `Bootstrap` (nonparametric or
|
|
326
|
+
Bayesian, over objects, with variable totals for rate models).
|
|
327
|
+
- **Interfaces.** `binference.infer` and the scikit-learn-style `PopulationEstimator`.
|
|
328
|
+
- **Results.** `PopulationResult` and `PointEstimate` provide:
|
|
329
|
+
- summaries, intervals (central and HDI), functionals and rebinning;
|
|
330
|
+
- per-object assignment probabilities, values and realised counts;
|
|
331
|
+
- posterior predictive scores, diagnostics and checks with hints;
|
|
332
|
+
- plots, save/load and xarray `DataTree` export.
|
|
333
|
+
- **Diagnostics.** Rank-normalised split R-hat, bulk and tail ESS,
|
|
334
|
+
autocorrelation time, MCSE and PSIS.
|
|
335
|
+
- **Validation.** Exact quadrature posteriors (K <= 3), simulation-based
|
|
336
|
+
calibration and coverage studies. Mock catalogues in 1-D and 2-D, plus
|
|
337
|
+
categorical, unfolding and prior-predictive mocks.
|
|
338
|
+
- **Design documents, tests, docs.**
|
|
339
|
+
- Specification, test plan, implementation plan, and a survey of related
|
|
340
|
+
software, including an audit of the `frankenz` samplers.
|
|
341
|
+
- A fast and a slow (statistical) test suite.
|
|
342
|
+
- Sphinx documentation with tutorials.
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
cff-version: 1.2.0
|
|
2
|
+
message: "If you use binference, please cite it as below, together with the method papers relevant to your application."
|
|
3
|
+
title: "binference: population and hierarchical inference with PDFs"
|
|
4
|
+
abstract: >-
|
|
5
|
+
binference infers population distributions over bins, and the posteriors of
|
|
6
|
+
individual objects, from heteroscedastic per-object likelihoods, posteriors
|
|
7
|
+
or posterior samples, using an exact hierarchical Bayesian model with
|
|
8
|
+
smoothness priors, selection effects and built-in validation.
|
|
9
|
+
type: software
|
|
10
|
+
authors:
|
|
11
|
+
- family-names: Speagle
|
|
12
|
+
given-names: Joshua S.
|
|
13
|
+
version: 0.1.0
|
|
14
|
+
date-released: 2026-10-29
|
|
15
|
+
license: MIT
|
|
16
|
+
repository-code: "https://github.com/joshspeagle/binference"
|
|
17
|
+
keywords:
|
|
18
|
+
- Bayesian inference
|
|
19
|
+
- hierarchical models
|
|
20
|
+
- population inference
|
|
21
|
+
- deconvolution
|
|
22
|
+
- Dirichlet
|
|
23
|
+
- photometric redshifts
|
|
24
|
+
- unfolding
|
|
25
|
+
references:
|
|
26
|
+
- type: article
|
|
27
|
+
title: "Hierarchical Bayesian inference of galaxy redshift distributions from photometric surveys"
|
|
28
|
+
authors:
|
|
29
|
+
- family-names: Leistedt
|
|
30
|
+
given-names: Boris
|
|
31
|
+
- family-names: Mortlock
|
|
32
|
+
given-names: Daniel J.
|
|
33
|
+
- family-names: Peiris
|
|
34
|
+
given-names: Hiranya V.
|
|
35
|
+
journal: "Monthly Notices of the Royal Astronomical Society"
|
|
36
|
+
volume: 460
|
|
37
|
+
start: 4258
|
|
38
|
+
year: 2016
|
|
39
|
+
doi: "10.1093/mnras/stw1304"
|
|
40
|
+
- type: article
|
|
41
|
+
title: "Inferring the eccentricity distribution"
|
|
42
|
+
authors:
|
|
43
|
+
- family-names: Hogg
|
|
44
|
+
given-names: David W.
|
|
45
|
+
- family-names: Myers
|
|
46
|
+
given-names: Adam D.
|
|
47
|
+
- family-names: Bovy
|
|
48
|
+
given-names: Jo
|
|
49
|
+
journal: "The Astrophysical Journal"
|
|
50
|
+
volume: 725
|
|
51
|
+
start: 2166
|
|
52
|
+
year: 2010
|
|
53
|
+
doi: "10.1088/0004-637X/725/2/2166"
|
binference-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2018 Josh Speagle
|
|
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,130 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: binference
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Population and hierarchical inference with PDFs: honest population distributions from noisy per-object PDFs over bins.
|
|
5
|
+
Project-URL: Homepage, https://github.com/joshspeagle/binference
|
|
6
|
+
Project-URL: Source, https://github.com/joshspeagle/binference
|
|
7
|
+
Project-URL: Documentation, https://joshspeagle.github.io/binference/
|
|
8
|
+
Project-URL: Issues, https://github.com/joshspeagle/binference/issues
|
|
9
|
+
Author: Joshua S. Speagle
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: bayesian,deconvolution,dirichlet,hierarchical,mcmc,photometric redshifts,population inference,quantification,unfolding
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Classifier: Intended Audience :: Science/Research
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering :: Astronomy
|
|
21
|
+
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
22
|
+
Classifier: Topic :: Scientific/Engineering :: Physics
|
|
23
|
+
Requires-Python: >=3.13
|
|
24
|
+
Requires-Dist: numpy>=2.1
|
|
25
|
+
Requires-Dist: scipy>=1.14.1
|
|
26
|
+
Requires-Dist: threadpoolctl>=3.1
|
|
27
|
+
Provides-Extra: all
|
|
28
|
+
Requires-Dist: matplotlib>=3.9.2; extra == 'all'
|
|
29
|
+
Requires-Dist: xarray>=2024.10; extra == 'all'
|
|
30
|
+
Provides-Extra: dev
|
|
31
|
+
Requires-Dist: fonttools>=4.47; extra == 'dev'
|
|
32
|
+
Requires-Dist: ipykernel>=6; extra == 'dev'
|
|
33
|
+
Requires-Dist: matplotlib>=3.9.2; extra == 'dev'
|
|
34
|
+
Requires-Dist: myst-nb>=1.1; extra == 'dev'
|
|
35
|
+
Requires-Dist: numpydoc>=1.6; extra == 'dev'
|
|
36
|
+
Requires-Dist: pre-commit>=3; extra == 'dev'
|
|
37
|
+
Requires-Dist: pytest-cov>=5; extra == 'dev'
|
|
38
|
+
Requires-Dist: pytest>=8; extra == 'dev'
|
|
39
|
+
Requires-Dist: sphinx-copybutton>=0.5; extra == 'dev'
|
|
40
|
+
Requires-Dist: sphinx>=7.2; extra == 'dev'
|
|
41
|
+
Requires-Dist: sphinxcontrib-bibtex>=2.6; extra == 'dev'
|
|
42
|
+
Requires-Dist: xarray>=2024.10; extra == 'dev'
|
|
43
|
+
Provides-Extra: docs
|
|
44
|
+
Requires-Dist: fonttools>=4.47; extra == 'docs'
|
|
45
|
+
Requires-Dist: ipykernel>=6; extra == 'docs'
|
|
46
|
+
Requires-Dist: matplotlib>=3.9.2; extra == 'docs'
|
|
47
|
+
Requires-Dist: myst-nb>=1.1; extra == 'docs'
|
|
48
|
+
Requires-Dist: numpydoc>=1.6; extra == 'docs'
|
|
49
|
+
Requires-Dist: sphinx-copybutton>=0.5; extra == 'docs'
|
|
50
|
+
Requires-Dist: sphinx>=7.2; extra == 'docs'
|
|
51
|
+
Requires-Dist: sphinxcontrib-bibtex>=2.6; extra == 'docs'
|
|
52
|
+
Provides-Extra: plot
|
|
53
|
+
Requires-Dist: matplotlib>=3.9.2; extra == 'plot'
|
|
54
|
+
Provides-Extra: test
|
|
55
|
+
Requires-Dist: matplotlib>=3.9.2; extra == 'test'
|
|
56
|
+
Requires-Dist: pytest-cov>=5; extra == 'test'
|
|
57
|
+
Requires-Dist: pytest>=8; extra == 'test'
|
|
58
|
+
Provides-Extra: xarray
|
|
59
|
+
Requires-Dist: xarray>=2024.10; extra == 'xarray'
|
|
60
|
+
Description-Content-Type: text/markdown
|
|
61
|
+
|
|
62
|
+
# binference
|
|
63
|
+
|
|
64
|
+
**Population and hierarchical inference with PDFs.**
|
|
65
|
+
|
|
66
|
+
Many objects are each measured with noise: galaxies, merger events, patients,
|
|
67
|
+
classified documents. binference reads each object's likelihood, posterior, samples,
|
|
68
|
+
binned measurement or classifier output. From these it infers the population the objects
|
|
69
|
+
come from, with calibrated uncertainty, and each object's posterior under that
|
|
70
|
+
population.
|
|
71
|
+
|
|
72
|
+
![Population posteriors for a mock catalogue][figure]
|
|
73
|
+
|
|
74
|
+
[figure]: https://raw.githubusercontent.com/joshspeagle/binference/main/docs/_static/quickstart.png
|
|
75
|
+
|
|
76
|
+
*The population inferred from 2000 simulated objects, under the default Dirichlet prior
|
|
77
|
+
(top) and a Gaussian-process prior (bottom). Each panel shows the posterior median, its
|
|
78
|
+
68% and 95% intervals, the true density (dashed) and the stacked estimate (dotted).*
|
|
79
|
+
|
|
80
|
+
## Install
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
pip install "binference[plot]"
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
The [installation page](https://joshspeagle.github.io/binference/start/install.html)
|
|
87
|
+
lists the extras and the supported Python versions.
|
|
88
|
+
|
|
89
|
+
## Example
|
|
90
|
+
|
|
91
|
+
```python
|
|
92
|
+
import binference
|
|
93
|
+
|
|
94
|
+
bins = binference.Bins.linear(0.0, 3.0, 15)
|
|
95
|
+
|
|
96
|
+
# a simulated stand-in for your arrays: measured values and their Gaussian errors
|
|
97
|
+
mock = binference.simulate.mock_1d(2000, bins, rng=42)
|
|
98
|
+
z_obs, z_err = mock.measurements["mean"], mock.measurements["sigma"]
|
|
99
|
+
|
|
100
|
+
lk = binference.Likelihoods.from_gaussian(z_obs, z_err, bins)
|
|
101
|
+
result = binference.infer(lk, rng=1) # method="auto" chooses the engine
|
|
102
|
+
print(result.summary())
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Documentation
|
|
106
|
+
|
|
107
|
+
- [Quick start][quickstart]
|
|
108
|
+
- [Is binference right for my data?][is-it-right]
|
|
109
|
+
- [Tutorials][tutorials]
|
|
110
|
+
- [Full documentation][docs]
|
|
111
|
+
|
|
112
|
+
[quickstart]: https://joshspeagle.github.io/binference/start/quickstart.html
|
|
113
|
+
[is-it-right]: https://joshspeagle.github.io/binference/start/is-it-right.html
|
|
114
|
+
[tutorials]: https://joshspeagle.github.io/binference/tutorials/index.html
|
|
115
|
+
[docs]: https://joshspeagle.github.io/binference/
|
|
116
|
+
|
|
117
|
+
To contribute, see [`CONTRIBUTING.md`][contributing].
|
|
118
|
+
|
|
119
|
+
[contributing]: https://github.com/joshspeagle/binference/blob/main/CONTRIBUTING.md
|
|
120
|
+
|
|
121
|
+
## Status and citing
|
|
122
|
+
|
|
123
|
+
binference is alpha software, and its API may change before 1.0. If you use it, please
|
|
124
|
+
cite it as described on the [citing page][citing].
|
|
125
|
+
|
|
126
|
+
[citing]: https://joshspeagle.github.io/binference/reference/citing.html
|
|
127
|
+
|
|
128
|
+
## License
|
|
129
|
+
|
|
130
|
+
MIT; see [LICENSE](https://github.com/joshspeagle/binference/blob/main/LICENSE).
|