dkist-processing-vbi 1.34.8__tar.gz → 2.0.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.
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/CHANGELOG.rst +11 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/PKG-INFO +30 -31
- dkist_processing_vbi-2.0.0/SCIENCE_CHANGELOG.rst +18 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/models/parameters.py +5 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/tasks/assemble_movie.py +20 -7
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/tasks/gain.py +57 -3
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/tests/conftest.py +1 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/tests/test_assemble_movie.py +86 -8
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/tests/test_gain.py +50 -1
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi.egg-info/PKG-INFO +30 -31
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi.egg-info/requires.txt +29 -30
- dkist_processing_vbi-2.0.0/dkist_processing_vbi.egg-info/scm_version.json +8 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/pyproject.toml +31 -32
- dkist_processing_vbi-1.34.8/SCIENCE_CHANGELOG.rst +0 -7
- dkist_processing_vbi-1.34.8/dkist_processing_vbi.egg-info/scm_version.json +0 -8
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/.gitignore +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/.pre-commit-config.yaml +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/.readthedocs.yml +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/.rovodev/.review-agent.md +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/.snyk +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/README.rst +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/bitbucket-pipelines.yml +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/changelog/.gitempty +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/__init__.py +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/config.py +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/models/__init__.py +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/models/burst.py +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/models/constants.py +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/models/dataset_extras.py +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/models/filter.py +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/models/fits_access.py +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/models/tags.py +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/models/task_name.py +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/parsers/__init__.py +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/parsers/burst.py +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/parsers/mosaic_repeats.py +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/parsers/spatial_step_pattern.py +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/parsers/time.py +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/parsers/vbi_l0_fits_access.py +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/parsers/vbi_l1_fits_access.py +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/tasks/__init__.py +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/tasks/dark.py +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/tasks/make_movie_frames.py +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/tasks/parse.py +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/tasks/process_summit_processed.py +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/tasks/quality_metrics.py +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/tasks/science.py +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/tasks/vbi_base.py +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/tasks/write_dataset_extras.py +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/tasks/write_l1.py +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/tests/__init__.py +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/tests/local_trial_workflows/__init__.py +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/tests/local_trial_workflows/l0_to_l1.py +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/tests/test_dark.py +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/tests/test_dataset_extras.py +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/tests/test_fits_access.py +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/tests/test_make_movie_frames.py +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/tests/test_parse_l0.py +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/tests/test_parse_summit.py +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/tests/test_process_summit.py +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/tests/test_quality_metrics.py +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/tests/test_science.py +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/tests/test_spatial_step_pattern.py +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/tests/test_vbi_base.py +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/tests/test_vbi_constants.py +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/tests/test_workflows.py +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/tests/test_write_l1.py +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/workflows/__init__.py +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/workflows/l0_processing.py +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/workflows/summit_data_processing.py +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/workflows/trial_workflows.py +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi.egg-info/SOURCES.txt +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi.egg-info/dependency_links.txt +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi.egg-info/scm_file_list.json +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi.egg-info/top_level.txt +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/docs/Makefile +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/docs/changelog.rst +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/docs/conf.py +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/docs/dataset_extras.rst +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/docs/index.rst +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/docs/l0_to_l1_vbi_no-speckle-full-trial.rst +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/docs/l0_to_l1_vbi_no-speckle.rst +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/docs/l0_to_l1_vbi_summit-calibrated-full-trial.rst +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/docs/l0_to_l1_vbi_summit-calibrated.rst +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/docs/landing_page.rst +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/docs/make.bat +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/docs/requirements.txt +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/docs/requirements_table.rst +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/docs/scientific_changelog.rst +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/licenses/LICENSE.rst +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/science_towncrier.sh +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/setup.cfg +0 -0
- {dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/towncrier_science.toml +0 -0
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
v2.0.0 (2026-09-03)
|
|
2
|
+
===================
|
|
3
|
+
|
|
4
|
+
Features
|
|
5
|
+
--------
|
|
6
|
+
|
|
7
|
+
- Distinguish large, edge-connected gain occlusions from detector bad pixels, assigning occluded pixels a neutral gain of 1.0 and excluding them from bad-pixel correction. (`#231 <https://bitbucket.org/dkistdc/dkist-processing-vbi/pull-requests/231>`__)
|
|
8
|
+
- Update VBI movies to use percentile-clipped linear intensity scaling. (`#231 <https://bitbucket.org/dkistdc/dkist-processing-vbi/pull-requests/231>`__)
|
|
9
|
+
- Update VBI movies to display the observation's scanning mode. (`#231 <https://bitbucket.org/dkistdc/dkist-processing-vbi/pull-requests/231>`__)
|
|
10
|
+
|
|
11
|
+
|
|
1
12
|
v1.34.8 (2026-08-25)
|
|
2
13
|
====================
|
|
3
14
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dkist-processing-vbi
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2.0.0
|
|
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
|
|
@@ -80,7 +80,7 @@ Requires-Dist: alembic==1.19.1; extra == "frozen"
|
|
|
80
80
|
Requires-Dist: amqp==5.3.1; extra == "frozen"
|
|
81
81
|
Requires-Dist: annotated-doc==0.0.5; extra == "frozen"
|
|
82
82
|
Requires-Dist: annotated-types==0.8.0; extra == "frozen"
|
|
83
|
-
Requires-Dist: anyio==4.
|
|
83
|
+
Requires-Dist: anyio==4.15.0; 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
86
|
Requires-Dist: apache-airflow-providers-celery==3.23.1; extra == "frozen"
|
|
@@ -101,7 +101,7 @@ Requires-Dist: asdf_standard==1.5.0; extra == "frozen"
|
|
|
101
101
|
Requires-Dist: asgiref==3.12.1; extra == "frozen"
|
|
102
102
|
Requires-Dist: asteval==1.0.10; extra == "frozen"
|
|
103
103
|
Requires-Dist: astropy==7.0.2; extra == "frozen"
|
|
104
|
-
Requires-Dist: astropy-iers-data==0.2026.8.
|
|
104
|
+
Requires-Dist: astropy-iers-data==0.2026.8.31.0.57.9; extra == "frozen"
|
|
105
105
|
Requires-Dist: astropy_healpix==2.0.1; extra == "frozen"
|
|
106
106
|
Requires-Dist: asttokens==3.0.2; extra == "frozen"
|
|
107
107
|
Requires-Dist: async-lru==2.3.0; extra == "frozen"
|
|
@@ -111,15 +111,15 @@ Requires-Dist: babel==2.18.0; extra == "frozen"
|
|
|
111
111
|
Requires-Dist: beautifulsoup4==4.15.0; extra == "frozen"
|
|
112
112
|
Requires-Dist: billiard==4.2.4; extra == "frozen"
|
|
113
113
|
Requires-Dist: bleach==6.4.0; extra == "frozen"
|
|
114
|
-
Requires-Dist: boto3==1.43.
|
|
115
|
-
Requires-Dist: botocore==1.43.
|
|
116
|
-
Requires-Dist: cachetools==7.1.
|
|
114
|
+
Requires-Dist: boto3==1.43.88; extra == "frozen"
|
|
115
|
+
Requires-Dist: botocore==1.43.88; extra == "frozen"
|
|
116
|
+
Requires-Dist: cachetools==7.1.8; extra == "frozen"
|
|
117
117
|
Requires-Dist: cadwyn==7.0.0; extra == "frozen"
|
|
118
118
|
Requires-Dist: celery==5.6.3; extra == "frozen"
|
|
119
119
|
Requires-Dist: certifi==2026.7.22; extra == "frozen"
|
|
120
120
|
Requires-Dist: cffi==2.1.1; extra == "frozen"
|
|
121
121
|
Requires-Dist: charset-normalizer==3.5.1; extra == "frozen"
|
|
122
|
-
Requires-Dist: click==8.
|
|
122
|
+
Requires-Dist: click==8.5.0; extra == "frozen"
|
|
123
123
|
Requires-Dist: click-didyoumean==0.3.1; extra == "frozen"
|
|
124
124
|
Requires-Dist: click-plugins==1.1.1.2; extra == "frozen"
|
|
125
125
|
Requires-Dist: click-repl==0.3.0; extra == "frozen"
|
|
@@ -129,7 +129,7 @@ Requires-Dist: comm==0.2.3; extra == "frozen"
|
|
|
129
129
|
Requires-Dist: contourpy==1.3.3; extra == "frozen"
|
|
130
130
|
Requires-Dist: cron_descriptor==2.1.0; extra == "frozen"
|
|
131
131
|
Requires-Dist: croniter==6.2.4; extra == "frozen"
|
|
132
|
-
Requires-Dist: cryptography==50.0.
|
|
132
|
+
Requires-Dist: cryptography==50.0.1; extra == "frozen"
|
|
133
133
|
Requires-Dist: cycler==0.12.1; extra == "frozen"
|
|
134
134
|
Requires-Dist: dask==2026.8.0; extra == "frozen"
|
|
135
135
|
Requires-Dist: dask-image==2026.5.0; extra == "frozen"
|
|
@@ -142,7 +142,7 @@ Requires-Dist: dkist-processing-common==14.4.0; extra == "frozen"
|
|
|
142
142
|
Requires-Dist: dkist-processing-core==7.5.0; extra == "frozen"
|
|
143
143
|
Requires-Dist: dkist-processing-math==2.2.3; extra == "frozen"
|
|
144
144
|
Requires-Dist: dkist-processing-pac==3.1.2; extra == "frozen"
|
|
145
|
-
Requires-Dist: dkist-processing-vbi==
|
|
145
|
+
Requires-Dist: dkist-processing-vbi==2.0.0; extra == "frozen"
|
|
146
146
|
Requires-Dist: dkist-service-configuration==4.3.0; extra == "frozen"
|
|
147
147
|
Requires-Dist: dkist-spectral-lines==3.0.1; extra == "frozen"
|
|
148
148
|
Requires-Dist: dkist_fits_specifications==4.28.1; extra == "frozen"
|
|
@@ -154,17 +154,17 @@ Requires-Dist: fastapi==0.136.3; extra == "frozen"
|
|
|
154
154
|
Requires-Dist: fastapi-cli==0.0.32; extra == "frozen"
|
|
155
155
|
Requires-Dist: fastjsonschema==2.22.2; extra == "frozen"
|
|
156
156
|
Requires-Dist: flower==2.1.0; extra == "frozen"
|
|
157
|
-
Requires-Dist: fonttools==4.
|
|
157
|
+
Requires-Dist: fonttools==4.64.0; extra == "frozen"
|
|
158
158
|
Requires-Dist: fqdn==1.5.1; extra == "frozen"
|
|
159
159
|
Requires-Dist: frozenlist==1.8.0; extra == "frozen"
|
|
160
160
|
Requires-Dist: fsspec==2026.7.0; extra == "frozen"
|
|
161
161
|
Requires-Dist: globus-sdk==4.9.0; extra == "frozen"
|
|
162
162
|
Requires-Dist: google-crc32c==1.8.0; extra == "frozen"
|
|
163
|
-
Requires-Dist: googleapis-common-protos==1.75.
|
|
163
|
+
Requires-Dist: googleapis-common-protos==1.75.2; extra == "frozen"
|
|
164
164
|
Requires-Dist: gqlclient==2.0.0; extra == "frozen"
|
|
165
165
|
Requires-Dist: greenback==1.3.0; extra == "frozen"
|
|
166
166
|
Requires-Dist: greenlet==3.5.5; extra == "frozen"
|
|
167
|
-
Requires-Dist: grpcio==1.83.
|
|
167
|
+
Requires-Dist: grpcio==1.83.1; extra == "frozen"
|
|
168
168
|
Requires-Dist: h11==0.16.0; extra == "frozen"
|
|
169
169
|
Requires-Dist: httpcore==1.0.9; extra == "frozen"
|
|
170
170
|
Requires-Dist: httptools==0.8.0; extra == "frozen"
|
|
@@ -172,9 +172,9 @@ Requires-Dist: httpx==0.28.1; extra == "frozen"
|
|
|
172
172
|
Requires-Dist: humanize==4.16.0; extra == "frozen"
|
|
173
173
|
Requires-Dist: idna==3.19; extra == "frozen"
|
|
174
174
|
Requires-Dist: imageio-ffmpeg==0.6.0; extra == "frozen"
|
|
175
|
-
Requires-Dist: importlib_metadata==9.0.
|
|
175
|
+
Requires-Dist: importlib_metadata==9.0.1; extra == "frozen"
|
|
176
176
|
Requires-Dist: ipykernel==7.3.0; extra == "frozen"
|
|
177
|
-
Requires-Dist: ipython==9.
|
|
177
|
+
Requires-Dist: ipython==9.17.1; extra == "frozen"
|
|
178
178
|
Requires-Dist: ipython_pygments_lexers==1.1.1; extra == "frozen"
|
|
179
179
|
Requires-Dist: isoduration==20.11.0; extra == "frozen"
|
|
180
180
|
Requires-Dist: itsdangerous==2.2.0; extra == "frozen"
|
|
@@ -187,20 +187,20 @@ Requires-Dist: jsonschema-specifications==2025.9.1; extra == "frozen"
|
|
|
187
187
|
Requires-Dist: jupyter-events==0.12.1; extra == "frozen"
|
|
188
188
|
Requires-Dist: jupyter-lsp==2.3.1; extra == "frozen"
|
|
189
189
|
Requires-Dist: jupyter_builder==1.2.2; extra == "frozen"
|
|
190
|
-
Requires-Dist: jupyter_client==8.
|
|
190
|
+
Requires-Dist: jupyter_client==8.10.0; extra == "frozen"
|
|
191
191
|
Requires-Dist: jupyter_core==5.9.1; extra == "frozen"
|
|
192
|
-
Requires-Dist: jupyter_server==2.
|
|
192
|
+
Requires-Dist: jupyter_server==2.21.0; extra == "frozen"
|
|
193
193
|
Requires-Dist: jupyter_server_terminals==0.5.4; extra == "frozen"
|
|
194
194
|
Requires-Dist: jupyterlab==4.6.3; extra == "frozen"
|
|
195
195
|
Requires-Dist: jupyterlab_pygments==0.3.0; extra == "frozen"
|
|
196
196
|
Requires-Dist: jupyterlab_server==2.28.0; extra == "frozen"
|
|
197
|
-
Requires-Dist: kiwisolver==1.5.
|
|
197
|
+
Requires-Dist: kiwisolver==1.5.1; extra == "frozen"
|
|
198
198
|
Requires-Dist: kombu==5.6.2; extra == "frozen"
|
|
199
199
|
Requires-Dist: lark==1.3.1; extra == "frozen"
|
|
200
200
|
Requires-Dist: lazy-loader==0.5; extra == "frozen"
|
|
201
201
|
Requires-Dist: lazy-object-proxy==1.12.0; extra == "frozen"
|
|
202
202
|
Requires-Dist: libcst==1.9.0; extra == "frozen"
|
|
203
|
-
Requires-Dist: linkify-it-py==2.
|
|
203
|
+
Requires-Dist: linkify-it-py==2.2.0; extra == "frozen"
|
|
204
204
|
Requires-Dist: lmfit==1.3.4; extra == "frozen"
|
|
205
205
|
Requires-Dist: locket==1.0.0; extra == "frozen"
|
|
206
206
|
Requires-Dist: lockfile==0.12.2; extra == "frozen"
|
|
@@ -264,27 +264,27 @@ Requires-Dist: pexpect==4.9.0; extra == "frozen"
|
|
|
264
264
|
Requires-Dist: pika==1.4.4; extra == "frozen"
|
|
265
265
|
Requires-Dist: pillow==10.4.0; extra == "frozen"
|
|
266
266
|
Requires-Dist: pip==26.2.1; extra == "frozen"
|
|
267
|
-
Requires-Dist: platformdirs==4.11.
|
|
267
|
+
Requires-Dist: platformdirs==4.11.7; extra == "frozen"
|
|
268
268
|
Requires-Dist: pluggy==1.6.0; extra == "frozen"
|
|
269
269
|
Requires-Dist: pooch==1.9.0; extra == "frozen"
|
|
270
270
|
Requires-Dist: proglog==0.1.12; extra == "frozen"
|
|
271
271
|
Requires-Dist: prometheus_client==0.26.0; extra == "frozen"
|
|
272
272
|
Requires-Dist: prompt_toolkit==3.0.53; extra == "frozen"
|
|
273
273
|
Requires-Dist: propcache==0.5.2; extra == "frozen"
|
|
274
|
-
Requires-Dist: protobuf==7.36.
|
|
274
|
+
Requires-Dist: protobuf==7.36.1; extra == "frozen"
|
|
275
275
|
Requires-Dist: psutil==7.2.2; extra == "frozen"
|
|
276
|
-
Requires-Dist: psycopg==3.3.
|
|
277
|
-
Requires-Dist: psycopg-binary==3.3.
|
|
276
|
+
Requires-Dist: psycopg==3.3.5; extra == "frozen"
|
|
277
|
+
Requires-Dist: psycopg-binary==3.3.5; extra == "frozen"
|
|
278
278
|
Requires-Dist: psycopg2-binary==2.9.12; extra == "frozen"
|
|
279
279
|
Requires-Dist: ptyprocess==0.7.0; extra == "frozen"
|
|
280
280
|
Requires-Dist: pure_eval==0.2.3; extra == "frozen"
|
|
281
281
|
Requires-Dist: pycparser==3.0; extra == "frozen"
|
|
282
|
-
Requires-Dist: pydantic==2.13.
|
|
282
|
+
Requires-Dist: pydantic==2.13.5; extra == "frozen"
|
|
283
283
|
Requires-Dist: pydantic-extra-types==2.11.1; extra == "frozen"
|
|
284
284
|
Requires-Dist: pydantic-settings==2.15.0; extra == "frozen"
|
|
285
|
-
Requires-Dist: pydantic_core==2.46.
|
|
285
|
+
Requires-Dist: pydantic_core==2.46.5; extra == "frozen"
|
|
286
286
|
Requires-Dist: pyerfa==2.0.1.5; extra == "frozen"
|
|
287
|
-
Requires-Dist: pygtrie==2.
|
|
287
|
+
Requires-Dist: pygtrie==2.6.1; extra == "frozen"
|
|
288
288
|
Requires-Dist: pyparsing==3.3.2; extra == "frozen"
|
|
289
289
|
Requires-Dist: python-daemon==3.1.2; extra == "frozen"
|
|
290
290
|
Requires-Dist: python-dateutil==2.9.0.post0; extra == "frozen"
|
|
@@ -335,12 +335,11 @@ Requires-Dist: toolz==1.1.0; extra == "frozen"
|
|
|
335
335
|
Requires-Dist: tornado==6.5.8; extra == "frozen"
|
|
336
336
|
Requires-Dist: tqdm==4.70.0; extra == "frozen"
|
|
337
337
|
Requires-Dist: traitlets==5.16.1; extra == "frozen"
|
|
338
|
-
Requires-Dist: typer==0.27.
|
|
338
|
+
Requires-Dist: typer==0.27.2; extra == "frozen"
|
|
339
339
|
Requires-Dist: typing-inspection==0.4.4; extra == "frozen"
|
|
340
340
|
Requires-Dist: typing_extensions==4.16.0; extra == "frozen"
|
|
341
341
|
Requires-Dist: tzdata==2026.3; extra == "frozen"
|
|
342
342
|
Requires-Dist: tzlocal==5.4.4; extra == "frozen"
|
|
343
|
-
Requires-Dist: uc-micro-py==2.0.0; extra == "frozen"
|
|
344
343
|
Requires-Dist: uncertainties==3.2.3; extra == "frozen"
|
|
345
344
|
Requires-Dist: universal_pathlib==0.3.10; extra == "frozen"
|
|
346
345
|
Requires-Dist: uri-template==1.3.0; extra == "frozen"
|
|
@@ -351,13 +350,13 @@ Requires-Dist: uvloop==0.22.1; extra == "frozen"
|
|
|
351
350
|
Requires-Dist: vine==5.1.0; extra == "frozen"
|
|
352
351
|
Requires-Dist: voluptuous==0.16.0; extra == "frozen"
|
|
353
352
|
Requires-Dist: watchfiles==1.2.0; extra == "frozen"
|
|
354
|
-
Requires-Dist: wcwidth==0.8.
|
|
353
|
+
Requires-Dist: wcwidth==0.8.3; extra == "frozen"
|
|
355
354
|
Requires-Dist: webcolors==25.10.0; extra == "frozen"
|
|
356
355
|
Requires-Dist: webencodings==0.6.1; extra == "frozen"
|
|
357
|
-
Requires-Dist: websocket-client==1.9.
|
|
358
|
-
Requires-Dist: websockets==17.
|
|
356
|
+
Requires-Dist: websocket-client==1.9.2; extra == "frozen"
|
|
357
|
+
Requires-Dist: websockets==17.1; extra == "frozen"
|
|
359
358
|
Requires-Dist: wirerope==1.0.0; extra == "frozen"
|
|
360
|
-
Requires-Dist: wrapt==2.
|
|
359
|
+
Requires-Dist: wrapt==2.4.0; extra == "frozen"
|
|
361
360
|
Requires-Dist: yamale==6.1.0; extra == "frozen"
|
|
362
361
|
Requires-Dist: yarl==1.24.5; extra == "frozen"
|
|
363
362
|
Requires-Dist: zarr==3.3.0; extra == "frozen"
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
v2.0.0 (2026-09-03)
|
|
2
|
+
===================
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
- Large, edge-connected regions identified as bad in a gain frame can now be classified as observation-related occlusions using the configurable ``vbi_occlusion_minimum_connected_pixels`` threshold.
|
|
8
|
+
Occluded pixels are excluded from full-field gain normalization and the bad-pixel map, then assigned a neutral gain of 1.0.
|
|
9
|
+
This prevents unilluminated detector regions from being interpolated as if they were defective camera pixels and avoids invalid values when a correction neighborhood would otherwise contain only flagged pixels. (`#231 <https://bitbucket.org/dkistdc/dkist-processing-vbi/pull-requests/231>`__)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
v1.1.0 (2022-12-15)
|
|
13
|
+
===================
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
- Don't re-compress already compressed data that are processed at the summit. This ensures L1 files served by the Data Center are *exactly* the same as those processed on the summit. (`#39 <https://bitbucket.org/dkistdc/dkist-processing-vbi/pull-requests/39>`__)
|
{dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/models/parameters.py
RENAMED
|
@@ -16,6 +16,11 @@ class VbiParameters(ParameterBase):
|
|
|
16
16
|
"""Return the number of standard deviations used to identify bad pixels."""
|
|
17
17
|
return self._find_most_recent_past_value("vbi_bad_pixel_standard_deviations")
|
|
18
18
|
|
|
19
|
+
@property
|
|
20
|
+
def occlusion_minimum_connected_pixels(self) -> int:
|
|
21
|
+
"""Return the minimum edge-connected area classified as an occlusion."""
|
|
22
|
+
return self._find_most_recent_past_value("vbi_occlusion_minimum_connected_pixels")
|
|
23
|
+
|
|
19
24
|
@property
|
|
20
25
|
def movie_intensity_clipping_percentile(self) -> float:
|
|
21
26
|
"""Percentile to clip the movie intensity at."""
|
|
@@ -208,7 +208,7 @@ class AssembleVbiMovie(VbiTaskBase):
|
|
|
208
208
|
|
|
209
209
|
def apply_colormap(self, array: np.ndarray) -> np.ndarray:
|
|
210
210
|
"""
|
|
211
|
-
Convert floats to RGB colors using
|
|
211
|
+
Convert floats to RGB colors using a linear normalization scheme.
|
|
212
212
|
|
|
213
213
|
Parameters
|
|
214
214
|
----------
|
|
@@ -217,13 +217,23 @@ class AssembleVbiMovie(VbiTaskBase):
|
|
|
217
217
|
"""
|
|
218
218
|
# Clip the top and bottom 0.5% of data values to improve the contrast
|
|
219
219
|
movie_intensity_clipping_percentile = self.parameters.movie_intensity_clipping_percentile
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
)
|
|
223
|
-
|
|
220
|
+
finite = np.isfinite(array)
|
|
221
|
+
scaled_array = np.full(array.shape, np.nan)
|
|
222
|
+
if np.any(finite):
|
|
223
|
+
vmin, vmax = np.percentile(
|
|
224
|
+
array[finite],
|
|
225
|
+
(movie_intensity_clipping_percentile, 100 - movie_intensity_clipping_percentile),
|
|
226
|
+
)
|
|
227
|
+
if vmax > vmin:
|
|
228
|
+
scaled_array[finite] = np.clip(
|
|
229
|
+
a=(array[finite] - vmin) / (vmax - vmin),
|
|
230
|
+
a_min=0,
|
|
231
|
+
a_max=1,
|
|
232
|
+
)
|
|
233
|
+
else:
|
|
234
|
+
scaled_array[finite] = 0.0
|
|
224
235
|
|
|
225
236
|
color_mapper = colormaps.get_cmap("gray").with_extremes(bad="white")
|
|
226
|
-
scaled_array = ZScaleInterval()(array)
|
|
227
237
|
return color_mapper(scaled_array, bytes=True)[
|
|
228
238
|
:, :, :-1
|
|
229
239
|
] # Drop the last (alpha) color dimension
|
|
@@ -436,8 +446,11 @@ class AssembleVbiMovie(VbiTaskBase):
|
|
|
436
446
|
last_frame = self.movie_frames[-1]
|
|
437
447
|
obs_part_id = self.metadata_store_input_dataset_observe_frames.inputDatasetPartId
|
|
438
448
|
product_id = WriteL1Frame.compute_product_id(obs_part_id, "L1")
|
|
449
|
+
scanning_mode = (
|
|
450
|
+
"Center only" if first_frame.number_of_spatial_steps == 1 else "Field Scanning"
|
|
451
|
+
)
|
|
439
452
|
return (
|
|
440
|
-
f"Instrument: {self.instrument_string} -- Wavelength: {self.constants.wavelength:.3f} nm\n"
|
|
453
|
+
f"Instrument: {self.instrument_string} -- Wavelength: {self.constants.wavelength:.3f} nm -- Scanning Mode: {scanning_mode}\n"
|
|
441
454
|
f"Product ID: {product_id} --- Experiment ID: {self.constants.experiment_id}\n"
|
|
442
455
|
f"Start Time: {first_frame.time_obs} --- End Time: {last_frame.time_obs}"
|
|
443
456
|
)
|
{dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/tasks/gain.py
RENAMED
|
@@ -8,6 +8,7 @@ from dkist_processing_common.tasks.mixin.quality import QualityMixin
|
|
|
8
8
|
from dkist_processing_math.arithmetic import subtract_array_from_arrays
|
|
9
9
|
from dkist_processing_math.statistics import average_numpy_arrays
|
|
10
10
|
from dkist_service_configuration.logging import logger
|
|
11
|
+
from scipy import ndimage
|
|
11
12
|
|
|
12
13
|
from dkist_processing_vbi.models.tags import VbiTag
|
|
13
14
|
from dkist_processing_vbi.tasks.vbi_base import VbiTaskBase
|
|
@@ -52,8 +53,9 @@ class GainCalibration(VbiTaskBase, QualityMixin):
|
|
|
52
53
|
|
|
53
54
|
# We'll just stuff the un-normalized arrays in this dictionary to avoid dealing with tags, io, etc.
|
|
54
55
|
# This is OK (tm) because this will be, at most, 9 4k x 4k arrays. This is a lot (~1G), but not too much.
|
|
55
|
-
step_gain_dict: dict = {}
|
|
56
|
-
step_bad_pixel_map_dict: dict = {}
|
|
56
|
+
step_gain_dict: dict[int, np.ndarray] = {}
|
|
57
|
+
step_bad_pixel_map_dict: dict[int, np.ndarray] = {}
|
|
58
|
+
step_occlusion_mask_dict: dict[int, np.ndarray] = {}
|
|
57
59
|
|
|
58
60
|
with self.telemetry_span(
|
|
59
61
|
f"Collecting and reducing gain arrays from {self.constants.num_spatial_steps} steps and {len(self.constants.solar_gain_exposure_times)} exp times",
|
|
@@ -102,10 +104,13 @@ class GainCalibration(VbiTaskBase, QualityMixin):
|
|
|
102
104
|
averaged_gain_array=averaged_gain_array,
|
|
103
105
|
dark_subtracted_gain_array=dark_subtracted_gain_array,
|
|
104
106
|
)
|
|
107
|
+
occlusion_mask = self.identify_occlusion_pixels(bad_pixel_map)
|
|
108
|
+
step_occlusion_mask_dict[step] = occlusion_mask
|
|
109
|
+
bad_pixel_map = bad_pixel_map & ~occlusion_mask
|
|
105
110
|
step_bad_pixel_map_dict[step] = bad_pixel_map
|
|
106
111
|
|
|
107
112
|
logger.info(f"Recording processed gain image for {step = }")
|
|
108
|
-
usable_pixel_mask = ~bad_pixel_map
|
|
113
|
+
usable_pixel_mask = ~(bad_pixel_map | occlusion_mask)
|
|
109
114
|
self.total_usable_pix[step] = np.count_nonzero(usable_pixel_mask)
|
|
110
115
|
self.total_counts[step] = np.sum(dark_subtracted_gain_array[usable_pixel_mask])
|
|
111
116
|
step_gain_dict[step] = dark_subtracted_gain_array
|
|
@@ -113,6 +118,12 @@ class GainCalibration(VbiTaskBase, QualityMixin):
|
|
|
113
118
|
with self.telemetry_span("normalizing gain arrays"):
|
|
114
119
|
normalized_array_dict = self.normalize_fov(step_gain_dict)
|
|
115
120
|
|
|
121
|
+
with self.telemetry_span("neutralizing occluded gain values"):
|
|
122
|
+
normalized_array_dict = self.neutralize_occlusion_gain_values(
|
|
123
|
+
gain_array_dict=normalized_array_dict,
|
|
124
|
+
step_occlusion_mask_dict=step_occlusion_mask_dict,
|
|
125
|
+
)
|
|
126
|
+
|
|
116
127
|
with self.telemetry_span("replacing invalid inverse-gain values"):
|
|
117
128
|
normalized_array_dict = self.replace_invalid_gain_values(normalized_array_dict)
|
|
118
129
|
|
|
@@ -160,6 +171,49 @@ class GainCalibration(VbiTaskBase, QualityMixin):
|
|
|
160
171
|
|
|
161
172
|
return step_gain_dict
|
|
162
173
|
|
|
174
|
+
def identify_occlusion_pixels(self, bad_pixel_map: np.ndarray) -> np.ndarray:
|
|
175
|
+
"""Find large connected bad-pixel regions caused by edge occlusion."""
|
|
176
|
+
bad_pixel_plane = np.squeeze(bad_pixel_map)
|
|
177
|
+
# Give each 8-connected region a unique label
|
|
178
|
+
labels, _ = ndimage.label(
|
|
179
|
+
bad_pixel_plane,
|
|
180
|
+
structure=np.ones((3, 3), dtype=bool),
|
|
181
|
+
)
|
|
182
|
+
# Get the label number of every region that touches an edge
|
|
183
|
+
edge_labels = np.unique(
|
|
184
|
+
np.concatenate(
|
|
185
|
+
(
|
|
186
|
+
labels[0, :],
|
|
187
|
+
labels[-1, :],
|
|
188
|
+
labels[:, 0],
|
|
189
|
+
labels[:, -1],
|
|
190
|
+
)
|
|
191
|
+
)
|
|
192
|
+
)
|
|
193
|
+
edge_labels = edge_labels[edge_labels != 0]
|
|
194
|
+
|
|
195
|
+
occlusion_plane = np.zeros_like(bad_pixel_plane, dtype=bool)
|
|
196
|
+
component_sizes = np.bincount(labels.ravel())
|
|
197
|
+
minimum_connected_pixels = self.parameters.occlusion_minimum_connected_pixels
|
|
198
|
+
for label in edge_labels:
|
|
199
|
+
component_size = component_sizes[label]
|
|
200
|
+
if component_size >= minimum_connected_pixels:
|
|
201
|
+
# Add the pixels in this component to the occlusion plane
|
|
202
|
+
occlusion_plane |= labels == label
|
|
203
|
+
logger.info(f"Identified {component_size} edge-connected occlusion pixels")
|
|
204
|
+
|
|
205
|
+
return occlusion_plane.reshape(bad_pixel_map.shape)
|
|
206
|
+
|
|
207
|
+
@staticmethod
|
|
208
|
+
def neutralize_occlusion_gain_values(
|
|
209
|
+
gain_array_dict: dict[int, np.ndarray],
|
|
210
|
+
step_occlusion_mask_dict: dict[int, np.ndarray],
|
|
211
|
+
) -> dict[int, np.ndarray]:
|
|
212
|
+
"""Set occluded pixels to a neutral gain correction."""
|
|
213
|
+
for step, occlusion_mask in step_occlusion_mask_dict.items():
|
|
214
|
+
gain_array_dict[step][occlusion_mask] = 1.0
|
|
215
|
+
return gain_array_dict
|
|
216
|
+
|
|
163
217
|
@staticmethod
|
|
164
218
|
def replace_invalid_gain_values(
|
|
165
219
|
gain_array_dict: dict[int, np.ndarray],
|
{dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/tests/conftest.py
RENAMED
|
@@ -346,6 +346,7 @@ class VbiConstantsDb:
|
|
|
346
346
|
class VbiInputDatasetParameterValues:
|
|
347
347
|
vbi_bad_pixel_neighborhood_radius: int = 5
|
|
348
348
|
vbi_bad_pixel_standard_deviations: float = 9.0
|
|
349
|
+
vbi_occlusion_minimum_connected_pixels: int = 1000
|
|
349
350
|
vbi_movie_intensity_clipping_percentile: float = 0.5
|
|
350
351
|
vbi_central_region_side_length: int = 300
|
|
351
352
|
|
|
@@ -3,6 +3,9 @@ import pytest
|
|
|
3
3
|
from astropy.visualization.wcsaxes import WCSAxes
|
|
4
4
|
from dkist_processing_common._util.scratch import WorkflowFileSystem
|
|
5
5
|
from dkist_processing_common.codecs.fits import fits_hdulist_encoder
|
|
6
|
+
from dkist_processing_common.tests.mock_metadata_store import (
|
|
7
|
+
make_default_input_dataset_recipe_run_response,
|
|
8
|
+
)
|
|
6
9
|
from imageio_ffmpeg import count_frames_and_secs
|
|
7
10
|
from imageio_ffmpeg import read_frames
|
|
8
11
|
|
|
@@ -14,9 +17,22 @@ from dkist_processing_vbi.tests.conftest import VbiInputDatasetParameterValues
|
|
|
14
17
|
from dkist_processing_vbi.tests.conftest import generate_214_l1_fits_frame
|
|
15
18
|
|
|
16
19
|
|
|
20
|
+
@pytest.fixture(
|
|
21
|
+
scope="function",
|
|
22
|
+
params=[1, 10],
|
|
23
|
+
ids=["1_mosaic_repeat", "10_mosaic_repeats"],
|
|
24
|
+
)
|
|
25
|
+
def num_mosaic_repeats(request):
|
|
26
|
+
return request.param
|
|
27
|
+
|
|
28
|
+
|
|
17
29
|
@pytest.fixture(scope="function")
|
|
18
30
|
def assemble_task_with_tagged_movie_frames(
|
|
19
|
-
tmp_path,
|
|
31
|
+
tmp_path,
|
|
32
|
+
recipe_run_id,
|
|
33
|
+
init_vbi_constants_db,
|
|
34
|
+
assign_input_dataset_doc_to_task,
|
|
35
|
+
num_mosaic_repeats,
|
|
20
36
|
):
|
|
21
37
|
constants_db = VbiConstantsDb(NUM_MOSAIC_REPEATS=num_mosaic_repeats)
|
|
22
38
|
init_vbi_constants_db(recipe_run_id, constants_db)
|
|
@@ -47,26 +63,20 @@ def assemble_task_with_tagged_movie_frames(
|
|
|
47
63
|
],
|
|
48
64
|
encoder=fits_hdulist_encoder,
|
|
49
65
|
)
|
|
66
|
+
assign_input_dataset_doc_to_task(task, VbiInputDatasetParameterValues())
|
|
50
67
|
yield task
|
|
51
68
|
task._purge()
|
|
52
69
|
|
|
53
70
|
|
|
54
|
-
@pytest.mark.parametrize(
|
|
55
|
-
"num_mosaic_repeats",
|
|
56
|
-
[pytest.param(1, id="1_mosaic_repeat"), pytest.param(10, id="10_mosaic_repeats")],
|
|
57
|
-
)
|
|
58
71
|
def test_assemble_movie(
|
|
59
72
|
assemble_task_with_tagged_movie_frames,
|
|
60
73
|
mocker,
|
|
61
|
-
assign_input_dataset_doc_to_task,
|
|
62
74
|
fake_gql_client,
|
|
63
|
-
num_mosaic_repeats,
|
|
64
75
|
):
|
|
65
76
|
mocker.patch(
|
|
66
77
|
"dkist_processing_common.tasks.mixin.metadata_store.GraphQLClient", new=fake_gql_client
|
|
67
78
|
)
|
|
68
79
|
task = assemble_task_with_tagged_movie_frames
|
|
69
|
-
assign_input_dataset_doc_to_task(task, VbiInputDatasetParameterValues())
|
|
70
80
|
task()
|
|
71
81
|
assert task.parameters.movie_intensity_clipping_percentile == 0.5
|
|
72
82
|
movie_file = list(assemble_task_with_tagged_movie_frames.read(tags=[VbiTag.movie()]))
|
|
@@ -82,3 +92,71 @@ def test_assemble_movie(
|
|
|
82
92
|
assert f"DKIST/VBI-RED Level 1 Quicklook -- Dataset {task.constants.dataset_id}" in figure_text
|
|
83
93
|
assert isinstance(task.movie_axis, WCSAxes)
|
|
84
94
|
assert all(frame.data is None for frame in task.movie_frames)
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
@pytest.mark.parametrize(
|
|
98
|
+
("number_of_spatial_steps", "scanning_mode"),
|
|
99
|
+
[
|
|
100
|
+
pytest.param(1, "Center only", id="center_only"),
|
|
101
|
+
pytest.param(2, "Field Scanning", id="field_scanning"),
|
|
102
|
+
],
|
|
103
|
+
)
|
|
104
|
+
def test_format_dataset_info_includes_scanning_mode(
|
|
105
|
+
assemble_task_with_tagged_movie_frames,
|
|
106
|
+
number_of_spatial_steps,
|
|
107
|
+
scanning_mode,
|
|
108
|
+
):
|
|
109
|
+
"""
|
|
110
|
+
Given: A set of movie frames with a specified number of spatial steps
|
|
111
|
+
When: Formatting the dataset info
|
|
112
|
+
Then: The scanning mode is correctly included in the dataset info string
|
|
113
|
+
"""
|
|
114
|
+
task = assemble_task_with_tagged_movie_frames
|
|
115
|
+
task.metadata_store_input_dataset_recipe_run = make_default_input_dataset_recipe_run_response()
|
|
116
|
+
task.movie_frames = task.read_movie_frames()
|
|
117
|
+
first_frame = task.movie_frames[0]
|
|
118
|
+
first_frame.number_of_spatial_steps = number_of_spatial_steps
|
|
119
|
+
|
|
120
|
+
dataset_info = task.format_dataset_info(first_frame)
|
|
121
|
+
|
|
122
|
+
assert f"Scanning Mode: {scanning_mode}\n" in dataset_info
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
@pytest.mark.parametrize(
|
|
126
|
+
"non_finite_value",
|
|
127
|
+
[
|
|
128
|
+
pytest.param(np.nan, id="nan"),
|
|
129
|
+
pytest.param(np.inf, id="positive_infinity"),
|
|
130
|
+
pytest.param(-np.inf, id="negative_infinity"),
|
|
131
|
+
],
|
|
132
|
+
)
|
|
133
|
+
def test_apply_colormap_ignores_non_finite_values_when_scaling(
|
|
134
|
+
assemble_task_with_tagged_movie_frames, non_finite_value
|
|
135
|
+
):
|
|
136
|
+
"""
|
|
137
|
+
Given: An array with non-finite values (NaN, positive infinity, negative infinity)
|
|
138
|
+
When: Applying the colormap to the array
|
|
139
|
+
Then: The non-finite values are ignored when scaling, and they are mapped to white
|
|
140
|
+
"""
|
|
141
|
+
array = np.array([[0.0, 0.5, 1.0, non_finite_value]])
|
|
142
|
+
|
|
143
|
+
result = assemble_task_with_tagged_movie_frames.apply_colormap(array)
|
|
144
|
+
|
|
145
|
+
expected = np.array([[[0, 0, 0], [128, 128, 128], [255, 255, 255], [255, 255, 255]]])
|
|
146
|
+
np.testing.assert_array_equal(result, expected)
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
def test_apply_colormap_handles_array_without_finite_values(
|
|
150
|
+
assemble_task_with_tagged_movie_frames,
|
|
151
|
+
):
|
|
152
|
+
"""
|
|
153
|
+
Given: An array without any finite values (only NaN, positive infinity, negative infinity)
|
|
154
|
+
When: Applying the colormap to the array
|
|
155
|
+
Then: The result is an array of white pixels for all positions
|
|
156
|
+
"""
|
|
157
|
+
array = np.array([[np.nan, np.inf, -np.inf]])
|
|
158
|
+
|
|
159
|
+
result = assemble_task_with_tagged_movie_frames.apply_colormap(array)
|
|
160
|
+
|
|
161
|
+
expected = np.full((1, 3, 3), 255)
|
|
162
|
+
np.testing.assert_array_equal(result, expected)
|
{dkist_processing_vbi-1.34.8 → dkist_processing_vbi-2.0.0}/dkist_processing_vbi/tests/test_gain.py
RENAMED
|
@@ -138,7 +138,11 @@ def test_gain_calibration(gain_calibration_task, mocker, fake_gql_client):
|
|
|
138
138
|
|
|
139
139
|
|
|
140
140
|
def test_identify_bad_pixels(gain_calibration_task):
|
|
141
|
-
"""
|
|
141
|
+
"""
|
|
142
|
+
Given: a set of gain frames with known bad pixels
|
|
143
|
+
When: the identify_bad_pixels method is called
|
|
144
|
+
Then: the bad pixels are correctly identified in the output map
|
|
145
|
+
"""
|
|
142
146
|
averaged_gain_array = np.full((100, 100), 100.0)
|
|
143
147
|
dark_subtracted_gain_array = averaged_gain_array.copy()
|
|
144
148
|
|
|
@@ -160,3 +164,48 @@ def test_identify_bad_pixels(gain_calibration_task):
|
|
|
160
164
|
expected_bad_pixel_map = np.zeros_like(averaged_gain_array, dtype=bool)
|
|
161
165
|
expected_bad_pixel_map[0, :5] = True
|
|
162
166
|
np.testing.assert_array_equal(bad_pixel_map, expected_bad_pixel_map)
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
@pytest.mark.parametrize(
|
|
170
|
+
"bad_pixel_map_shape",
|
|
171
|
+
[
|
|
172
|
+
pytest.param((200, 200), id="2d"),
|
|
173
|
+
pytest.param((1, 200, 200), id="leading_dimension"),
|
|
174
|
+
],
|
|
175
|
+
)
|
|
176
|
+
def test_identify_occlusion_pixels(gain_calibration_task, bad_pixel_map_shape):
|
|
177
|
+
"""
|
|
178
|
+
Given: a bad pixel map with known occluded regions
|
|
179
|
+
When: the identify_occlusion_pixels method is called
|
|
180
|
+
Then: the occluded regions are correctly identified in the output mask
|
|
181
|
+
"""
|
|
182
|
+
bad_pixel_map = np.zeros(bad_pixel_map_shape, dtype=bool)
|
|
183
|
+
bad_pixel_map[..., 0:20, 75:125] = True # large edge region - occlusion
|
|
184
|
+
bad_pixel_map[..., 50:75, 80:120] = True # large interior region
|
|
185
|
+
bad_pixel_map[..., 150:160, 0:99] = True # small edge region
|
|
186
|
+
|
|
187
|
+
occlusion_mask = gain_calibration_task.identify_occlusion_pixels(bad_pixel_map)
|
|
188
|
+
|
|
189
|
+
expected_occlusion_mask = np.zeros_like(bad_pixel_map)
|
|
190
|
+
expected_occlusion_mask[..., 0:20, 75:125] = True
|
|
191
|
+
assert occlusion_mask.shape == bad_pixel_map_shape
|
|
192
|
+
np.testing.assert_array_equal(occlusion_mask, expected_occlusion_mask)
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
def test_neutralize_occlusion_gain_values():
|
|
196
|
+
"""
|
|
197
|
+
Given: a gain array with known occluded regions
|
|
198
|
+
When: the neutralize_occlusion_gain_values method is called
|
|
199
|
+
Then: the occluded regions are set to 1.0 and the other values remain unchanged
|
|
200
|
+
"""
|
|
201
|
+
gain_array = np.array([[[0.5, 0.75, 1.25], [1.5, 1.75, 2.0]]])
|
|
202
|
+
original_gain_array = gain_array.copy()
|
|
203
|
+
occlusion_mask = np.array([[[False, True, False], [True, False, False]]])
|
|
204
|
+
|
|
205
|
+
result = GainCalibration.neutralize_occlusion_gain_values(
|
|
206
|
+
gain_array_dict={1: gain_array},
|
|
207
|
+
step_occlusion_mask_dict={1: occlusion_mask},
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
np.testing.assert_array_equal(result[1][occlusion_mask], 1.0)
|
|
211
|
+
np.testing.assert_array_equal(result[1][~occlusion_mask], original_gain_array[~occlusion_mask])
|