gw-catalog-tools 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.
Files changed (25) hide show
  1. gw_catalog_tools-0.1.0/LICENSE +21 -0
  2. gw_catalog_tools-0.1.0/MANIFEST.in +7 -0
  3. gw_catalog_tools-0.1.0/PKG-INFO +151 -0
  4. gw_catalog_tools-0.1.0/README.md +120 -0
  5. gw_catalog_tools-0.1.0/pyproject.toml +54 -0
  6. gw_catalog_tools-0.1.0/setup.cfg +4 -0
  7. gw_catalog_tools-0.1.0/src/catalog_tools/__init__.py +8 -0
  8. gw_catalog_tools-0.1.0/src/catalog_tools/__main__.py +5 -0
  9. gw_catalog_tools-0.1.0/src/catalog_tools/asimov_tests/__init__.py +17 -0
  10. gw_catalog_tools-0.1.0/src/catalog_tools/asimov_tests/automated_review.py +984 -0
  11. gw_catalog_tools-0.1.0/src/catalog_tools/asimov_tests/samples.py +46 -0
  12. gw_catalog_tools-0.1.0/src/catalog_tools/asimov_tests/waveform.py +62 -0
  13. gw_catalog_tools-0.1.0/src/catalog_tools/batch.py +219 -0
  14. gw_catalog_tools-0.1.0/src/catalog_tools/cli.py +171 -0
  15. gw_catalog_tools-0.1.0/src/catalog_tools/diptest.py +538 -0
  16. gw_catalog_tools-0.1.0/src/catalog_tools/review.py +711 -0
  17. gw_catalog_tools-0.1.0/src/gw_catalog_tools.egg-info/PKG-INFO +151 -0
  18. gw_catalog_tools-0.1.0/src/gw_catalog_tools.egg-info/SOURCES.txt +23 -0
  19. gw_catalog_tools-0.1.0/src/gw_catalog_tools.egg-info/dependency_links.txt +1 -0
  20. gw_catalog_tools-0.1.0/src/gw_catalog_tools.egg-info/entry_points.txt +2 -0
  21. gw_catalog_tools-0.1.0/src/gw_catalog_tools.egg-info/requires.txt +11 -0
  22. gw_catalog_tools-0.1.0/src/gw_catalog_tools.egg-info/scm_file_list.json +51 -0
  23. gw_catalog_tools-0.1.0/src/gw_catalog_tools.egg-info/scm_version.json +8 -0
  24. gw_catalog_tools-0.1.0/src/gw_catalog_tools.egg-info/top_level.txt +1 -0
  25. gw_catalog_tools-0.1.0/tests/test_review.py +407 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Daniel Williams
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,7 @@
1
+ # setuptools-scm adds every tracked file to the sdist; keep it to the package.
2
+ prune scripts
3
+ prune examples
4
+ prune docs
5
+ exclude tests/conftest.py tests/test_config_consistency.py tests/test_release_files.py tests/test_release_quality.py
6
+ prune .github
7
+ exclude CLAUDE.md Makefile .gitignore
@@ -0,0 +1,151 @@
1
+ Metadata-Version: 2.4
2
+ Name: gw-catalog-tools
3
+ Version: 0.1.0
4
+ Summary: Automated checks of gravitational-wave parameter estimation results, for catalogue production.
5
+ Author-email: Daniel Williams <daniel.williams@ligo.org>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/transientlunatic/gw-catalog-tools
8
+ Project-URL: Issues, https://github.com/transientlunatic/gw-catalog-tools/issues
9
+ Project-URL: Source, https://github.com/transientlunatic/gw-catalog-tools
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.11
12
+ Classifier: Programming Language :: Python :: 3.12
13
+ Classifier: Programming Language :: Python :: 3.13
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Environment :: Console
16
+ Classifier: Intended Audience :: Science/Research
17
+ Classifier: Topic :: Scientific/Engineering :: Astronomy
18
+ Requires-Python: >=3.11
19
+ Description-Content-Type: text/markdown
20
+ License-File: LICENSE
21
+ Requires-Dist: numpy
22
+ Requires-Dist: scipy
23
+ Requires-Dist: h5py
24
+ Provides-Extra: asimov
25
+ Requires-Dist: asimov>=0.7; extra == "asimov"
26
+ Requires-Dist: bilby_pipe; extra == "asimov"
27
+ Requires-Dist: dill; extra == "asimov"
28
+ Provides-Extra: test
29
+ Requires-Dist: pytest; extra == "test"
30
+ Dynamic: license-file
31
+
32
+ # gw-catalog-tools
33
+
34
+ Automated checks of gravitational-wave parameter estimation (PE) results, for
35
+ producing catalogues at scale. Reviewing every posterior by eye does not scale
36
+ to a catalogue, so these checks flag the common failure modes — a posterior
37
+ railing against its prior, a signal which is really noise or a glitch, several
38
+ modes, a broken post-processing step — and leave the judgement to an analyst.
39
+
40
+ The checks work on PESummary `posterior_samples.h5` files. They can be run from
41
+ the command line on one file, or as tests in an [asimov](https://asimov.readthedocs.io)
42
+ project, where they are run on each analysis awaiting review and write an HTML
43
+ report.
44
+
45
+ ## Installation
46
+
47
+ ```bash
48
+ pip install gw-catalog-tools # the checks and the command line
49
+ pip install "gw-catalog-tools[asimov]" # and what the asimov tests need
50
+ ```
51
+
52
+ From a checkout, `pip install .` (or `pip install -e .`). The checks need only
53
+ numpy, scipy and h5py.
54
+
55
+ ## Command line
56
+
57
+ ```bash
58
+ catalog-tools review posterior_samples.h5 # print a table of results
59
+ catalog-tools review posterior_samples.h5 --json # machine-readable results
60
+ ```
61
+
62
+ The exit status is 1 if any check FAILs, 2 if the file can't be read, and 0
63
+ otherwise. Warnings don't affect it.
64
+
65
+ To review a whole tree of results laid out as
66
+ `ROOT/EVENT/ANALYSIS/posterior_samples.h5`, and summarise them in a table:
67
+
68
+ ```bash
69
+ catalog-tools batch --root ROOT --analysis "bilby-*" -o review.json -m review.md
70
+ catalog-tools report review.json --no-emoji --ignore sky_localization
71
+ ```
72
+
73
+ `batch` skips `generate-psd` directories unless `--exclude` says otherwise, and
74
+ exits 1 if any analysis FAILs or can't be read. `report` renders the JSON again
75
+ without re-running anything.
76
+
77
+ ## In an asimov project
78
+
79
+ ```bash
80
+ cd my-project
81
+ catalog-tools install-tests tests # writes tests/test_catalog_tools.py
82
+ python -m pytest tests
83
+ ```
84
+
85
+ The module it writes is a single import of `catalog_tools.asimov_tests`, so
86
+ pytest finds the tests and upgrading the package upgrades them. asimov must be
87
+ version 0.7 or later, with its bilby pipeline available.
88
+
89
+ By default the review tests run on uploaded bilby analyses which have not been
90
+ reviewed yet. Environment variables change that:
91
+
92
+ | Variable | Effect |
93
+ |---|---|
94
+ | `PE_REVIEW_INCLUDE_REVIEWED=1` | also test analyses which are already approved, rejected or deprecated (useful for validating the checks against past decisions) |
95
+ | `PE_REVIEW_REPORT_DIR=DIR` | write the HTML reports to `DIR/<event>/<analysis>/automated_review.html` instead of beside the PESummary pages in the web root |
96
+
97
+ The samples file of an analysis is looked for in the project's web root
98
+ (`<webroot>/<event>/<analysis>/pesummary/samples/posterior_samples.h5`) and then
99
+ in its results store (`results/<event>/<analysis>/posterior_samples.h5`).
100
+
101
+ ## The checks
102
+
103
+ A FAIL means the analysis should not be accepted as it is; a WARNING flags
104
+ something for an analyst to look at. Thresholds are in `catalog_tools.review`.
105
+
106
+ | Check | Looks for | Result | Threshold |
107
+ |---|---|---|---|
108
+ | `chirp_mass_railing`, `distance_railing` | the prior cutting off real support: the end bin of a histogram of the posterior holds a significant fraction of the density of the highest bin | FAIL, with suggested new bounds | end bin > 2% of the highest of 50 bins (as in peconfigurator); not for the upper end of q, nor for the lower end of distance if the prior already extends below the suggested bound |
109
+ | `multimodality` | more than one significant mode in q, chirp mass or (log) distance, by counting peaks of a kernel density estimate | WARNING | prominence ≥ 8% of the highest peak and ≥ 3% of the probability |
110
+ | `diptest_unimodality` | Hartigan's dip test rejecting unimodality of q, chirp mass or distance; complements the peak count above | WARNING | p ≤ 0.01 |
111
+ | `snr_negative` | negative samples in a matched-filter or optimal SNR column | WARNING | any |
112
+ | `spin_prior_comparison` | spins pushed to the bounds, relative to the prior | WARNING | more than 10% more posterior than prior beyond 0.7 (a₁, a₂, χp) or ±0.9 (χeff) |
113
+ | `snr_plausibility` | a signal which isn't there, is too loud for a near-threshold candidate, or sits in one detector | WARNING | ln Bayes factor < 1 or network SNR < 4; network SNR > 20; one detector holding more than 75% of the SNR² |
114
+ | `effective_sample_size` | too few independent samples | FAIL / WARNING | the sampler's effective sample size < 1000 / < 2500 (the sample count if not stored) |
115
+ | `parameter_consistency` | broken post-processing: total mass, mass ratio and chirp mass inconsistent with the component masses | FAIL | relative error > 0.1% |
116
+ | `likelihood_sanity` | non-finite or constant log-likelihood or log-prior | FAIL | std of log-likelihood < 0.1 |
117
+ | `network_snr` | network SNR not the quadrature sum of the detector SNRs | FAIL | relative error > 1% |
118
+ | `sky_localization` | the 90% sky area (informational; large areas are normal near threshold) | INFO, or WARNING if collapsed to a couple of cells | |
119
+
120
+ The SNR and Bayes-factor thresholds are tuned for a catalogue of near-threshold
121
+ candidates, where a real signal has a network SNR of roughly 6–15. Change the
122
+ constants in `catalog_tools.review` for other uses.
123
+
124
+ Two further tests of the asimov project's own setup are included: that the
125
+ sampler output hasn't lost samples (`TestSampleLoss`), and that the waveform
126
+ arguments in each analysis' configuration are the intended ones
127
+ (`TestWaveformConfiguration`).
128
+
129
+ ### Limitations
130
+
131
+ * The multimodality check does not report a second mode with less than about
132
+ 10–20% of the probability, and a shoulder against a prior bound is not a mode;
133
+ railing is the check which reports that.
134
+ * The checks screen; they do not replace looking at the data. A glitch which
135
+ produces a plausible posterior will pass them all.
136
+
137
+ ## The rest of this repository
138
+
139
+ The repository also holds the scripts and Makefile which drive a catalogue
140
+ release from an asimov ledger. They are not part of the installed package; see
141
+ [docs/release-pipeline.md](docs/release-pipeline.md).
142
+
143
+ ## Development
144
+
145
+ ```bash
146
+ pip install -e ".[test]"
147
+ pytest tests
148
+ ```
149
+
150
+ The tests use synthetic data with known answers, and need neither asimov nor
151
+ a project.
@@ -0,0 +1,120 @@
1
+ # gw-catalog-tools
2
+
3
+ Automated checks of gravitational-wave parameter estimation (PE) results, for
4
+ producing catalogues at scale. Reviewing every posterior by eye does not scale
5
+ to a catalogue, so these checks flag the common failure modes — a posterior
6
+ railing against its prior, a signal which is really noise or a glitch, several
7
+ modes, a broken post-processing step — and leave the judgement to an analyst.
8
+
9
+ The checks work on PESummary `posterior_samples.h5` files. They can be run from
10
+ the command line on one file, or as tests in an [asimov](https://asimov.readthedocs.io)
11
+ project, where they are run on each analysis awaiting review and write an HTML
12
+ report.
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ pip install gw-catalog-tools # the checks and the command line
18
+ pip install "gw-catalog-tools[asimov]" # and what the asimov tests need
19
+ ```
20
+
21
+ From a checkout, `pip install .` (or `pip install -e .`). The checks need only
22
+ numpy, scipy and h5py.
23
+
24
+ ## Command line
25
+
26
+ ```bash
27
+ catalog-tools review posterior_samples.h5 # print a table of results
28
+ catalog-tools review posterior_samples.h5 --json # machine-readable results
29
+ ```
30
+
31
+ The exit status is 1 if any check FAILs, 2 if the file can't be read, and 0
32
+ otherwise. Warnings don't affect it.
33
+
34
+ To review a whole tree of results laid out as
35
+ `ROOT/EVENT/ANALYSIS/posterior_samples.h5`, and summarise them in a table:
36
+
37
+ ```bash
38
+ catalog-tools batch --root ROOT --analysis "bilby-*" -o review.json -m review.md
39
+ catalog-tools report review.json --no-emoji --ignore sky_localization
40
+ ```
41
+
42
+ `batch` skips `generate-psd` directories unless `--exclude` says otherwise, and
43
+ exits 1 if any analysis FAILs or can't be read. `report` renders the JSON again
44
+ without re-running anything.
45
+
46
+ ## In an asimov project
47
+
48
+ ```bash
49
+ cd my-project
50
+ catalog-tools install-tests tests # writes tests/test_catalog_tools.py
51
+ python -m pytest tests
52
+ ```
53
+
54
+ The module it writes is a single import of `catalog_tools.asimov_tests`, so
55
+ pytest finds the tests and upgrading the package upgrades them. asimov must be
56
+ version 0.7 or later, with its bilby pipeline available.
57
+
58
+ By default the review tests run on uploaded bilby analyses which have not been
59
+ reviewed yet. Environment variables change that:
60
+
61
+ | Variable | Effect |
62
+ |---|---|
63
+ | `PE_REVIEW_INCLUDE_REVIEWED=1` | also test analyses which are already approved, rejected or deprecated (useful for validating the checks against past decisions) |
64
+ | `PE_REVIEW_REPORT_DIR=DIR` | write the HTML reports to `DIR/<event>/<analysis>/automated_review.html` instead of beside the PESummary pages in the web root |
65
+
66
+ The samples file of an analysis is looked for in the project's web root
67
+ (`<webroot>/<event>/<analysis>/pesummary/samples/posterior_samples.h5`) and then
68
+ in its results store (`results/<event>/<analysis>/posterior_samples.h5`).
69
+
70
+ ## The checks
71
+
72
+ A FAIL means the analysis should not be accepted as it is; a WARNING flags
73
+ something for an analyst to look at. Thresholds are in `catalog_tools.review`.
74
+
75
+ | Check | Looks for | Result | Threshold |
76
+ |---|---|---|---|
77
+ | `chirp_mass_railing`, `distance_railing` | the prior cutting off real support: the end bin of a histogram of the posterior holds a significant fraction of the density of the highest bin | FAIL, with suggested new bounds | end bin > 2% of the highest of 50 bins (as in peconfigurator); not for the upper end of q, nor for the lower end of distance if the prior already extends below the suggested bound |
78
+ | `multimodality` | more than one significant mode in q, chirp mass or (log) distance, by counting peaks of a kernel density estimate | WARNING | prominence ≥ 8% of the highest peak and ≥ 3% of the probability |
79
+ | `diptest_unimodality` | Hartigan's dip test rejecting unimodality of q, chirp mass or distance; complements the peak count above | WARNING | p ≤ 0.01 |
80
+ | `snr_negative` | negative samples in a matched-filter or optimal SNR column | WARNING | any |
81
+ | `spin_prior_comparison` | spins pushed to the bounds, relative to the prior | WARNING | more than 10% more posterior than prior beyond 0.7 (a₁, a₂, χp) or ±0.9 (χeff) |
82
+ | `snr_plausibility` | a signal which isn't there, is too loud for a near-threshold candidate, or sits in one detector | WARNING | ln Bayes factor < 1 or network SNR < 4; network SNR > 20; one detector holding more than 75% of the SNR² |
83
+ | `effective_sample_size` | too few independent samples | FAIL / WARNING | the sampler's effective sample size < 1000 / < 2500 (the sample count if not stored) |
84
+ | `parameter_consistency` | broken post-processing: total mass, mass ratio and chirp mass inconsistent with the component masses | FAIL | relative error > 0.1% |
85
+ | `likelihood_sanity` | non-finite or constant log-likelihood or log-prior | FAIL | std of log-likelihood < 0.1 |
86
+ | `network_snr` | network SNR not the quadrature sum of the detector SNRs | FAIL | relative error > 1% |
87
+ | `sky_localization` | the 90% sky area (informational; large areas are normal near threshold) | INFO, or WARNING if collapsed to a couple of cells | |
88
+
89
+ The SNR and Bayes-factor thresholds are tuned for a catalogue of near-threshold
90
+ candidates, where a real signal has a network SNR of roughly 6–15. Change the
91
+ constants in `catalog_tools.review` for other uses.
92
+
93
+ Two further tests of the asimov project's own setup are included: that the
94
+ sampler output hasn't lost samples (`TestSampleLoss`), and that the waveform
95
+ arguments in each analysis' configuration are the intended ones
96
+ (`TestWaveformConfiguration`).
97
+
98
+ ### Limitations
99
+
100
+ * The multimodality check does not report a second mode with less than about
101
+ 10–20% of the probability, and a shoulder against a prior bound is not a mode;
102
+ railing is the check which reports that.
103
+ * The checks screen; they do not replace looking at the data. A glitch which
104
+ produces a plausible posterior will pass them all.
105
+
106
+ ## The rest of this repository
107
+
108
+ The repository also holds the scripts and Makefile which drive a catalogue
109
+ release from an asimov ledger. They are not part of the installed package; see
110
+ [docs/release-pipeline.md](docs/release-pipeline.md).
111
+
112
+ ## Development
113
+
114
+ ```bash
115
+ pip install -e ".[test]"
116
+ pytest tests
117
+ ```
118
+
119
+ The tests use synthetic data with known answers, and need neither asimov nor
120
+ a project.
@@ -0,0 +1,54 @@
1
+ [build-system]
2
+ requires = ["setuptools>=77.0", "setuptools-scm>=8"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "gw-catalog-tools"
7
+ dynamic = ["version"]
8
+ description = "Automated checks of gravitational-wave parameter estimation results, for catalogue production."
9
+ readme = "README.md"
10
+ requires-python = ">=3.11"
11
+ license = "MIT"
12
+ license-files = ["LICENSE"]
13
+ authors = [
14
+ { name = "Daniel Williams", email = "daniel.williams@ligo.org" },
15
+ ]
16
+ classifiers = [
17
+ "Programming Language :: Python :: 3",
18
+ "Programming Language :: Python :: 3.11",
19
+ "Programming Language :: Python :: 3.12",
20
+ "Programming Language :: Python :: 3.13",
21
+ "Operating System :: OS Independent",
22
+ "Environment :: Console",
23
+ "Intended Audience :: Science/Research",
24
+ "Topic :: Scientific/Engineering :: Astronomy",
25
+ ]
26
+ dependencies = [
27
+ "numpy",
28
+ "scipy",
29
+ "h5py",
30
+ ]
31
+
32
+ [project.optional-dependencies]
33
+ # What the tests which run inside an asimov project need.
34
+ asimov = [
35
+ "asimov>=0.7",
36
+ "bilby_pipe",
37
+ "dill",
38
+ ]
39
+ test = [
40
+ "pytest",
41
+ ]
42
+
43
+ [project.urls]
44
+ Homepage = "https://github.com/transientlunatic/gw-catalog-tools"
45
+ Issues = "https://github.com/transientlunatic/gw-catalog-tools/issues"
46
+ Source = "https://github.com/transientlunatic/gw-catalog-tools"
47
+
48
+ [project.scripts]
49
+ catalog-tools = "catalog_tools.cli:main"
50
+
51
+ [tool.setuptools.packages.find]
52
+ where = ["src"]
53
+
54
+ [tool.setuptools_scm]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,8 @@
1
+ """Automated checks of gravitational-wave parameter estimation results."""
2
+
3
+ from importlib.metadata import PackageNotFoundError, version
4
+
5
+ try:
6
+ __version__ = version("gw-catalog-tools")
7
+ except PackageNotFoundError: # running from a source tree which isn't installed
8
+ __version__ = "unknown"
@@ -0,0 +1,5 @@
1
+ import sys
2
+
3
+ from .cli import main
4
+
5
+ sys.exit(main())
@@ -0,0 +1,17 @@
1
+ """
2
+ The tests which run in an asimov project.
3
+
4
+ Importing this module needs asimov, and, as asimov does when it is imported,
5
+ reads the ledger of the project in the current directory.
6
+
7
+ To run the tests, put them in the project's tests directory with
8
+ ``catalog-tools install-tests``, or import them into a test module of your own::
9
+
10
+ from catalog_tools.asimov_tests import *
11
+ """
12
+
13
+ from .automated_review import TestAutomatedReview
14
+ from .samples import TestSampleLoss
15
+ from .waveform import TestWaveformConfiguration
16
+
17
+ __all__ = ["TestAutomatedReview", "TestSampleLoss", "TestWaveformConfiguration"]