nullcal 0.2.0__tar.gz → 0.2.1__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.
- {nullcal-0.2.0 → nullcal-0.2.1}/.github/workflows/codeql.yml +3 -3
- {nullcal-0.2.0 → nullcal-0.2.1}/.github/workflows/draft_release.yml +1 -1
- {nullcal-0.2.0 → nullcal-0.2.1}/.github/workflows/release.yml +1 -1
- {nullcal-0.2.0 → nullcal-0.2.1}/.github/workflows/scheduled_release.yml +1 -1
- {nullcal-0.2.0 → nullcal-0.2.1}/.github/workflows/support_floor_update.yml +1 -1
- {nullcal-0.2.0 → nullcal-0.2.1}/.pre-commit-config.yaml +4 -4
- {nullcal-0.2.0 → nullcal-0.2.1}/PKG-INFO +1 -1
- {nullcal-0.2.0 → nullcal-0.2.1}/docs/user-guide/quickstart.md +23 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/pyproject.toml +4 -3
- {nullcal-0.2.0 → nullcal-0.2.1}/src/nullcal/calibration.py +34 -0
- nullcal-0.2.1/tests/calibration/test_posterior_summary.py +23 -0
- nullcal-0.2.1/tests/likelihood/test_recalibration_direction.py +107 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/tests/time_frequency_transform/test_time_domain_transform.py +16 -1
- {nullcal-0.2.0 → nullcal-0.2.1}/uv.lock +192 -191
- {nullcal-0.2.0 → nullcal-0.2.1}/.coderabbit.yaml +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/.github/ISSUE_TEMPLATE/bug-report.md +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/.github/ISSUE_TEMPLATE/feature-request.md +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/.github/pull_request_template.md +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/.github/workflows/ci.yml +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/.github/workflows/documentation.yml +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/.github/workflows/publish.yml +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/.github/workflows/publish_testpypi.yml +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/.github/workflows/semantic_pull_request.yml +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/.gitignore +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/.markdownlint.yaml +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/.prettierignore +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/.prettierrc.yaml +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/.typos.toml +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/CODE_OF_CONDUCT.md +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/CONTRIBUTING.md +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/LICENSE +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/MANIFEST.in +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/README.md +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/cliff.toml +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/docs/.gitignore +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/docs/contributing.md +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/docs/dev/architecture.md +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/docs/index.md +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/docs/javascripts/mathjax.js +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/docs/reference/index.md +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/docs/reference/nullcal/clustering/base.md +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/docs/reference/nullcal/clustering/index.md +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/docs/reference/nullcal/clustering/injection.md +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/docs/reference/nullcal/clustering/precompute.md +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/docs/reference/nullcal/clustering/single.md +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/docs/reference/nullcal/clustering/time_frequency_map.md +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/docs/reference/nullcal/data.md +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/docs/reference/nullcal/index.md +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/docs/reference/nullcal/likelihood/index.md +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/docs/reference/nullcal/likelihood/recalibration_likelihood.md +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/docs/reference/nullcal/metadata/index.md +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/docs/reference/nullcal/metadata/yaml.md +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/docs/reference/nullcal/null_stream/calibration.md +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/docs/reference/nullcal/null_stream/index.md +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/docs/reference/nullcal/null_stream/null_stream.md +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/docs/reference/nullcal/null_stream/projector.md +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/docs/reference/nullcal/null_stream/whiten.md +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/docs/reference/nullcal/result/index.md +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/docs/reference/nullcal/result/result.md +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/docs/reference/nullcal/result/utils.md +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/docs/reference/nullcal/time_frequency_transform/index.md +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/docs/reference/nullcal/time_frequency_transform/inverse_wavelet_freq_funcs.md +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/docs/reference/nullcal/time_frequency_transform/inverse_wavelet_time_funcs.md +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/docs/reference/nullcal/time_frequency_transform/stft.md +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/docs/reference/nullcal/time_frequency_transform/transform_freq_funcs.md +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/docs/reference/nullcal/time_frequency_transform/transform_time_funcs.md +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/docs/reference/nullcal/time_frequency_transform/utils.md +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/docs/reference/nullcal/time_frequency_transform/wavelet_transforms.md +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/docs/reference/nullcal/utils/index.md +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/docs/reference/nullcal/utils/log.md +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/docs/reference/nullcal/utils/snr.md +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/docs/reference/nullcal/version.md +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/docs/security.md +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/docs/user-guide/installation.md +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/renovate.json +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/scripts/calibration_bilby_anchor.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/scripts/diagnose_likelihood_agreement.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/scripts/jax_wdm_verification.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/scripts/lwa_leakage_study.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/scripts/release_version.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/scripts/run_reference_blackjax.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/scripts/spline_resolution_study.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/src/nullcal/__init__.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/src/nullcal/clustering/__init__.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/src/nullcal/clustering/base.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/src/nullcal/clustering/injection.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/src/nullcal/clustering/precompute.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/src/nullcal/clustering/single.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/src/nullcal/clustering/time_frequency_map.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/src/nullcal/data.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/src/nullcal/likelihood/__init__.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/src/nullcal/likelihood/recalibration_likelihood.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/src/nullcal/metadata/__init__.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/src/nullcal/metadata/yaml.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/src/nullcal/null_stream/__init__.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/src/nullcal/null_stream/calibration.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/src/nullcal/null_stream/null_stream.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/src/nullcal/null_stream/projector.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/src/nullcal/null_stream/whiten.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/src/nullcal/result/__init__.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/src/nullcal/result/result.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/src/nullcal/result/utils.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/src/nullcal/sampler.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/src/nullcal/studies/__init__.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/src/nullcal/studies/lwa_leakage.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/src/nullcal/studies/spline_resolution.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/src/nullcal/time_frequency_transform/README.md +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/src/nullcal/time_frequency_transform/__init__.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/src/nullcal/time_frequency_transform/inverse_wavelet_freq_funcs.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/src/nullcal/time_frequency_transform/inverse_wavelet_time_funcs.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/src/nullcal/time_frequency_transform/stft.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/src/nullcal/time_frequency_transform/transform_freq_funcs.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/src/nullcal/time_frequency_transform/transform_time_funcs.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/src/nullcal/time_frequency_transform/utils.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/src/nullcal/time_frequency_transform/wavelet_transforms.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/src/nullcal/utils/__init__.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/src/nullcal/utils/log.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/src/nullcal/utils/snr.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/src/nullcal/version.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/tests/.gitignore +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/tests/calibration/bilby_anchor.md +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/tests/calibration/test_model.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/tests/clustering/conftest.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/tests/clustering/test_clustering_algorithm.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/tests/clustering/test_clustering_classes.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/tests/clustering/test_single_clustering.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/tests/clustering/test_time_frequency_map.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/tests/e2e/README.md +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/tests/e2e/__init__.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/tests/e2e/config.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/tests/e2e/diagnostics/likelihood_agreement.json +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/tests/e2e/generate_reference.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/tests/e2e/generate_reference_inputs.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/tests/e2e/pipeline.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/tests/e2e/reference/artifacts.npz +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/tests/e2e/reference/blackjax_posterior_manifest.json +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/tests/e2e/reference/blackjax_posterior_samples.npz +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/tests/e2e/reference/inputs.npz +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/tests/e2e/reference/inputs_manifest.json +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/tests/e2e/reference/manifest.json +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/tests/e2e/reference/posterior_manifest.json +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/tests/e2e/reference/posterior_samples.npz +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/tests/e2e/test_blackjax_posterior.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/tests/e2e/test_noise_log_likelihood_filter_domain.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/tests/e2e/test_reference_artifacts.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/tests/e2e/test_reference_posterior.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/tests/likelihood/test_logdensity.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/tests/likelihood/test_recalibration_likelihood.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/tests/metadata/test_yaml.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/tests/null_stream/test_calibration_jax.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/tests/null_stream/test_null_stream.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/tests/null_stream/test_projector.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/tests/null_stream/test_whiten.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/tests/result/test_result.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/tests/smoke_test.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/tests/studies/test_lwa_leakage.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/tests/studies/test_spline_resolution.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/tests/test_blackjax_boundary.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/tests/test_data.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/tests/test_dependencies_are_declared.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/tests/test_jax_wdm_verification.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/tests/test_release_version.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/tests/test_sampler.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/tests/time_frequency_transform/test_jax_transform.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/tests/time_frequency_transform/test_stft.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/tests/time_frequency_transform/test_transform_freq_funcs.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/tests/time_frequency_transform/test_utils.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/tests/time_frequency_transform/test_wavelet_transforms.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/tests/time_frequency_transform/test_wdm_window.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/tests/utils/test_log.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/tests/utils/test_snr.py +0 -0
- {nullcal-0.2.0 → nullcal-0.2.1}/zensical.toml +0 -0
|
@@ -22,13 +22,13 @@ jobs:
|
|
|
22
22
|
uses: actions/checkout@d23441a48e516b6c34aea4fa41551a30e30af803 # v6
|
|
23
23
|
|
|
24
24
|
- name: Initialize CodeQL
|
|
25
|
-
uses: github/codeql-action/init@
|
|
25
|
+
uses: github/codeql-action/init@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4
|
|
26
26
|
with:
|
|
27
27
|
languages: python
|
|
28
28
|
queries: security-and-quality
|
|
29
29
|
|
|
30
30
|
- name: Autobuild
|
|
31
|
-
uses: github/codeql-action/autobuild@
|
|
31
|
+
uses: github/codeql-action/autobuild@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4
|
|
32
32
|
|
|
33
33
|
- name: Perform CodeQL Analysis
|
|
34
|
-
uses: github/codeql-action/analyze@
|
|
34
|
+
uses: github/codeql-action/analyze@2892aa5e19bbd11bc0cff5427e3b750a04d9e3c2 # v4
|
|
@@ -22,7 +22,7 @@ jobs:
|
|
|
22
22
|
|
|
23
23
|
- name: Generate changelog
|
|
24
24
|
id: changelog
|
|
25
|
-
uses: orhun/git-cliff-action@
|
|
25
|
+
uses: orhun/git-cliff-action@a9a95522b26fe6403f7bb24031f21fb573d0f5ff # v4.9.1
|
|
26
26
|
with:
|
|
27
27
|
config: cliff.toml
|
|
28
28
|
args: --unreleased --verbose
|
|
@@ -30,7 +30,7 @@ jobs:
|
|
|
30
30
|
|
|
31
31
|
- name: Generate changelog
|
|
32
32
|
id: changelog
|
|
33
|
-
uses: orhun/git-cliff-action@
|
|
33
|
+
uses: orhun/git-cliff-action@a9a95522b26fe6403f7bb24031f21fb573d0f5ff # v4.9.1
|
|
34
34
|
with:
|
|
35
35
|
config: cliff.toml
|
|
36
36
|
args: --current --verbose
|
|
@@ -31,7 +31,7 @@ jobs:
|
|
|
31
31
|
|
|
32
32
|
- name: Check for new commits
|
|
33
33
|
id: check_commits
|
|
34
|
-
uses: isaac-cf-wong/detect-git-changes-action@
|
|
34
|
+
uses: isaac-cf-wong/detect-git-changes-action@a8b0d224a4fdff017607079f83f01f013b9d66a6 # v0.0.20
|
|
35
35
|
with:
|
|
36
36
|
use-latest-tag: true
|
|
37
37
|
|
|
@@ -22,7 +22,7 @@ jobs:
|
|
|
22
22
|
|
|
23
23
|
- name: Apply support policy (spec0, from pyproject tool table)
|
|
24
24
|
id: policy
|
|
25
|
-
uses: isaac-cf-wong/dependency-support-policy-action@
|
|
25
|
+
uses: isaac-cf-wong/dependency-support-policy-action@dfc24273d70d9730ede96b5fdef09a8d7887cf04 # v0.2.10
|
|
26
26
|
with:
|
|
27
27
|
mode: update
|
|
28
28
|
|
|
@@ -17,7 +17,7 @@ repos:
|
|
|
17
17
|
- id: check-json
|
|
18
18
|
|
|
19
19
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
20
|
-
rev: v0.16.
|
|
20
|
+
rev: v0.16.9
|
|
21
21
|
hooks:
|
|
22
22
|
- id: ruff
|
|
23
23
|
args: [--fix, --config=pyproject.toml]
|
|
@@ -29,13 +29,13 @@ repos:
|
|
|
29
29
|
- id: taplo-format
|
|
30
30
|
|
|
31
31
|
- repo: https://github.com/crate-ci/typos
|
|
32
|
-
rev: v1.50.
|
|
32
|
+
rev: v1.50.3
|
|
33
33
|
hooks:
|
|
34
34
|
- id: typos
|
|
35
35
|
args: []
|
|
36
36
|
|
|
37
37
|
- repo: https://github.com/rbubley/mirrors-prettier
|
|
38
|
-
rev: v3.9.
|
|
38
|
+
rev: v3.9.9
|
|
39
39
|
hooks:
|
|
40
40
|
- id: prettier
|
|
41
41
|
exclude: ^tests/e2e/diagnostics/likelihood_agreement\.json$
|
|
@@ -54,7 +54,7 @@ repos:
|
|
|
54
54
|
- id: actionlint
|
|
55
55
|
|
|
56
56
|
- repo: https://github.com/astral-sh/uv-pre-commit
|
|
57
|
-
rev: 0.12.
|
|
57
|
+
rev: 0.12.20
|
|
58
58
|
hooks:
|
|
59
59
|
# Update the uv lockfile
|
|
60
60
|
- id: uv-lock
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: nullcal
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: A package to constrain calibration errors of a closed-geometry network of gravitational-wave detectors.
|
|
5
5
|
Project-URL: Source, https://github.com/Leuven-Gravity-Institute/nullcal
|
|
6
6
|
Project-URL: Tracker, https://github.com/Leuven-Gravity-Institute/nullcal/issues
|
|
@@ -77,6 +77,29 @@ log_posterior = likelihood.logdensity_fn(params)
|
|
|
77
77
|
Use `nullcal.sampler.sample_nuts` when the standard window-adapted NUTS run and
|
|
78
78
|
R-hat, ESS, and divergence diagnostics are desired together.
|
|
79
79
|
|
|
80
|
+
## 5. Summarize and Apply a Calibration Posterior
|
|
81
|
+
|
|
82
|
+
```python
|
|
83
|
+
from nullcal.calibration import posterior_median_calibration_factor
|
|
84
|
+
|
|
85
|
+
# result is the output of nullcal.sampler.sample_nuts(...).
|
|
86
|
+
frequencies = data.frequency_array[np.all(data.mask, axis=0)]
|
|
87
|
+
factor = posterior_median_calibration_factor(
|
|
88
|
+
frequencies,
|
|
89
|
+
likelihood.knot_frequencies,
|
|
90
|
+
result.samples["amplitude"],
|
|
91
|
+
result.samples["phase"],
|
|
92
|
+
)
|
|
93
|
+
corrected_strain = np.asarray(data.strain).copy()
|
|
94
|
+
corrected_strain[:, np.all(data.mask, axis=0)] /= np.asarray(factor)
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
The likelihood multiplies the whitened antenna response by the calibration
|
|
98
|
+
factor. Correcting observed strain uses its inverse, as above. The point
|
|
99
|
+
estimate evaluates the complex factor for every posterior sample at every
|
|
100
|
+
frequency, then takes separate medians of its real and imaginary parts.
|
|
101
|
+
Evaluating a spline from median knot values is a different estimator.
|
|
102
|
+
|
|
80
103
|
## Next Steps
|
|
81
104
|
|
|
82
105
|
- See [Installation](installation.md) for environment setup
|
|
@@ -53,7 +53,7 @@ Tracker = "https://github.com/Leuven-Gravity-Institute/nullcal/issues"
|
|
|
53
53
|
|
|
54
54
|
[dependency-groups]
|
|
55
55
|
dev = [
|
|
56
|
-
"ruff>=0.16.
|
|
56
|
+
"ruff>=0.16.9",
|
|
57
57
|
"prek>=0.5.3",
|
|
58
58
|
"pytest-github-actions-annotate-failures>=0.4.2",
|
|
59
59
|
"pytest-cov>=7.1.0",
|
|
@@ -61,7 +61,7 @@ dev = [
|
|
|
61
61
|
"pytest>=9.1.1",
|
|
62
62
|
]
|
|
63
63
|
|
|
64
|
-
docs = ["zensical>=0.0.
|
|
64
|
+
docs = ["zensical>=0.0.65", "mkdocstrings-python>=2.0.9"]
|
|
65
65
|
build = ["hatch>=1.18.1"]
|
|
66
66
|
release = ["git-cliff>=2.14.2"]
|
|
67
67
|
|
|
@@ -84,7 +84,8 @@ parallel = true
|
|
|
84
84
|
source = ["src"]
|
|
85
85
|
|
|
86
86
|
[tool.coverage.report]
|
|
87
|
-
|
|
87
|
+
# Policy target: keep at least three-fifths of the package covered while retaining regression headroom.
|
|
88
|
+
fail_under = 60
|
|
88
89
|
omit = ["*/tests/*", "*/site-packages/*"]
|
|
89
90
|
|
|
90
91
|
[tool.coverage.paths]
|
|
@@ -7,6 +7,12 @@ uniform log-frequency grid and also permits nonuniform knot placement.
|
|
|
7
7
|
Importing this module enables JAX's process-wide ``jax_enable_x64`` setting.
|
|
8
8
|
Calibration inference requires float64 precision, so this side effect is an
|
|
9
9
|
intentional part of the module's public behavior.
|
|
10
|
+
|
|
11
|
+
For a posterior point estimate, evaluate the complex calibration factor for
|
|
12
|
+
each sample at each frequency, then take the componentwise median of its real
|
|
13
|
+
and imaginary parts. Interpolating median knot values gives a different curve.
|
|
14
|
+
The factor multiplies the antenna response; to correct observed strain, divide
|
|
15
|
+
the strain by the estimated factor.
|
|
10
16
|
"""
|
|
11
17
|
|
|
12
18
|
from __future__ import annotations
|
|
@@ -21,6 +27,7 @@ jax.config.update("jax_enable_x64", True)
|
|
|
21
27
|
import jax.numpy as jnp # noqa: E402
|
|
22
28
|
|
|
23
29
|
MINIMUM_CUBIC_SPLINE_KNOTS = 4
|
|
30
|
+
POSTERIOR_ARRAY_NDIM = 3
|
|
24
31
|
|
|
25
32
|
|
|
26
33
|
def _float64(values):
|
|
@@ -109,6 +116,32 @@ def calibration_factor(frequencies, knot_frequencies, amplitude, phase):
|
|
|
109
116
|
return (1.0 + delta_amplitude) * (2.0 + imaginary_phase) / (2.0 - imaginary_phase)
|
|
110
117
|
|
|
111
118
|
|
|
119
|
+
def posterior_median_calibration_factor(frequencies, knot_frequencies, amplitudes, phases):
|
|
120
|
+
"""Return the per-frequency posterior median of the complex factor.
|
|
121
|
+
|
|
122
|
+
``amplitudes`` and ``phases`` have shape ``(sample, detector, knot)``;
|
|
123
|
+
knots may have shape ``(knot,)`` or ``(detector, knot)``. The complex median
|
|
124
|
+
is defined componentwise in real and imaginary coordinates. This evaluates
|
|
125
|
+
every posterior sample before taking the median, rather than evaluating a
|
|
126
|
+
curve from median knot values.
|
|
127
|
+
"""
|
|
128
|
+
amplitudes = _float64(amplitudes)
|
|
129
|
+
phases = _float64(phases)
|
|
130
|
+
knots = _float64(knot_frequencies)
|
|
131
|
+
if amplitudes.ndim != POSTERIOR_ARRAY_NDIM or phases.shape != amplitudes.shape or amplitudes.shape[0] == 0:
|
|
132
|
+
raise ValueError("amplitudes and phases must have matching nonempty (sample, detector, knot) shapes")
|
|
133
|
+
if knots.ndim == 1:
|
|
134
|
+
knots = jnp.broadcast_to(knots, amplitudes.shape[1:])
|
|
135
|
+
if knots.shape != amplitudes.shape[1:]:
|
|
136
|
+
raise ValueError("knot_frequencies must match the detector-by-knot shape")
|
|
137
|
+
|
|
138
|
+
factors = jax.vmap(
|
|
139
|
+
jax.vmap(calibration_factor, in_axes=(None, 0, 0, 0)),
|
|
140
|
+
in_axes=(None, None, 0, 0),
|
|
141
|
+
)(frequencies, knots, amplitudes, phases)
|
|
142
|
+
return jnp.median(jnp.real(factors), axis=0) + 1j * jnp.median(jnp.imag(factors), axis=0)
|
|
143
|
+
|
|
144
|
+
|
|
112
145
|
def calibration_log_prior(
|
|
113
146
|
amplitude,
|
|
114
147
|
phase,
|
|
@@ -185,5 +218,6 @@ __all__ = [
|
|
|
185
218
|
"calibration_factor",
|
|
186
219
|
"calibration_log_prior",
|
|
187
220
|
"calibration_parameters_to_unconstrained",
|
|
221
|
+
"posterior_median_calibration_factor",
|
|
188
222
|
"unconstrained_to_calibration_parameters",
|
|
189
223
|
]
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"""Input validation for the per-frequency calibration posterior summary."""
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
import pytest
|
|
5
|
+
|
|
6
|
+
from nullcal.calibration import posterior_median_calibration_factor
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def test_posterior_median_rejects_empty_samples():
|
|
10
|
+
knots = np.geomspace(4.0, 32.0, 4)
|
|
11
|
+
empty = np.empty((0, 1, knots.size))
|
|
12
|
+
|
|
13
|
+
with pytest.raises(ValueError, match="matching nonempty"):
|
|
14
|
+
posterior_median_calibration_factor(knots, knots, empty, empty)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def test_posterior_median_rejects_detector_by_knot_mismatch():
|
|
18
|
+
knots = np.geomspace(4.0, 32.0, 4)
|
|
19
|
+
samples = np.zeros((2, 2, knots.size))
|
|
20
|
+
one_detector_knots = knots[np.newaxis, :]
|
|
21
|
+
|
|
22
|
+
with pytest.raises(ValueError, match="detector-by-knot shape"):
|
|
23
|
+
posterior_median_calibration_factor(knots, one_detector_knots, samples, samples)
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
"""Zero-noise calibration-direction and posterior-summary checks."""
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
import pytest
|
|
5
|
+
|
|
6
|
+
from nullcal.calibration import calibration_factor, posterior_median_calibration_factor
|
|
7
|
+
from nullcal.data import InterferometerData
|
|
8
|
+
from nullcal.likelihood import RecalibrationLikelihood
|
|
9
|
+
from nullcal.likelihood.recalibration_likelihood import ET_BEAM_PATTERN
|
|
10
|
+
from nullcal.null_stream.null_stream import NullStream
|
|
11
|
+
from nullcal.time_frequency_transform.wavelet_transforms import WaveletTransform
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@pytest.mark.parametrize("path", ["likelihood", "null_stream"])
|
|
15
|
+
@pytest.mark.parametrize(
|
|
16
|
+
"correction",
|
|
17
|
+
[
|
|
18
|
+
"truth",
|
|
19
|
+
pytest.param("inverse", marks=pytest.mark.xfail(strict=True, raises=AssertionError)),
|
|
20
|
+
pytest.param("conjugate", marks=pytest.mark.xfail(strict=True, raises=AssertionError)),
|
|
21
|
+
],
|
|
22
|
+
)
|
|
23
|
+
def test_exact_calibration_truth_removes_zero_noise_null_residual(path, correction, monkeypatch):
|
|
24
|
+
frequencies = np.fft.rfftfreq(64, 1.0 / 64.0)
|
|
25
|
+
mask = (frequencies >= 4.0) & (frequencies <= 32.0)
|
|
26
|
+
knots = np.geomspace(4.0, 32.0, 4)
|
|
27
|
+
amplitude = np.array([[0.08, 0.04, -0.03, 0.02], [-0.06, 0.03, 0.05, -0.02], [0.02, -0.04, 0.07, 0.01]])
|
|
28
|
+
phase = np.array([[0.06, -0.03, 0.02, 0.04], [-0.05, 0.02, 0.04, -0.03], [0.03, 0.05, -0.02, 0.01]])
|
|
29
|
+
factors = np.asarray(
|
|
30
|
+
[calibration_factor(frequencies[mask], knots, a, p) for a, p in zip(amplitude, phase, strict=True)]
|
|
31
|
+
)
|
|
32
|
+
waveforms = np.vstack(
|
|
33
|
+
(
|
|
34
|
+
np.exp(0.04j * frequencies[mask]),
|
|
35
|
+
0.7 * np.exp(-0.07j * frequencies[mask]),
|
|
36
|
+
)
|
|
37
|
+
)
|
|
38
|
+
clean_signal = ET_BEAM_PATTERN @ waveforms
|
|
39
|
+
strain = np.zeros((3, frequencies.size), dtype=np.complex128)
|
|
40
|
+
strain[:, mask] = factors * clean_signal
|
|
41
|
+
data = InterferometerData(
|
|
42
|
+
psd=np.ones((3, frequencies.size)),
|
|
43
|
+
strain=strain,
|
|
44
|
+
mask=np.broadcast_to(mask, strain.shape),
|
|
45
|
+
frequency_array=frequencies,
|
|
46
|
+
duration=1.0,
|
|
47
|
+
sampling_frequency=64.0,
|
|
48
|
+
start_time=0.0,
|
|
49
|
+
name=("ET1", "ET2", "ET3"),
|
|
50
|
+
)
|
|
51
|
+
likelihood = RecalibrationLikelihood(
|
|
52
|
+
data,
|
|
53
|
+
knots,
|
|
54
|
+
time_frequency_filter=np.ones((8, 8), dtype=bool),
|
|
55
|
+
wavelet_transform_frequency_resolution=4.0,
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
transform = {"truth": lambda factor: factor, "inverse": lambda factor: 1.0 / factor, "conjugate": np.conj}[
|
|
59
|
+
correction
|
|
60
|
+
]
|
|
61
|
+
if path == "likelihood":
|
|
62
|
+
if correction != "truth":
|
|
63
|
+
original_factor = likelihood._calibration_factor
|
|
64
|
+
monkeypatch.setattr(likelihood, "_calibration_factor", lambda a, p: transform(original_factor(a, p)))
|
|
65
|
+
residual = np.asarray(likelihood._frequency_domain_null_stream(amplitude, phase))[:, mask]
|
|
66
|
+
else:
|
|
67
|
+
null_stream = NullStream(
|
|
68
|
+
data,
|
|
69
|
+
WaveletTransform(duration=1.0, sampling_frequency=64.0, frequency_resolution=4.0, nx=4.0),
|
|
70
|
+
np.ones((8, 8), dtype=bool),
|
|
71
|
+
)
|
|
72
|
+
full_factors = np.zeros_like(strain)
|
|
73
|
+
full_factors[:, mask] = transform(factors)
|
|
74
|
+
residual = np.asarray(null_stream.compute_calibrated_frequency_domain_null_stream(full_factors))[:, mask]
|
|
75
|
+
|
|
76
|
+
relative_residual = np.max(np.abs(residual)) / np.max(np.abs(strain))
|
|
77
|
+
assert relative_residual < 2e-15, f"relative residual {relative_residual:.17g} exceeds 2e-15"
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def test_posterior_median_is_taken_after_evaluating_each_factor():
|
|
81
|
+
frequencies = np.geomspace(4.0, 32.0, 17)
|
|
82
|
+
knots = np.geomspace(4.0, 32.0, 4)
|
|
83
|
+
amplitudes = np.zeros((3, 1, 4))
|
|
84
|
+
amplitudes[0, 0, 0] = 0.12
|
|
85
|
+
amplitudes[1, 0, 1] = 0.12
|
|
86
|
+
amplitudes[2, 0, 2] = 0.12
|
|
87
|
+
phases = np.zeros_like(amplitudes)
|
|
88
|
+
phases[0, 0, 1] = 0.04
|
|
89
|
+
phases[1, 0, 2] = -0.03
|
|
90
|
+
phases[2, 0, 3] = 0.05
|
|
91
|
+
|
|
92
|
+
sample_factors = np.asarray(
|
|
93
|
+
[calibration_factor(frequencies, knots, a[0], p[0]) for a, p in zip(amplitudes, phases, strict=True)]
|
|
94
|
+
)
|
|
95
|
+
expected = np.median(sample_factors.real, axis=0) + 1j * np.median(sample_factors.imag, axis=0)
|
|
96
|
+
actual = np.asarray(posterior_median_calibration_factor(frequencies, knots, amplitudes, phases))
|
|
97
|
+
median_knot_curve = np.asarray(
|
|
98
|
+
calibration_factor(
|
|
99
|
+
frequencies,
|
|
100
|
+
knots,
|
|
101
|
+
np.median(amplitudes[:, 0], axis=0),
|
|
102
|
+
np.median(phases[:, 0], axis=0),
|
|
103
|
+
)
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
np.testing.assert_allclose(actual[0], expected, rtol=0.0, atol=1e-15)
|
|
107
|
+
assert np.max(np.abs(actual[0] - median_knot_curve)) > 1e-3
|
{nullcal-0.2.0 → nullcal-0.2.1}/tests/time_frequency_transform/test_time_domain_transform.py
RENAMED
|
@@ -19,7 +19,10 @@ import numpy as np
|
|
|
19
19
|
import pytest
|
|
20
20
|
|
|
21
21
|
from nullcal.time_frequency_transform import get_shape_of_wavelet_transform, transform_wavelet_freq_time
|
|
22
|
-
from nullcal.time_frequency_transform.inverse_wavelet_time_funcs import
|
|
22
|
+
from nullcal.time_frequency_transform.inverse_wavelet_time_funcs import (
|
|
23
|
+
_compact_packets,
|
|
24
|
+
inverse_wavelet_time_helper_fast,
|
|
25
|
+
)
|
|
23
26
|
from nullcal.time_frequency_transform.transform_time_funcs import phi_vec, transform_wavelet_time_helper
|
|
24
27
|
from nullcal.time_frequency_transform.wavelet_transforms import inverse_wavelet_time, transform_wavelet_time
|
|
25
28
|
|
|
@@ -59,6 +62,18 @@ def noise():
|
|
|
59
62
|
return np.random.default_rng(20260914).normal(size=N_SAMPLES)
|
|
60
63
|
|
|
61
64
|
|
|
65
|
+
@pytest.mark.unit
|
|
66
|
+
def test_compact_packets_preserve_odd_row_sign_for_even_modes():
|
|
67
|
+
"""Odd-row even modes enter the low and mirrored packets with opposite signs."""
|
|
68
|
+
wave = np.zeros((2, 4))
|
|
69
|
+
wave[0, 2] = 5.0
|
|
70
|
+
wave[1, 2] = 2.0
|
|
71
|
+
|
|
72
|
+
packets = np.asarray(_compact_packets(wave, n_f=4, n_t=2))
|
|
73
|
+
|
|
74
|
+
np.testing.assert_array_equal(packets[0, [2, 6]], [3.0, 7.0])
|
|
75
|
+
|
|
76
|
+
|
|
62
77
|
@pytest.mark.unit
|
|
63
78
|
def test_phi_vec_has_the_length_the_kernels_index(shape, phi):
|
|
64
79
|
"""The filter spans ``mult * 2 * n_f`` samples, the window length the kernels loop over.
|