dkist-processing-vbi 2.0.1rc2__tar.gz → 2.1.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.
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/CHANGELOG.rst +49 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/PKG-INFO +64 -61
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi/models/filter.py +1 -1
- dkist_processing_vbi-2.1.1/dkist_processing_vbi/tasks/science.py +298 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi/tests/test_science.py +10 -2
- dkist_processing_vbi-2.1.1/dkist_processing_vbi/workflows/l0_processing.py +98 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi/workflows/summit_data_processing.py +2 -2
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi/workflows/trial_workflows.py +19 -19
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi.egg-info/PKG-INFO +64 -61
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi.egg-info/SOURCES.txt +3 -5
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi.egg-info/requires.txt +63 -60
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi.egg-info/scm_file_list.json +3 -5
- dkist_processing_vbi-2.1.1/dkist_processing_vbi.egg-info/scm_version.json +8 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/docs/index.rst +3 -2
- dkist_processing_vbi-2.1.1/docs/l0_to_l1_vbi.rst +21 -0
- dkist_processing_vbi-2.1.1/docs/l0_to_l1_vbi_bulk.rst +18 -0
- dkist_processing_vbi-2.1.1/docs/l0_to_l1_vbi_full-trial.rst +22 -0
- dkist_processing_vbi-2.1.1/docs/l0_to_l1_vbi_summit-calibrated-full-trial.rst +18 -0
- dkist_processing_vbi-2.1.1/docs/l0_to_l1_vbi_summit-calibrated.rst +19 -0
- dkist_processing_vbi-2.1.1/docs/landing_page.rst +31 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/pyproject.toml +65 -62
- dkist_processing_vbi-2.0.1rc2/changelog/223.misc.1.rst +0 -3
- dkist_processing_vbi-2.0.1rc2/changelog/223.misc.2.rst +0 -3
- dkist_processing_vbi-2.0.1rc2/changelog/223.misc.rst +0 -3
- dkist_processing_vbi-2.0.1rc2/dkist_processing_vbi/tasks/science.py +0 -195
- dkist_processing_vbi-2.0.1rc2/dkist_processing_vbi/workflows/l0_processing.py +0 -74
- dkist_processing_vbi-2.0.1rc2/dkist_processing_vbi.egg-info/scm_version.json +0 -8
- dkist_processing_vbi-2.0.1rc2/docs/l0_to_l1_vbi_no-speckle-full-trial.rst +0 -11
- dkist_processing_vbi-2.0.1rc2/docs/l0_to_l1_vbi_no-speckle.rst +0 -13
- dkist_processing_vbi-2.0.1rc2/docs/l0_to_l1_vbi_summit-calibrated-full-trial.rst +0 -11
- dkist_processing_vbi-2.0.1rc2/docs/l0_to_l1_vbi_summit-calibrated.rst +0 -10
- dkist_processing_vbi-2.0.1rc2/docs/landing_page.rst +0 -18
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/.gitignore +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/.pre-commit-config.yaml +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/.readthedocs.yml +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/.rovodev/.review-agent.md +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/.snyk +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/README.rst +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/SCIENCE_CHANGELOG.rst +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/bitbucket-pipelines.yml +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/changelog/.gitempty +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi/__init__.py +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi/config.py +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi/models/__init__.py +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi/models/burst.py +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi/models/constants.py +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi/models/dataset_extras.py +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi/models/fits_access.py +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi/models/parameters.py +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi/models/tags.py +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi/models/task_name.py +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi/parsers/__init__.py +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi/parsers/burst.py +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi/parsers/mosaic_repeats.py +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi/parsers/spatial_step_pattern.py +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi/parsers/time.py +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi/parsers/vbi_l0_fits_access.py +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi/parsers/vbi_l1_fits_access.py +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi/tasks/__init__.py +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi/tasks/assemble_movie.py +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi/tasks/dark.py +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi/tasks/gain.py +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi/tasks/make_movie_frames.py +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi/tasks/parse.py +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi/tasks/process_summit_processed.py +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi/tasks/quality_metrics.py +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi/tasks/vbi_base.py +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi/tasks/write_dataset_extras.py +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi/tasks/write_l1.py +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi/tests/__init__.py +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi/tests/conftest.py +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi/tests/local_trial_workflows/__init__.py +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi/tests/local_trial_workflows/l0_to_l1.py +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi/tests/test_assemble_movie.py +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi/tests/test_dark.py +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi/tests/test_dataset_extras.py +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi/tests/test_fits_access.py +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi/tests/test_gain.py +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi/tests/test_make_movie_frames.py +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi/tests/test_parse_l0.py +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi/tests/test_parse_summit.py +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi/tests/test_process_summit.py +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi/tests/test_quality_metrics.py +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi/tests/test_spatial_step_pattern.py +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi/tests/test_vbi_base.py +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi/tests/test_vbi_constants.py +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi/tests/test_workflows.py +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi/tests/test_write_l1.py +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi/workflows/__init__.py +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi.egg-info/dependency_links.txt +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi.egg-info/top_level.txt +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/docs/Makefile +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/docs/changelog.rst +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/docs/conf.py +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/docs/dataset_extras.rst +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/docs/make.bat +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/docs/requirements.txt +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/docs/requirements_table.rst +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/docs/scientific_changelog.rst +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/licenses/LICENSE.rst +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/science_towncrier.sh +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/setup.cfg +0 -0
- {dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/towncrier_science.toml +0 -0
|
@@ -1,3 +1,52 @@
|
|
|
1
|
+
v2.1.1 (2026-09-30)
|
|
2
|
+
===================
|
|
3
|
+
|
|
4
|
+
Misc
|
|
5
|
+
----
|
|
6
|
+
|
|
7
|
+
- Update dkist-processing-common to 14.5.2 to restore provenance recording for
|
|
8
|
+
manual parse tasks and trial dataset inventory, ASDF, and quality report tasks. (`#236 <https://bitbucket.org/dkistdc/dkist-processing-vbi/pull-requests/236>`__)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
v2.1.0 (2026-09-28)
|
|
12
|
+
===================
|
|
13
|
+
|
|
14
|
+
Features
|
|
15
|
+
--------
|
|
16
|
+
|
|
17
|
+
- Add the ``l0_to_l1_vbi_bulk`` workflow for bulk processing of L0 data, using the default resource queue for science calibration. (`#233 <https://bitbucket.org/dkistdc/dkist-processing-vbi/pull-requests/233>`__)
|
|
18
|
+
- Enable multi-core parallel science frame calibration in the default VBI pipeline. (`#233 <https://bitbucket.org/dkistdc/dkist-processing-vbi/pull-requests/233>`__)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
Misc
|
|
22
|
+
----
|
|
23
|
+
|
|
24
|
+
- Rename workflows ``l0_to_l1_vbi_no-speckle`` to ``l0_to_l1_vbi`` and ``l0_to_l1_vbi_no-speckle-full-trial`` to ``l0_to_l1_vbi_full-trial``. (`#233 <https://bitbucket.org/dkistdc/dkist-processing-vbi/pull-requests/233>`__)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
v2.0.1 (2026-09-24)
|
|
28
|
+
===================
|
|
29
|
+
|
|
30
|
+
Bugfixes
|
|
31
|
+
--------
|
|
32
|
+
|
|
33
|
+
- Fix the typo in the name for the "VBI-Red Fe XI" filter. (`#235 <https://bitbucket.org/dkistdc/dkist-processing-vbi/pull-requests/235>`__)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
Misc
|
|
37
|
+
----
|
|
38
|
+
|
|
39
|
+
- Use the "level0_spec214" file schema keyword argument in test Datasets.
|
|
40
|
+
With this keyword, subsequent translation of the resulting headers to
|
|
41
|
+
Spec 214 is not necessary. (`#223 <https://bitbucket.org/dkistdc/dkist-processing-vbi/pull-requests/223>`__)
|
|
42
|
+
- Use dkist-fits-specifications v4.29.0, which includes the Trend FITS specification.
|
|
43
|
+
Use dkist-header-validator v6.0.0, a significant refactor that allows multi-HDU objects to be validated.
|
|
44
|
+
Use dkist-processing-common v14.5.0, which accommodates the changes to the header validator. (`#223 <https://bitbucket.org/dkistdc/dkist-processing-vbi/pull-requests/223>`__)
|
|
45
|
+
- Validators no longer have validate-and-translate methods.
|
|
46
|
+
Where still necessary, replace validate-and-translate calls with a call to
|
|
47
|
+
validate and then a call to translate. (`#223 <https://bitbucket.org/dkistdc/dkist-processing-vbi/pull-requests/223>`__)
|
|
48
|
+
|
|
49
|
+
|
|
1
50
|
v2.0.0 (2026-09-03)
|
|
2
51
|
===================
|
|
3
52
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dkist-processing-vbi
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.1.1
|
|
4
4
|
Summary: Processing code for the VBI instrument on DKIST
|
|
5
5
|
Author-email: NSO / AURA <dkistdc@nso.edu>
|
|
6
6
|
License: BSD-3-Clause
|
|
@@ -13,10 +13,10 @@ Classifier: Programming Language :: Python :: 3
|
|
|
13
13
|
Classifier: Programming Language :: Python :: 3.13
|
|
14
14
|
Requires-Python: >=3.13
|
|
15
15
|
Description-Content-Type: text/x-rst
|
|
16
|
-
Requires-Dist: dkist-processing-common==14.5.
|
|
16
|
+
Requires-Dist: dkist-processing-common==14.5.2
|
|
17
17
|
Requires-Dist: dkist-processing-math==2.2.3
|
|
18
|
-
Requires-Dist: dkist-header-validator==6.0.
|
|
19
|
-
Requires-Dist: dkist-fits-specifications==4.29.
|
|
18
|
+
Requires-Dist: dkist-header-validator==6.0.0
|
|
19
|
+
Requires-Dist: dkist-fits-specifications==4.29.0
|
|
20
20
|
Requires-Dist: astropy==7.0.2
|
|
21
21
|
Requires-Dist: numpy==2.2.5
|
|
22
22
|
Requires-Dist: sunpy==6.1.1
|
|
@@ -55,19 +55,19 @@ Requires-Dist: sphinx-autoapi; extra == "docs"
|
|
|
55
55
|
Requires-Dist: pytest; extra == "docs"
|
|
56
56
|
Requires-Dist: dkist-sphinx-theme; extra == "docs"
|
|
57
57
|
Provides-Extra: frozen
|
|
58
|
-
Requires-Dist: Deprecated==
|
|
59
|
-
Requires-Dist: ImageIO==2.
|
|
58
|
+
Requires-Dist: Deprecated==3.0.0; extra == "frozen"
|
|
59
|
+
Requires-Dist: ImageIO==2.38.0; extra == "frozen"
|
|
60
60
|
Requires-Dist: Jinja2==3.1.6; extra == "frozen"
|
|
61
61
|
Requires-Dist: Mako==1.4.3; extra == "frozen"
|
|
62
62
|
Requires-Dist: MarkupSafe==3.0.3; extra == "frozen"
|
|
63
63
|
Requires-Dist: PIMS==0.7; extra == "frozen"
|
|
64
64
|
Requires-Dist: PeakUtils==1.3.5; extra == "frozen"
|
|
65
65
|
Requires-Dist: PyAVM==0.9.9; extra == "frozen"
|
|
66
|
-
Requires-Dist: PyJWT==2.15.
|
|
66
|
+
Requires-Dist: PyJWT==2.15.1; extra == "frozen"
|
|
67
67
|
Requires-Dist: PyYAML==6.0.3; extra == "frozen"
|
|
68
68
|
Requires-Dist: PyYAML-ft==8.0.0; extra == "frozen"
|
|
69
69
|
Requires-Dist: Pygments==2.21.0; extra == "frozen"
|
|
70
|
-
Requires-Dist: SQLAlchemy==2.
|
|
70
|
+
Requires-Dist: SQLAlchemy==2.1.1; extra == "frozen"
|
|
71
71
|
Requires-Dist: Send2Trash==2.1.0; extra == "frozen"
|
|
72
72
|
Requires-Dist: a2wsgi==1.10.10; extra == "frozen"
|
|
73
73
|
Requires-Dist: aioftp==0.28.3; extra == "frozen"
|
|
@@ -83,14 +83,15 @@ Requires-Dist: annotated-types==0.8.0; extra == "frozen"
|
|
|
83
83
|
Requires-Dist: anyio==4.15.1; extra == "frozen"
|
|
84
84
|
Requires-Dist: apache-airflow==3.3.1; extra == "frozen"
|
|
85
85
|
Requires-Dist: apache-airflow-core==3.3.1; extra == "frozen"
|
|
86
|
-
Requires-Dist: apache-airflow-providers-celery==3.24.
|
|
87
|
-
Requires-Dist: apache-airflow-providers-common-compat==1.
|
|
88
|
-
Requires-Dist: apache-airflow-providers-common-io==1.
|
|
89
|
-
Requires-Dist: apache-airflow-providers-common-sql==2.
|
|
90
|
-
Requires-Dist: apache-airflow-providers-postgres==7.0
|
|
91
|
-
Requires-Dist: apache-airflow-providers-smtp==3.0
|
|
92
|
-
Requires-Dist: apache-airflow-providers-standard==1.
|
|
86
|
+
Requires-Dist: apache-airflow-providers-celery==3.24.1; extra == "frozen"
|
|
87
|
+
Requires-Dist: apache-airflow-providers-common-compat==1.20.0; extra == "frozen"
|
|
88
|
+
Requires-Dist: apache-airflow-providers-common-io==1.10.0; extra == "frozen"
|
|
89
|
+
Requires-Dist: apache-airflow-providers-common-sql==2.2.0; extra == "frozen"
|
|
90
|
+
Requires-Dist: apache-airflow-providers-postgres==7.1.0; extra == "frozen"
|
|
91
|
+
Requires-Dist: apache-airflow-providers-smtp==3.1.0; extra == "frozen"
|
|
92
|
+
Requires-Dist: apache-airflow-providers-standard==1.20.0; extra == "frozen"
|
|
93
93
|
Requires-Dist: apache-airflow-task-sdk==1.3.1; extra == "frozen"
|
|
94
|
+
Requires-Dist: appnope==1.0.0; extra == "frozen"
|
|
94
95
|
Requires-Dist: argcomplete==3.7.2; extra == "frozen"
|
|
95
96
|
Requires-Dist: argon2-cffi==25.1.0; extra == "frozen"
|
|
96
97
|
Requires-Dist: argon2-cffi-bindings==26.1.0; extra == "frozen"
|
|
@@ -100,7 +101,7 @@ Requires-Dist: asdf_standard==1.5.0; extra == "frozen"
|
|
|
100
101
|
Requires-Dist: asgiref==3.12.1; extra == "frozen"
|
|
101
102
|
Requires-Dist: asteval==1.0.10; extra == "frozen"
|
|
102
103
|
Requires-Dist: astropy==7.0.2; extra == "frozen"
|
|
103
|
-
Requires-Dist: astropy-iers-data==0.2026.9.
|
|
104
|
+
Requires-Dist: astropy-iers-data==0.2026.9.28.0.59.37; extra == "frozen"
|
|
104
105
|
Requires-Dist: astropy_healpix==2.0.1; extra == "frozen"
|
|
105
106
|
Requires-Dist: asttokens==3.0.2; extra == "frozen"
|
|
106
107
|
Requires-Dist: async-lru==2.3.0; extra == "frozen"
|
|
@@ -110,14 +111,14 @@ Requires-Dist: babel==2.18.0; extra == "frozen"
|
|
|
110
111
|
Requires-Dist: beautifulsoup4==4.15.0; extra == "frozen"
|
|
111
112
|
Requires-Dist: billiard==4.3.0; extra == "frozen"
|
|
112
113
|
Requires-Dist: bleach==6.4.0; extra == "frozen"
|
|
113
|
-
Requires-Dist: boto3==1.43.
|
|
114
|
-
Requires-Dist: botocore==1.43.
|
|
114
|
+
Requires-Dist: boto3==1.43.106; extra == "frozen"
|
|
115
|
+
Requires-Dist: botocore==1.43.106; extra == "frozen"
|
|
115
116
|
Requires-Dist: cachetools==7.2.0; extra == "frozen"
|
|
116
117
|
Requires-Dist: cadwyn==7.0.0; extra == "frozen"
|
|
117
118
|
Requires-Dist: celery==5.6.3; extra == "frozen"
|
|
118
119
|
Requires-Dist: certifi==2026.7.22; extra == "frozen"
|
|
119
120
|
Requires-Dist: cffi==2.1.1; extra == "frozen"
|
|
120
|
-
Requires-Dist: charset-normalizer==3.5.
|
|
121
|
+
Requires-Dist: charset-normalizer==3.5.2; extra == "frozen"
|
|
121
122
|
Requires-Dist: click==8.5.0; extra == "frozen"
|
|
122
123
|
Requires-Dist: click-didyoumean==0.3.1; extra == "frozen"
|
|
123
124
|
Requires-Dist: click-plugins==1.1.1.2; extra == "frozen"
|
|
@@ -126,9 +127,9 @@ Requires-Dist: cloudpickle==3.1.2; extra == "frozen"
|
|
|
126
127
|
Requires-Dist: colorlog==6.12.0; extra == "frozen"
|
|
127
128
|
Requires-Dist: comm==0.2.3; extra == "frozen"
|
|
128
129
|
Requires-Dist: contourpy==1.4.0; extra == "frozen"
|
|
129
|
-
Requires-Dist: cron_descriptor==2.1.
|
|
130
|
+
Requires-Dist: cron_descriptor==2.1.1; extra == "frozen"
|
|
130
131
|
Requires-Dist: croniter==6.2.4; extra == "frozen"
|
|
131
|
-
Requires-Dist: cryptography==50.0.
|
|
132
|
+
Requires-Dist: cryptography==50.0.2; extra == "frozen"
|
|
132
133
|
Requires-Dist: cycler==0.12.1; extra == "frozen"
|
|
133
134
|
Requires-Dist: dask==2026.8.0; extra == "frozen"
|
|
134
135
|
Requires-Dist: dask-image==2026.5.0; extra == "frozen"
|
|
@@ -136,15 +137,15 @@ Requires-Dist: debugpy==1.8.22; extra == "frozen"
|
|
|
136
137
|
Requires-Dist: decorator==5.3.1; extra == "frozen"
|
|
137
138
|
Requires-Dist: defusedxml==0.7.1; extra == "frozen"
|
|
138
139
|
Requires-Dist: dill==0.4.1; extra == "frozen"
|
|
139
|
-
Requires-Dist: dkist-header-validator==6.0.
|
|
140
|
-
Requires-Dist: dkist-processing-common==14.5.
|
|
140
|
+
Requires-Dist: dkist-header-validator==6.0.0; extra == "frozen"
|
|
141
|
+
Requires-Dist: dkist-processing-common==14.5.2; extra == "frozen"
|
|
141
142
|
Requires-Dist: dkist-processing-core==7.5.0; extra == "frozen"
|
|
142
143
|
Requires-Dist: dkist-processing-math==2.2.3; extra == "frozen"
|
|
143
144
|
Requires-Dist: dkist-processing-pac==3.1.2; extra == "frozen"
|
|
144
|
-
Requires-Dist: dkist-processing-vbi==2.
|
|
145
|
+
Requires-Dist: dkist-processing-vbi==2.1.1; extra == "frozen"
|
|
145
146
|
Requires-Dist: dkist-service-configuration==4.3.0; extra == "frozen"
|
|
146
147
|
Requires-Dist: dkist-spectral-lines==3.0.1; extra == "frozen"
|
|
147
|
-
Requires-Dist: dkist_fits_specifications==4.29.
|
|
148
|
+
Requires-Dist: dkist_fits_specifications==4.29.0; extra == "frozen"
|
|
148
149
|
Requires-Dist: dnspython==2.8.0; extra == "frozen"
|
|
149
150
|
Requires-Dist: donfig==0.8.1.post1; extra == "frozen"
|
|
150
151
|
Requires-Dist: email-validator==2.3.0; extra == "frozen"
|
|
@@ -153,13 +154,13 @@ Requires-Dist: fastapi==0.136.3; extra == "frozen"
|
|
|
153
154
|
Requires-Dist: fastapi-cli==0.0.32; extra == "frozen"
|
|
154
155
|
Requires-Dist: fastjsonschema==2.22.2; extra == "frozen"
|
|
155
156
|
Requires-Dist: flower==2.2.0; extra == "frozen"
|
|
156
|
-
Requires-Dist: fonttools==4.66.
|
|
157
|
-
Requires-Dist: fqdn==1.
|
|
157
|
+
Requires-Dist: fonttools==4.66.1; extra == "frozen"
|
|
158
|
+
Requires-Dist: fqdn==1.6.0; extra == "frozen"
|
|
158
159
|
Requires-Dist: frozenlist==1.8.0; extra == "frozen"
|
|
159
160
|
Requires-Dist: fsspec==2026.9.0; extra == "frozen"
|
|
160
|
-
Requires-Dist: globus-sdk==4.9.
|
|
161
|
-
Requires-Dist: google-crc32c==1.
|
|
162
|
-
Requires-Dist: googleapis-common-protos==1.75.
|
|
161
|
+
Requires-Dist: globus-sdk==4.9.1; extra == "frozen"
|
|
162
|
+
Requires-Dist: google-crc32c==1.9.0; extra == "frozen"
|
|
163
|
+
Requires-Dist: googleapis-common-protos==1.75.5; extra == "frozen"
|
|
163
164
|
Requires-Dist: gqlclient==2.0.0; extra == "frozen"
|
|
164
165
|
Requires-Dist: greenback==1.3.0; extra == "frozen"
|
|
165
166
|
Requires-Dist: greenlet==3.5.6; extra == "frozen"
|
|
@@ -172,7 +173,7 @@ Requires-Dist: humanize==4.16.0; extra == "frozen"
|
|
|
172
173
|
Requires-Dist: idna==3.20; extra == "frozen"
|
|
173
174
|
Requires-Dist: imageio-ffmpeg==0.6.0; extra == "frozen"
|
|
174
175
|
Requires-Dist: importlib_metadata==9.0.1; extra == "frozen"
|
|
175
|
-
Requires-Dist: ipykernel==7.
|
|
176
|
+
Requires-Dist: ipykernel==7.4.0; extra == "frozen"
|
|
176
177
|
Requires-Dist: ipython==9.17.1; extra == "frozen"
|
|
177
178
|
Requires-Dist: ipython_pygments_lexers==1.1.1; extra == "frozen"
|
|
178
179
|
Requires-Dist: isoduration==20.11.0; extra == "frozen"
|
|
@@ -212,7 +213,7 @@ Requires-Dist: methodtools==0.4.7; extra == "frozen"
|
|
|
212
213
|
Requires-Dist: mistune==3.3.4; extra == "frozen"
|
|
213
214
|
Requires-Dist: more-itertools==11.1.0; extra == "frozen"
|
|
214
215
|
Requires-Dist: moviepy==2.2.1; extra == "frozen"
|
|
215
|
-
Requires-Dist: msgspec==0.
|
|
216
|
+
Requires-Dist: msgspec==0.22.0; extra == "frozen"
|
|
216
217
|
Requires-Dist: multidict==6.9.1; extra == "frozen"
|
|
217
218
|
Requires-Dist: natsort==8.4.0; extra == "frozen"
|
|
218
219
|
Requires-Dist: nbclient==0.11.0; extra == "frozen"
|
|
@@ -225,30 +226,32 @@ Requires-Dist: notebook_shim==0.2.4; extra == "frozen"
|
|
|
225
226
|
Requires-Dist: numcodecs==0.17.0; extra == "frozen"
|
|
226
227
|
Requires-Dist: numpy==2.2.5; extra == "frozen"
|
|
227
228
|
Requires-Dist: object-clerk==1.0.0; extra == "frozen"
|
|
228
|
-
Requires-Dist: opentelemetry-api==1.
|
|
229
|
-
Requires-Dist: opentelemetry-exporter-
|
|
230
|
-
Requires-Dist: opentelemetry-exporter-otlp
|
|
231
|
-
Requires-Dist: opentelemetry-exporter-otlp-
|
|
232
|
-
Requires-Dist: opentelemetry-exporter-otlp-proto-
|
|
233
|
-
Requires-Dist: opentelemetry-
|
|
234
|
-
Requires-Dist: opentelemetry-
|
|
235
|
-
Requires-Dist: opentelemetry-instrumentation
|
|
236
|
-
Requires-Dist: opentelemetry-instrumentation-
|
|
237
|
-
Requires-Dist: opentelemetry-instrumentation-
|
|
238
|
-
Requires-Dist: opentelemetry-instrumentation-
|
|
239
|
-
Requires-Dist: opentelemetry-instrumentation-
|
|
240
|
-
Requires-Dist: opentelemetry-instrumentation-
|
|
241
|
-
Requires-Dist: opentelemetry-instrumentation-
|
|
242
|
-
Requires-Dist: opentelemetry-instrumentation-
|
|
243
|
-
Requires-Dist: opentelemetry-instrumentation-
|
|
244
|
-
Requires-Dist: opentelemetry-instrumentation-
|
|
245
|
-
Requires-Dist: opentelemetry-instrumentation-
|
|
246
|
-
Requires-Dist: opentelemetry-instrumentation-
|
|
229
|
+
Requires-Dist: opentelemetry-api==1.45.0; extra == "frozen"
|
|
230
|
+
Requires-Dist: opentelemetry-exporter-http-transport==0.66b0; extra == "frozen"
|
|
231
|
+
Requires-Dist: opentelemetry-exporter-otlp==1.45.0; extra == "frozen"
|
|
232
|
+
Requires-Dist: opentelemetry-exporter-otlp-common==0.66b0; extra == "frozen"
|
|
233
|
+
Requires-Dist: opentelemetry-exporter-otlp-proto-common==1.45.0; extra == "frozen"
|
|
234
|
+
Requires-Dist: opentelemetry-exporter-otlp-proto-grpc==1.45.0; extra == "frozen"
|
|
235
|
+
Requires-Dist: opentelemetry-exporter-otlp-proto-http==1.45.0; extra == "frozen"
|
|
236
|
+
Requires-Dist: opentelemetry-instrumentation==0.66b0; extra == "frozen"
|
|
237
|
+
Requires-Dist: opentelemetry-instrumentation-aiohttp-client==0.66b0; extra == "frozen"
|
|
238
|
+
Requires-Dist: opentelemetry-instrumentation-asgi==0.66b0; extra == "frozen"
|
|
239
|
+
Requires-Dist: opentelemetry-instrumentation-botocore==0.66b0; extra == "frozen"
|
|
240
|
+
Requires-Dist: opentelemetry-instrumentation-celery==0.66b0; extra == "frozen"
|
|
241
|
+
Requires-Dist: opentelemetry-instrumentation-dbapi==0.66b0; extra == "frozen"
|
|
242
|
+
Requires-Dist: opentelemetry-instrumentation-fastapi==0.66b0; extra == "frozen"
|
|
243
|
+
Requires-Dist: opentelemetry-instrumentation-pika==0.66b0; extra == "frozen"
|
|
244
|
+
Requires-Dist: opentelemetry-instrumentation-psycopg2==0.66b0; extra == "frozen"
|
|
245
|
+
Requires-Dist: opentelemetry-instrumentation-pymongo==0.66b0; extra == "frozen"
|
|
246
|
+
Requires-Dist: opentelemetry-instrumentation-redis==0.66b0; extra == "frozen"
|
|
247
|
+
Requires-Dist: opentelemetry-instrumentation-requests==0.66b0; extra == "frozen"
|
|
248
|
+
Requires-Dist: opentelemetry-instrumentation-sqlalchemy==0.66b0; extra == "frozen"
|
|
249
|
+
Requires-Dist: opentelemetry-instrumentation-system-metrics==0.66b0; extra == "frozen"
|
|
247
250
|
Requires-Dist: opentelemetry-propagator-aws-xray==1.0.2; extra == "frozen"
|
|
248
|
-
Requires-Dist: opentelemetry-proto==1.
|
|
249
|
-
Requires-Dist: opentelemetry-sdk==1.
|
|
250
|
-
Requires-Dist: opentelemetry-semantic-conventions==0.
|
|
251
|
-
Requires-Dist: opentelemetry-util-http==0.
|
|
251
|
+
Requires-Dist: opentelemetry-proto==1.45.0; extra == "frozen"
|
|
252
|
+
Requires-Dist: opentelemetry-sdk==1.45.0; extra == "frozen"
|
|
253
|
+
Requires-Dist: opentelemetry-semantic-conventions==0.66b0; extra == "frozen"
|
|
254
|
+
Requires-Dist: opentelemetry-util-http==0.66b0; extra == "frozen"
|
|
252
255
|
Requires-Dist: outcome==1.3.0.post0; extra == "frozen"
|
|
253
256
|
Requires-Dist: packaging==26.3; extra == "frozen"
|
|
254
257
|
Requires-Dist: pandas==3.0.6; extra == "frozen"
|
|
@@ -263,7 +266,7 @@ Requires-Dist: pexpect==4.9.0; extra == "frozen"
|
|
|
263
266
|
Requires-Dist: pika==1.4.4; extra == "frozen"
|
|
264
267
|
Requires-Dist: pillow==10.4.0; extra == "frozen"
|
|
265
268
|
Requires-Dist: pip==26.2.1; extra == "frozen"
|
|
266
|
-
Requires-Dist: platformdirs==4.
|
|
269
|
+
Requires-Dist: platformdirs==4.12.2; extra == "frozen"
|
|
267
270
|
Requires-Dist: pluggy==1.6.0; extra == "frozen"
|
|
268
271
|
Requires-Dist: pooch==1.9.0; extra == "frozen"
|
|
269
272
|
Requires-Dist: proglog==0.1.12; extra == "frozen"
|
|
@@ -290,8 +293,8 @@ Requires-Dist: python-dateutil==2.9.0.post0; extra == "frozen"
|
|
|
290
293
|
Requires-Dist: python-dotenv==1.2.3; extra == "frozen"
|
|
291
294
|
Requires-Dist: python-json-logger==4.2.0; extra == "frozen"
|
|
292
295
|
Requires-Dist: python-multipart==0.0.32; extra == "frozen"
|
|
293
|
-
Requires-Dist: python-slugify==9.1.
|
|
294
|
-
Requires-Dist: pytz==2026.
|
|
296
|
+
Requires-Dist: python-slugify==9.1.2; extra == "frozen"
|
|
297
|
+
Requires-Dist: pytz==2026.4; extra == "frozen"
|
|
295
298
|
Requires-Dist: pyzmq==27.2.0; extra == "frozen"
|
|
296
299
|
Requires-Dist: redis==6.4.0; extra == "frozen"
|
|
297
300
|
Requires-Dist: referencing==0.37.0; extra == "frozen"
|
|
@@ -314,7 +317,7 @@ Requires-Dist: six==1.17.0; extra == "frozen"
|
|
|
314
317
|
Requires-Dist: slicerator==1.1.0; extra == "frozen"
|
|
315
318
|
Requires-Dist: sniffio==1.3.1; extra == "frozen"
|
|
316
319
|
Requires-Dist: solar-wavelength-calibration==2.0.3; extra == "frozen"
|
|
317
|
-
Requires-Dist: soupsieve==2.
|
|
320
|
+
Requires-Dist: soupsieve==2.10; extra == "frozen"
|
|
318
321
|
Requires-Dist: sqids==0.5.1; extra == "frozen"
|
|
319
322
|
Requires-Dist: sqlparse==0.6.0; extra == "frozen"
|
|
320
323
|
Requires-Dist: stack-data==0.6.3; extra == "frozen"
|
|
@@ -344,7 +347,7 @@ Requires-Dist: universal_pathlib==0.3.10; extra == "frozen"
|
|
|
344
347
|
Requires-Dist: uri-template==1.3.0; extra == "frozen"
|
|
345
348
|
Requires-Dist: urllib3==2.8.0; extra == "frozen"
|
|
346
349
|
Requires-Dist: uuid6==2025.0.1; extra == "frozen"
|
|
347
|
-
Requires-Dist: uvicorn==0.
|
|
350
|
+
Requires-Dist: uvicorn==0.54.0; extra == "frozen"
|
|
348
351
|
Requires-Dist: uvloop==0.22.1; extra == "frozen"
|
|
349
352
|
Requires-Dist: vine==5.1.0; extra == "frozen"
|
|
350
353
|
Requires-Dist: voluptuous==0.16.0; extra == "frozen"
|
|
@@ -355,7 +358,7 @@ Requires-Dist: webencodings==0.6.1; extra == "frozen"
|
|
|
355
358
|
Requires-Dist: websocket-client==1.9.2; extra == "frozen"
|
|
356
359
|
Requires-Dist: websockets==17.1; extra == "frozen"
|
|
357
360
|
Requires-Dist: wirerope==1.0.0; extra == "frozen"
|
|
358
|
-
Requires-Dist: wrapt==2.
|
|
361
|
+
Requires-Dist: wrapt==2.5.0; extra == "frozen"
|
|
359
362
|
Requires-Dist: yamale==6.1.0; extra == "frozen"
|
|
360
363
|
Requires-Dist: yarl==1.25.1; extra == "frozen"
|
|
361
364
|
Requires-Dist: zarr==3.4.0; extra == "frozen"
|
{dkist_processing_vbi-2.0.1rc2 → dkist_processing_vbi-2.1.1}/dkist_processing_vbi/models/filter.py
RENAMED
|
@@ -25,7 +25,7 @@ VBI_FILTERS = [
|
|
|
25
25
|
Filter(name="VBI-Red H-alpha", min=656.258 * u.nm, max=656.306 * u.nm),
|
|
26
26
|
Filter(name="VBI-Red Continuum", min=668.202 * u.nm, max=668.644 * u.nm),
|
|
27
27
|
Filter(name="VBI-Red Ti O", min=705.545 * u.nm, max=706.133 * u.nm),
|
|
28
|
-
Filter(name="VBI-Red Fe
|
|
28
|
+
Filter(name="VBI-Red Fe XI", min=789.168 * u.nm, max=789.204 * u.nm),
|
|
29
29
|
]
|
|
30
30
|
|
|
31
31
|
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
"""VBI science task."""
|
|
2
|
+
|
|
3
|
+
from concurrent.futures import FIRST_COMPLETED
|
|
4
|
+
from concurrent.futures import ProcessPoolExecutor
|
|
5
|
+
from concurrent.futures import wait
|
|
6
|
+
from functools import lru_cache
|
|
7
|
+
from functools import partial
|
|
8
|
+
from itertools import islice
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
|
|
11
|
+
import numpy as np
|
|
12
|
+
from astropy.io import fits
|
|
13
|
+
from dkist_processing_common.codecs.fits import fits_access_decoder
|
|
14
|
+
from dkist_processing_common.codecs.fits import fits_array_decoder
|
|
15
|
+
from dkist_processing_common.codecs.fits import fits_hdulist_encoder
|
|
16
|
+
from dkist_processing_common.models.task_name import TaskName
|
|
17
|
+
from dkist_processing_common.tasks.mixin.quality import QualityMixin
|
|
18
|
+
from dkist_processing_math.arithmetic import divide_fits_access_by_array
|
|
19
|
+
from dkist_processing_math.arithmetic import subtract_array_from_fits_access
|
|
20
|
+
from dkist_service_configuration.logging import logger
|
|
21
|
+
|
|
22
|
+
from dkist_processing_vbi.config import dkist_processing_vbi_configurations
|
|
23
|
+
from dkist_processing_vbi.models.tags import VbiTag
|
|
24
|
+
from dkist_processing_vbi.parsers.vbi_l0_fits_access import VbiL0FitsAccess
|
|
25
|
+
from dkist_processing_vbi.tasks.vbi_base import VbiTaskBase
|
|
26
|
+
|
|
27
|
+
__all__ = ["ScienceCalibration"]
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
# One entry per calibration type (dark, gain, bad-pixel map).
|
|
31
|
+
@lru_cache(maxsize=3)
|
|
32
|
+
def _mmap_calibration_array(path: Path) -> np.ndarray:
|
|
33
|
+
"""Memory-map and cache a calibration array in the current worker process."""
|
|
34
|
+
array = fits_array_decoder(
|
|
35
|
+
path,
|
|
36
|
+
auto_squeeze=False,
|
|
37
|
+
checksum=False,
|
|
38
|
+
memmap=True,
|
|
39
|
+
)
|
|
40
|
+
array.flags.writeable = False
|
|
41
|
+
return array
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def _decode_calibration_file(path: Path) -> None:
|
|
45
|
+
"""Decode a calibration FITS file with checksum checking and discard the array."""
|
|
46
|
+
array = fits_array_decoder(
|
|
47
|
+
path,
|
|
48
|
+
auto_squeeze=False,
|
|
49
|
+
checksum=True,
|
|
50
|
+
memmap=True,
|
|
51
|
+
)
|
|
52
|
+
del array
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
class ScienceCalibration(VbiTaskBase, QualityMixin):
|
|
56
|
+
"""
|
|
57
|
+
Task class for running full science calibration on a set of observe images.
|
|
58
|
+
|
|
59
|
+
Parameters
|
|
60
|
+
----------
|
|
61
|
+
recipe_run_id : int
|
|
62
|
+
id of the recipe run used to identify the workflow run this task is part of
|
|
63
|
+
workflow_name : str
|
|
64
|
+
name of the workflow to which this instance of the task belongs
|
|
65
|
+
workflow_version : str
|
|
66
|
+
version of the workflow to which this instance of the task belongs
|
|
67
|
+
"""
|
|
68
|
+
|
|
69
|
+
record_provenance = True
|
|
70
|
+
|
|
71
|
+
@staticmethod
|
|
72
|
+
def correct_bad_pixels(
|
|
73
|
+
image: np.ndarray,
|
|
74
|
+
bad_pixel_map: np.ndarray,
|
|
75
|
+
neighborhood_radius: int,
|
|
76
|
+
) -> np.ndarray:
|
|
77
|
+
"""Replace bad pixels with a masked neighborhood median."""
|
|
78
|
+
bad_pixel_map = np.squeeze(bad_pixel_map).astype(bool)
|
|
79
|
+
|
|
80
|
+
corrected_image = image.copy()
|
|
81
|
+
bad_rows, bad_columns = np.where(bad_pixel_map)
|
|
82
|
+
source_plane = image[0]
|
|
83
|
+
corrected_plane = corrected_image[0]
|
|
84
|
+
masked_source_plane = np.ma.masked_array(
|
|
85
|
+
source_plane,
|
|
86
|
+
mask=bad_pixel_map,
|
|
87
|
+
)
|
|
88
|
+
for row, column in zip(bad_rows, bad_columns, strict=True):
|
|
89
|
+
row_slice = slice(
|
|
90
|
+
max(0, row - neighborhood_radius),
|
|
91
|
+
min(source_plane.shape[0], row + neighborhood_radius + 1),
|
|
92
|
+
)
|
|
93
|
+
column_slice = slice(
|
|
94
|
+
max(0, column - neighborhood_radius),
|
|
95
|
+
min(source_plane.shape[1], column + neighborhood_radius + 1),
|
|
96
|
+
)
|
|
97
|
+
corrected_plane[row, column] = np.ma.median(
|
|
98
|
+
masked_source_plane[row_slice, column_slice]
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
return corrected_image
|
|
102
|
+
|
|
103
|
+
@staticmethod
|
|
104
|
+
def calibrate_science_frame(
|
|
105
|
+
science_access: VbiL0FitsAccess,
|
|
106
|
+
dark_calibration_array: np.ndarray,
|
|
107
|
+
gain_calibration_array: np.ndarray,
|
|
108
|
+
bad_pixel_map: np.ndarray,
|
|
109
|
+
bad_pixel_neighborhood_radius: int,
|
|
110
|
+
) -> VbiL0FitsAccess:
|
|
111
|
+
"""Calibrate one decoded science frame in a worker process."""
|
|
112
|
+
science_access = next(
|
|
113
|
+
subtract_array_from_fits_access(
|
|
114
|
+
access_objs=science_access,
|
|
115
|
+
array_to_subtract=dark_calibration_array,
|
|
116
|
+
)
|
|
117
|
+
)
|
|
118
|
+
science_access = next(
|
|
119
|
+
divide_fits_access_by_array(
|
|
120
|
+
access_objs=science_access,
|
|
121
|
+
array_to_divide_by=gain_calibration_array,
|
|
122
|
+
)
|
|
123
|
+
)
|
|
124
|
+
science_access.data = ScienceCalibration.correct_bad_pixels(
|
|
125
|
+
image=science_access.data,
|
|
126
|
+
bad_pixel_map=bad_pixel_map,
|
|
127
|
+
neighborhood_radius=bad_pixel_neighborhood_radius,
|
|
128
|
+
)
|
|
129
|
+
return science_access
|
|
130
|
+
|
|
131
|
+
@staticmethod
|
|
132
|
+
def encode_calibrated_science_frame(
|
|
133
|
+
science_access: VbiL0FitsAccess,
|
|
134
|
+
mosaic: int,
|
|
135
|
+
num_mosaic_repeats: int,
|
|
136
|
+
) -> bytes:
|
|
137
|
+
"""Encode one calibrated science frame as compressed FITS bytes."""
|
|
138
|
+
# Run the header through an `ImageHDU` to strip out any `PrimaryHDU`-only keys. This is to get around an
|
|
139
|
+
# `astropy` bug (since 7.0) that produces bad headers if a `CompImageHDU` is populated with a header
|
|
140
|
+
# from a `PrimaryHDU`.
|
|
141
|
+
cleaned_header = fits.ImageHDU(header=science_access.header).header
|
|
142
|
+
processed_hdu_list = fits.HDUList(
|
|
143
|
+
[fits.PrimaryHDU(), fits.CompImageHDU(data=science_access.data, header=cleaned_header)]
|
|
144
|
+
)
|
|
145
|
+
processed_hdu_list[1].header["VBINMOSC"] = num_mosaic_repeats
|
|
146
|
+
processed_hdu_list[1].header["VBICMOSC"] = mosaic
|
|
147
|
+
|
|
148
|
+
return fits_hdulist_encoder(processed_hdu_list)
|
|
149
|
+
|
|
150
|
+
@staticmethod
|
|
151
|
+
def calibrate_and_encode_science_frame(
|
|
152
|
+
science_path: Path,
|
|
153
|
+
dark_calibration_path: Path,
|
|
154
|
+
gain_calibration_path: Path,
|
|
155
|
+
bad_pixel_map_path: Path,
|
|
156
|
+
bad_pixel_neighborhood_radius: int,
|
|
157
|
+
mosaic: int,
|
|
158
|
+
num_mosaic_repeats: int,
|
|
159
|
+
) -> tuple[bytes, int]:
|
|
160
|
+
"""Decode, calibrate, and FITS-encode one science frame, returning bytes and its exposure number."""
|
|
161
|
+
fits_obj = fits_access_decoder(
|
|
162
|
+
science_path,
|
|
163
|
+
fits_access_class=VbiL0FitsAccess,
|
|
164
|
+
auto_squeeze=False,
|
|
165
|
+
)
|
|
166
|
+
fits_obj = ScienceCalibration.calibrate_science_frame(
|
|
167
|
+
science_access=fits_obj,
|
|
168
|
+
dark_calibration_array=_mmap_calibration_array(dark_calibration_path),
|
|
169
|
+
gain_calibration_array=_mmap_calibration_array(gain_calibration_path),
|
|
170
|
+
bad_pixel_map=_mmap_calibration_array(bad_pixel_map_path),
|
|
171
|
+
bad_pixel_neighborhood_radius=bad_pixel_neighborhood_radius,
|
|
172
|
+
)
|
|
173
|
+
encoded_frame = ScienceCalibration.encode_calibrated_science_frame(
|
|
174
|
+
science_access=fits_obj,
|
|
175
|
+
mosaic=mosaic,
|
|
176
|
+
num_mosaic_repeats=num_mosaic_repeats,
|
|
177
|
+
)
|
|
178
|
+
return encoded_frame, fits_obj.current_mosaic_step_exp
|
|
179
|
+
|
|
180
|
+
def run(self) -> None:
|
|
181
|
+
"""
|
|
182
|
+
Perform science calibrations.
|
|
183
|
+
|
|
184
|
+
- Do initial array corrections (dark, gain, bad pixels)
|
|
185
|
+
- Write out L1 science frames
|
|
186
|
+
- Record quality metrics
|
|
187
|
+
|
|
188
|
+
Returns
|
|
189
|
+
-------
|
|
190
|
+
None
|
|
191
|
+
|
|
192
|
+
"""
|
|
193
|
+
logger.info(
|
|
194
|
+
f"Starting science with {self.constants.num_spatial_steps} steps and {self.constants.num_mosaic_repeats} mosaic repeats"
|
|
195
|
+
)
|
|
196
|
+
worker_count = dkist_processing_vbi_configurations.cpu_count
|
|
197
|
+
logger.info(f"Calibrating science frames with {worker_count} worker processes")
|
|
198
|
+
with (
|
|
199
|
+
self.telemetry_span(
|
|
200
|
+
f"Reducing science frames from {self.constants.num_spatial_steps} steps and {self.constants.num_mosaic_repeats} mosaic repeats",
|
|
201
|
+
),
|
|
202
|
+
ProcessPoolExecutor(max_workers=worker_count) as executor,
|
|
203
|
+
):
|
|
204
|
+
for step in range(1, self.constants.num_spatial_steps + 1):
|
|
205
|
+
logger.info(f"retrieving gain calibration for step {step}")
|
|
206
|
+
gain_tags = [
|
|
207
|
+
VbiTag.intermediate(),
|
|
208
|
+
VbiTag.task_gain_frame(spatial_step=step),
|
|
209
|
+
]
|
|
210
|
+
gain_calibration_path = next(self.read(tags=gain_tags))
|
|
211
|
+
_decode_calibration_file(gain_calibration_path)
|
|
212
|
+
|
|
213
|
+
logger.info(f"retrieving bad pixel map for step {step}")
|
|
214
|
+
bad_pixel_map_tags = [
|
|
215
|
+
VbiTag.intermediate(),
|
|
216
|
+
VbiTag.bad_pixel_map(spatial_step=step),
|
|
217
|
+
]
|
|
218
|
+
bad_pixel_map_path = next(self.read(tags=bad_pixel_map_tags))
|
|
219
|
+
_decode_calibration_file(bad_pixel_map_path)
|
|
220
|
+
|
|
221
|
+
for exp_time in self.constants.observe_exposure_times:
|
|
222
|
+
logger.info(f"retrieving dark calibration for step {step} and {exp_time = }")
|
|
223
|
+
dark_tags = [
|
|
224
|
+
VbiTag.intermediate(),
|
|
225
|
+
VbiTag.task_dark_frame(spatial_step=step, exposure_time=exp_time),
|
|
226
|
+
]
|
|
227
|
+
dark_calibration_path = next(self.read(tags=dark_tags))
|
|
228
|
+
_decode_calibration_file(dark_calibration_path)
|
|
229
|
+
|
|
230
|
+
for mosaic in range(1, self.constants.num_mosaic_repeats + 1):
|
|
231
|
+
apm_str = f"step {step} and repeat number {mosaic}"
|
|
232
|
+
logger.info(f"collecting observe frames for {apm_str}")
|
|
233
|
+
science_paths = self.read(
|
|
234
|
+
tags=[
|
|
235
|
+
VbiTag.input(),
|
|
236
|
+
VbiTag.frame(),
|
|
237
|
+
VbiTag.task_observe(),
|
|
238
|
+
VbiTag.mosaic(mosaic),
|
|
239
|
+
VbiTag.spatial_step(step),
|
|
240
|
+
VbiTag.exposure_time(exp_time),
|
|
241
|
+
],
|
|
242
|
+
)
|
|
243
|
+
|
|
244
|
+
calibrate_frame = partial(
|
|
245
|
+
self.calibrate_and_encode_science_frame,
|
|
246
|
+
dark_calibration_path=dark_calibration_path,
|
|
247
|
+
gain_calibration_path=gain_calibration_path,
|
|
248
|
+
bad_pixel_map_path=bad_pixel_map_path,
|
|
249
|
+
bad_pixel_neighborhood_radius=self.parameters.bad_pixel_neighborhood_radius,
|
|
250
|
+
mosaic=mosaic,
|
|
251
|
+
num_mosaic_repeats=self.constants.num_mosaic_repeats,
|
|
252
|
+
)
|
|
253
|
+
# Keep one extra frame per worker queued while results are written.
|
|
254
|
+
pending_frames = {
|
|
255
|
+
executor.submit(calibrate_frame, science_path)
|
|
256
|
+
for science_path in islice(science_paths, 2 * worker_count)
|
|
257
|
+
}
|
|
258
|
+
while pending_frames:
|
|
259
|
+
completed_frames, pending_frames = wait(
|
|
260
|
+
pending_frames, return_when=FIRST_COMPLETED
|
|
261
|
+
)
|
|
262
|
+
while completed_frames:
|
|
263
|
+
encoded_frame, exp_num = completed_frames.pop().result()
|
|
264
|
+
logger.info(f"Writing output for {apm_str} and {exp_num = }")
|
|
265
|
+
self.write_calibrated_fits_bytes(encoded_frame, mosaic, step)
|
|
266
|
+
del encoded_frame
|
|
267
|
+
|
|
268
|
+
science_path = next(science_paths, None)
|
|
269
|
+
if science_path is not None:
|
|
270
|
+
pending_frames.add(
|
|
271
|
+
executor.submit(calibrate_frame, science_path)
|
|
272
|
+
)
|
|
273
|
+
|
|
274
|
+
with self.telemetry_span("Computing and logging quality metrics"):
|
|
275
|
+
no_of_raw_obs_frames: int = self.count(
|
|
276
|
+
tags=[
|
|
277
|
+
VbiTag.input(),
|
|
278
|
+
VbiTag.frame(),
|
|
279
|
+
VbiTag.task_observe(),
|
|
280
|
+
],
|
|
281
|
+
)
|
|
282
|
+
self.quality_write_intermediate_task_type_counts(
|
|
283
|
+
task_type=TaskName.observe.value, total_frames=no_of_raw_obs_frames
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
def write_calibrated_fits_bytes(self, encoded_frame: bytes, mosaic: int, step: int) -> None:
|
|
287
|
+
"""Write encoded calibrated FITS bytes to scratch and tag them correctly."""
|
|
288
|
+
# It is an intentional decision to not tag with exposure time here
|
|
289
|
+
self.write(
|
|
290
|
+
data=encoded_frame,
|
|
291
|
+
tags=[
|
|
292
|
+
VbiTag.calibrated(),
|
|
293
|
+
VbiTag.frame(),
|
|
294
|
+
VbiTag.spatial_step(step),
|
|
295
|
+
VbiTag.mosaic(mosaic),
|
|
296
|
+
VbiTag.stokes("I"),
|
|
297
|
+
],
|
|
298
|
+
)
|
|
@@ -143,15 +143,21 @@ def science_calibration_task(
|
|
|
143
143
|
"abort_mosaic",
|
|
144
144
|
[pytest.param(False, id="Full set"), pytest.param(True, id="Aborted last mosaic")],
|
|
145
145
|
)
|
|
146
|
-
|
|
146
|
+
@pytest.mark.parametrize("cpu_count", [1, 2], ids=["single-core", "multi-core"])
|
|
147
|
+
def test_science_calibration(science_calibration_task, mocker, fake_gql_client, cpu_count):
|
|
147
148
|
"""
|
|
148
149
|
Given: a set of parsed input observe frames, dark and gain calibrations, and a ScienceCalibration task
|
|
149
|
-
When: the task is run
|
|
150
|
+
When: the task is run with one or two worker processes
|
|
150
151
|
Then: the science frames are processed, no exposures are averaged, and the array values are correct
|
|
151
152
|
"""
|
|
152
153
|
mocker.patch(
|
|
153
154
|
"dkist_processing_common.tasks.mixin.metadata_store.GraphQLClient", new=fake_gql_client
|
|
154
155
|
)
|
|
156
|
+
mocker.patch(
|
|
157
|
+
"dkist_processing_vbi.config.DKISTProcessingVBIConfigurations.cpu_count",
|
|
158
|
+
new_callable=mocker.PropertyMock,
|
|
159
|
+
return_value=cpu_count,
|
|
160
|
+
)
|
|
155
161
|
task, num_steps, num_exp_per_step, expected_num_mosaic_repeats = science_calibration_task
|
|
156
162
|
task()
|
|
157
163
|
|
|
@@ -213,6 +219,7 @@ def test_correct_bad_pixels(science_calibration_task):
|
|
|
213
219
|
corrected_image = task.correct_bad_pixels(
|
|
214
220
|
image=image,
|
|
215
221
|
bad_pixel_map=bad_pixel_map,
|
|
222
|
+
neighborhood_radius=task.parameters.bad_pixel_neighborhood_radius,
|
|
216
223
|
)
|
|
217
224
|
|
|
218
225
|
neighborhood = image[0, :11, :11]
|
|
@@ -241,6 +248,7 @@ def test_correct_clustered_bad_pixels(science_calibration_task, abort_mosaic):
|
|
|
241
248
|
corrected_image = task.correct_bad_pixels(
|
|
242
249
|
image=image,
|
|
243
250
|
bad_pixel_map=bad_pixel_map,
|
|
251
|
+
neighborhood_radius=task.parameters.bad_pixel_neighborhood_radius,
|
|
244
252
|
)
|
|
245
253
|
|
|
246
254
|
for row, column in ((5, 5), (5, 6)):
|