dkist-processing-visp 4.0.0__tar.gz → 5.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.
Files changed (116) hide show
  1. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/CHANGELOG.rst +33 -0
  2. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/PKG-INFO +40 -37
  3. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/SCIENCE_CHANGELOG.rst +19 -0
  4. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/models/constants.py +50 -9
  5. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/models/fits_access.py +5 -1
  6. dkist_processing_visp-5.0.0/dkist_processing_visp/models/metric_code.py +10 -0
  7. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/models/parameters.py +128 -19
  8. dkist_processing_visp-5.0.0/dkist_processing_visp/parsers/spectrograph_configuration.py +75 -0
  9. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/parsers/visp_l0_fits_access.py +6 -0
  10. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/tasks/geometric.py +115 -7
  11. dkist_processing_visp-5.0.0/dkist_processing_visp/tasks/l1_output_data.py +216 -0
  12. dkist_processing_visp-5.0.0/dkist_processing_visp/tasks/lamp.py +126 -0
  13. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/tasks/parse.py +19 -0
  14. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/tasks/science.py +14 -14
  15. dkist_processing_visp-5.0.0/dkist_processing_visp/tasks/solar.py +1185 -0
  16. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/tasks/visp_base.py +1 -0
  17. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/tests/conftest.py +98 -35
  18. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/tests/header_models.py +71 -20
  19. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/tests/local_trial_workflows/local_trial_helpers.py +25 -1
  20. dkist_processing_visp-5.0.0/dkist_processing_visp/tests/test_assemble_quality.py +126 -0
  21. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/tests/test_geometric.py +40 -0
  22. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/tests/test_instrument_polarization.py +2 -1
  23. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/tests/test_lamp.py +17 -22
  24. dkist_processing_visp-5.0.0/dkist_processing_visp/tests/test_parameters.py +221 -0
  25. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/tests/test_parse.py +73 -1
  26. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/tests/test_science.py +5 -6
  27. dkist_processing_visp-5.0.0/dkist_processing_visp/tests/test_solar.py +485 -0
  28. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/tests/test_visp_constants.py +35 -6
  29. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp.egg-info/PKG-INFO +40 -37
  30. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp.egg-info/SOURCES.txt +2 -1
  31. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp.egg-info/requires.txt +39 -36
  32. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/docs/conf.py +4 -1
  33. dkist_processing_visp-5.0.0/docs/gain_correction.rst +118 -0
  34. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/pyproject.toml +41 -38
  35. dkist_processing_visp-4.0.0/dkist_processing_visp/tasks/l1_output_data.py +0 -14
  36. dkist_processing_visp-4.0.0/dkist_processing_visp/tasks/lamp.py +0 -167
  37. dkist_processing_visp-4.0.0/dkist_processing_visp/tasks/mixin/line_zones.py +0 -116
  38. dkist_processing_visp-4.0.0/dkist_processing_visp/tasks/solar.py +0 -742
  39. dkist_processing_visp-4.0.0/dkist_processing_visp/tests/test_assemble_quality.py +0 -41
  40. dkist_processing_visp-4.0.0/dkist_processing_visp/tests/test_parameters.py +0 -119
  41. dkist_processing_visp-4.0.0/dkist_processing_visp/tests/test_solar.py +0 -268
  42. dkist_processing_visp-4.0.0/docs/gain_correction.rst +0 -110
  43. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/.gitignore +0 -0
  44. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/.pre-commit-config.yaml +0 -0
  45. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/.readthedocs.yml +0 -0
  46. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/.snyk +0 -0
  47. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/README.rst +0 -0
  48. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/bitbucket-pipelines.yml +0 -0
  49. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/changelog/.gitempty +0 -0
  50. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/__init__.py +0 -0
  51. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/config.py +0 -0
  52. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/fonts/Lato-Regular.ttf +0 -0
  53. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/models/__init__.py +0 -0
  54. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/models/tags.py +0 -0
  55. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/models/task_name.py +0 -0
  56. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/parsers/__init__.py +0 -0
  57. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/parsers/map_repeats.py +0 -0
  58. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/parsers/modulator_states.py +0 -0
  59. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/parsers/polarimeter_mode.py +0 -0
  60. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/parsers/raster_step.py +0 -0
  61. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/parsers/time.py +0 -0
  62. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/parsers/visp_l1_fits_access.py +0 -0
  63. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/tasks/__init__.py +0 -0
  64. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/tasks/assemble_movie.py +0 -0
  65. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/tasks/background_light.py +0 -0
  66. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/tasks/dark.py +0 -0
  67. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/tasks/instrument_polarization.py +0 -0
  68. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/tasks/make_movie_frames.py +0 -0
  69. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/tasks/mixin/__init__.py +0 -0
  70. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/tasks/mixin/beam_access.py +0 -0
  71. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/tasks/mixin/corrections.py +0 -0
  72. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/tasks/mixin/downsample.py +0 -0
  73. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/tasks/quality_metrics.py +0 -0
  74. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/tasks/write_l1.py +0 -0
  75. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/tests/README.rst +0 -0
  76. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/tests/__init__.py +0 -0
  77. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/tests/local_trial_workflows/__init__.py +0 -0
  78. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/tests/local_trial_workflows/l0_cals_only.py +0 -0
  79. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/tests/local_trial_workflows/l0_polcals_as_science.py +0 -0
  80. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/tests/local_trial_workflows/l0_solar_gain_as_science.py +0 -0
  81. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/tests/local_trial_workflows/l0_to_l1.py +0 -0
  82. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/tests/test_assemble_movie.py +0 -0
  83. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/tests/test_background_light.py +0 -0
  84. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/tests/test_dark.py +0 -0
  85. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/tests/test_downsample.py +0 -0
  86. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/tests/test_fits_access.py +0 -0
  87. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/tests/test_make_movie_frames.py +0 -0
  88. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/tests/test_map_repeats.py +0 -0
  89. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/tests/test_quality.py +0 -0
  90. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/tests/test_trial_create_quality_report.py +0 -0
  91. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/tests/test_workflows.py +0 -0
  92. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/tests/test_write_l1.py +0 -0
  93. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/workflows/__init__.py +0 -0
  94. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/workflows/l0_processing.py +0 -0
  95. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/workflows/single_task_workflows.py +0 -0
  96. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp/workflows/trial_workflows.py +0 -0
  97. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp.egg-info/dependency_links.txt +0 -0
  98. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/dkist_processing_visp.egg-info/top_level.txt +0 -0
  99. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/docs/Makefile +0 -0
  100. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/docs/background_light.rst +0 -0
  101. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/docs/changelog.rst +0 -0
  102. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/docs/geometric.rst +0 -0
  103. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/docs/index.rst +0 -0
  104. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/docs/l0_to_l1_visp.rst +0 -0
  105. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/docs/l0_to_l1_visp_full-trial.rst +0 -0
  106. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/docs/landing_page.rst +0 -0
  107. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/docs/make.bat +0 -0
  108. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/docs/polarization_calibration.rst +0 -0
  109. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/docs/requirements.txt +0 -0
  110. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/docs/requirements_table.rst +0 -0
  111. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/docs/science_calibration.rst +0 -0
  112. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/docs/scientific_changelog.rst +0 -0
  113. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/licenses/LICENSE.rst +0 -0
  114. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/science_towncrier.sh +0 -0
  115. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/setup.cfg +0 -0
  116. {dkist_processing_visp-4.0.0 → dkist_processing_visp-5.0.0}/towncrier_science.toml +0 -0
@@ -1,3 +1,36 @@
1
+ v5.0.0 (2025-12-02)
2
+ ===================
3
+
4
+ Features
5
+ --------
6
+
7
+ - Only compute a single lamp gain for each beam. In the past a single map gain was also computed for each modulation state. (`#246 <https://bitbucket.org/dkistdc/dkist-processing-visp/pull-requests/246>`__)
8
+ - Add quality report metrics that show the quality of the vignette estimation in the Solar Gain tasks. (`#246 <https://bitbucket.org/dkistdc/dkist-processing-visp/pull-requests/246>`__)
9
+ - Update the Solar Gain task to measure vignetting signal, compute a single gain for each beam (as opposed to for each beam and modulator state),
10
+ and stop applying residual spectral shifts to the characteristic spectra before removing from the input gain array.
11
+ See the `Science Changelog <https://docs.dkist.nso.edu/projects/visp/en/stable/scientific_changelog.html>`_ and
12
+ `gain algorithm docs <https://docs.dkist.nso.edu/projects/visp/en/stable/gain_correction.html>`_ for more information. (`#246 <https://bitbucket.org/dkistdc/dkist-processing-visp/pull-requests/246>`__)
13
+ - Add Buds to parse the spectrograph setup into pipeline constants to be used when fitting a solar atlas. (`#246 <https://bitbucket.org/dkistdc/dkist-processing-visp/pull-requests/246>`__)
14
+
15
+
16
+ Misc
17
+ ----
18
+
19
+ - Remove the `LineZonesMixin` and move its methods directly to the Geometric calibration task, which is now the only task that uses them. (`#246 <https://bitbucket.org/dkistdc/dkist-processing-visp/pull-requests/246>`__)
20
+ - Rename the ``solar_spectral_avg_window`` to ``solar_spatial_median_filter_width_px`` to more accurately capture what it does. (`#246 <https://bitbucket.org/dkistdc/dkist-processing-visp/pull-requests/246>`__)
21
+ - Rename all line-zone parameters to be "geo*" parameters instead of "solar*" parameters. These parameters are now only used in the
22
+ Geometric calibration task. (`#246 <https://bitbucket.org/dkistdc/dkist-processing-visp/pull-requests/246>`__)
23
+
24
+
25
+ Documentation
26
+ -------------
27
+
28
+ - Update the online doc page for `gain calibration <https://docs.dkist.nso.edu/projects/visp/en/stable/gain_correction.html>`_
29
+ to reflect the updates to the Solar Gain task. (`#246 <https://bitbucket.org/dkistdc/dkist-processing-visp/pull-requests/246>`__)
30
+ - Add intersphinx mappings for `lmfit <https://lmfit.github.io/lmfit-py/>`_ and `scikit-learn <https://scikit-learn.org/stable/>`_
31
+ for linking bliss. (`#246 <https://bitbucket.org/dkistdc/dkist-processing-visp/pull-requests/246>`__)
32
+
33
+
1
34
  v4.0.0 (2025-11-12)
2
35
  ===================
3
36
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dkist-processing-visp
3
- Version: 4.0.0
3
+ Version: 5.0.0
4
4
  Summary: Science processing code for the ViSP instrument on DKIST
5
5
  Author-email: NSO / AURA <dkistdc@nso.edu>
6
6
  License: BSD-3-Clause
@@ -13,13 +13,14 @@ Classifier: Programming Language :: Python :: 3
13
13
  Classifier: Programming Language :: Python :: 3.12
14
14
  Requires-Python: >=3.12
15
15
  Description-Content-Type: text/x-rst
16
- Requires-Dist: dkist-processing-common==11.8.0
16
+ Requires-Dist: dkist-processing-common==11.8.1
17
17
  Requires-Dist: dkist-processing-math==2.2.1
18
18
  Requires-Dist: dkist-processing-pac==3.1.1
19
19
  Requires-Dist: dkist-header-validator==5.2.1
20
20
  Requires-Dist: dkist-fits-specifications==4.17.0
21
21
  Requires-Dist: dkist-service-configuration==4.1.7
22
22
  Requires-Dist: dkist-spectral-lines==3.0.0
23
+ Requires-Dist: solar-wavelength-calibration==2.0.0
23
24
  Requires-Dist: astropy==7.0.2
24
25
  Requires-Dist: numpy==2.2.5
25
26
  Requires-Dist: sunpy==6.1.1
@@ -94,44 +95,44 @@ Requires-Dist: aiohappyeyeballs==2.6.1; extra == "frozen"
94
95
  Requires-Dist: aiohttp==3.13.2; extra == "frozen"
95
96
  Requires-Dist: aiosignal==1.4.0; extra == "frozen"
96
97
  Requires-Dist: aiosmtplib==5.0.0; extra == "frozen"
97
- Requires-Dist: alembic==1.17.1; extra == "frozen"
98
+ Requires-Dist: alembic==1.17.2; extra == "frozen"
98
99
  Requires-Dist: amqp==5.3.1; extra == "frozen"
99
100
  Requires-Dist: annotated-types==0.7.0; extra == "frozen"
100
- Requires-Dist: anyio==4.11.0; extra == "frozen"
101
+ Requires-Dist: anyio==4.12.0; extra == "frozen"
101
102
  Requires-Dist: apache-airflow==2.11.0; extra == "frozen"
102
- Requires-Dist: apache-airflow-providers-celery==3.10.0; extra == "frozen"
103
- Requires-Dist: apache-airflow-providers-common-compat==1.8.0; extra == "frozen"
104
- Requires-Dist: apache-airflow-providers-common-io==1.6.4; extra == "frozen"
105
- Requires-Dist: apache-airflow-providers-common-sql==1.28.2; extra == "frozen"
103
+ Requires-Dist: apache-airflow-providers-celery==3.13.1; extra == "frozen"
104
+ Requires-Dist: apache-airflow-providers-common-compat==1.10.0; extra == "frozen"
105
+ Requires-Dist: apache-airflow-providers-common-io==1.7.0; extra == "frozen"
106
+ Requires-Dist: apache-airflow-providers-common-sql==1.29.0; extra == "frozen"
106
107
  Requires-Dist: apache-airflow-providers-fab==1.5.3; extra == "frozen"
107
- Requires-Dist: apache-airflow-providers-ftp==3.13.2; extra == "frozen"
108
- Requires-Dist: apache-airflow-providers-http==5.4.0; extra == "frozen"
109
- Requires-Dist: apache-airflow-providers-imap==3.9.3; extra == "frozen"
110
- Requires-Dist: apache-airflow-providers-postgres==6.4.0; extra == "frozen"
111
- Requires-Dist: apache-airflow-providers-smtp==2.3.1; extra == "frozen"
112
- Requires-Dist: apache-airflow-providers-sqlite==4.1.2; extra == "frozen"
113
- Requires-Dist: apispec==6.8.4; extra == "frozen"
108
+ Requires-Dist: apache-airflow-providers-ftp==3.14.0; extra == "frozen"
109
+ Requires-Dist: apache-airflow-providers-http==5.6.0; extra == "frozen"
110
+ Requires-Dist: apache-airflow-providers-imap==3.10.0; extra == "frozen"
111
+ Requires-Dist: apache-airflow-providers-postgres==6.5.0; extra == "frozen"
112
+ Requires-Dist: apache-airflow-providers-smtp==2.4.0; extra == "frozen"
113
+ Requires-Dist: apache-airflow-providers-sqlite==4.2.0; extra == "frozen"
114
+ Requires-Dist: apispec==6.9.0; extra == "frozen"
114
115
  Requires-Dist: argcomplete==3.6.3; extra == "frozen"
115
116
  Requires-Dist: asdf==3.5.0; extra == "frozen"
116
117
  Requires-Dist: asdf_standard==1.4.0; extra == "frozen"
117
118
  Requires-Dist: asdf_transform_schemas==0.6.0; extra == "frozen"
118
- Requires-Dist: asgiref==3.10.0; extra == "frozen"
119
+ Requires-Dist: asgiref==3.11.0; extra == "frozen"
119
120
  Requires-Dist: asteval==1.0.7; extra == "frozen"
120
121
  Requires-Dist: astropy==7.0.2; extra == "frozen"
121
- Requires-Dist: astropy-iers-data==0.2025.11.10.0.38.31; extra == "frozen"
122
- Requires-Dist: asyncpg==0.30.0; extra == "frozen"
122
+ Requires-Dist: astropy-iers-data==0.2025.12.1.0.45.12; extra == "frozen"
123
+ Requires-Dist: asyncpg==0.31.0; extra == "frozen"
123
124
  Requires-Dist: attrs==25.4.0; extra == "frozen"
124
125
  Requires-Dist: babel==2.17.0; extra == "frozen"
125
- Requires-Dist: billiard==4.2.2; extra == "frozen"
126
+ Requires-Dist: billiard==4.2.4; extra == "frozen"
126
127
  Requires-Dist: blinker==1.9.0; extra == "frozen"
127
- Requires-Dist: boto3==1.40.71; extra == "frozen"
128
- Requires-Dist: botocore==1.40.71; extra == "frozen"
128
+ Requires-Dist: boto3==1.42.1; extra == "frozen"
129
+ Requires-Dist: botocore==1.42.1; extra == "frozen"
129
130
  Requires-Dist: cachelib==0.13.0; extra == "frozen"
130
- Requires-Dist: celery==5.3.1; extra == "frozen"
131
+ Requires-Dist: celery==5.6.0; extra == "frozen"
131
132
  Requires-Dist: certifi==2025.11.12; extra == "frozen"
132
133
  Requires-Dist: cffi==2.0.0; extra == "frozen"
133
134
  Requires-Dist: charset-normalizer==3.4.4; extra == "frozen"
134
- Requires-Dist: click==8.3.0; extra == "frozen"
135
+ Requires-Dist: click==8.3.1; extra == "frozen"
135
136
  Requires-Dist: click-didyoumean==0.3.1; extra == "frozen"
136
137
  Requires-Dist: click-plugins==1.1.1.2; extra == "frozen"
137
138
  Requires-Dist: click-repl==0.3.0; extra == "frozen"
@@ -148,25 +149,27 @@ Requires-Dist: dacite==1.9.2; extra == "frozen"
148
149
  Requires-Dist: decorator==5.2.1; extra == "frozen"
149
150
  Requires-Dist: dill==0.4.0; extra == "frozen"
150
151
  Requires-Dist: dkist-header-validator==5.2.1; extra == "frozen"
151
- Requires-Dist: dkist-processing-common==11.8.0; extra == "frozen"
152
+ Requires-Dist: dkist-processing-common==11.8.1; extra == "frozen"
152
153
  Requires-Dist: dkist-processing-core==6.0.0; extra == "frozen"
153
154
  Requires-Dist: dkist-processing-math==2.2.1; extra == "frozen"
154
155
  Requires-Dist: dkist-processing-pac==3.1.1; extra == "frozen"
155
- Requires-Dist: dkist-processing-visp==4.0.0; extra == "frozen"
156
+ Requires-Dist: dkist-processing-visp==5.0.0; extra == "frozen"
156
157
  Requires-Dist: dkist-service-configuration==4.1.7; extra == "frozen"
157
158
  Requires-Dist: dkist-spectral-lines==3.0.0; extra == "frozen"
158
159
  Requires-Dist: dkist_fits_specifications==4.17.0; extra == "frozen"
159
160
  Requires-Dist: dnspython==2.8.0; extra == "frozen"
160
161
  Requires-Dist: email-validator==2.3.0; extra == "frozen"
162
+ Requires-Dist: exceptiongroup==1.3.1; extra == "frozen"
161
163
  Requires-Dist: fastjsonschema==2.21.2; extra == "frozen"
162
164
  Requires-Dist: flower==2.0.1; extra == "frozen"
163
- Requires-Dist: fonttools==4.60.1; extra == "frozen"
165
+ Requires-Dist: fonttools==4.61.0; extra == "frozen"
164
166
  Requires-Dist: frozenlist==1.8.0; extra == "frozen"
165
167
  Requires-Dist: fsspec==2025.10.0; extra == "frozen"
166
168
  Requires-Dist: globus-sdk==3.65.0; extra == "frozen"
167
169
  Requires-Dist: google-re2==1.1.20251105; extra == "frozen"
168
170
  Requires-Dist: googleapis-common-protos==1.72.0; extra == "frozen"
169
171
  Requires-Dist: gqlclient==1.2.3; extra == "frozen"
172
+ Requires-Dist: greenlet==3.2.4; extra == "frozen"
170
173
  Requires-Dist: grpcio==1.76.0; extra == "frozen"
171
174
  Requires-Dist: gunicorn==23.0.0; extra == "frozen"
172
175
  Requires-Dist: h11==0.16.0; extra == "frozen"
@@ -184,7 +187,7 @@ Requires-Dist: jsonschema==4.25.1; extra == "frozen"
184
187
  Requires-Dist: jsonschema-specifications==2025.9.1; extra == "frozen"
185
188
  Requires-Dist: jupyter_core==5.9.1; extra == "frozen"
186
189
  Requires-Dist: kiwisolver==1.4.9; extra == "frozen"
187
- Requires-Dist: kombu==5.6.0; extra == "frozen"
190
+ Requires-Dist: kombu==5.6.1; extra == "frozen"
188
191
  Requires-Dist: lazy-object-proxy==1.12.0; extra == "frozen"
189
192
  Requires-Dist: lazy_loader==0.4; extra == "frozen"
190
193
  Requires-Dist: limits==5.6.0; extra == "frozen"
@@ -204,7 +207,7 @@ Requires-Dist: more-itertools==10.8.0; extra == "frozen"
204
207
  Requires-Dist: moviepy==2.1.2; extra == "frozen"
205
208
  Requires-Dist: multidict==6.7.0; extra == "frozen"
206
209
  Requires-Dist: nbformat==5.10.4; extra == "frozen"
207
- Requires-Dist: networkx==3.5; extra == "frozen"
210
+ Requires-Dist: networkx==3.6; extra == "frozen"
208
211
  Requires-Dist: numpy==2.2.5; extra == "frozen"
209
212
  Requires-Dist: object-clerk==1.0.0; extra == "frozen"
210
213
  Requires-Dist: opentelemetry-api==1.38.0; extra == "frozen"
@@ -249,11 +252,11 @@ Requires-Dist: proglog==0.1.12; extra == "frozen"
249
252
  Requires-Dist: prometheus_client==0.23.1; extra == "frozen"
250
253
  Requires-Dist: prompt_toolkit==3.0.52; extra == "frozen"
251
254
  Requires-Dist: propcache==0.4.1; extra == "frozen"
252
- Requires-Dist: protobuf==6.33.0; extra == "frozen"
255
+ Requires-Dist: protobuf==6.33.1; extra == "frozen"
253
256
  Requires-Dist: psutil==7.1.3; extra == "frozen"
254
257
  Requires-Dist: psycopg2-binary==2.9.11; extra == "frozen"
255
258
  Requires-Dist: pycparser==2.23; extra == "frozen"
256
- Requires-Dist: pydantic==2.12.4; extra == "frozen"
259
+ Requires-Dist: pydantic==2.12.5; extra == "frozen"
257
260
  Requires-Dist: pydantic-settings==2.12.0; extra == "frozen"
258
261
  Requires-Dist: pydantic_core==2.41.5; extra == "frozen"
259
262
  Requires-Dist: pyerfa==2.0.1.5; extra == "frozen"
@@ -271,18 +274,17 @@ Requires-Dist: requests-toolbelt==1.0.0; extra == "frozen"
271
274
  Requires-Dist: rfc3339-validator==0.1.4; extra == "frozen"
272
275
  Requires-Dist: rich==13.9.4; extra == "frozen"
273
276
  Requires-Dist: rich-argparse==1.7.2; extra == "frozen"
274
- Requires-Dist: rpds-py==0.28.0; extra == "frozen"
275
- Requires-Dist: s3transfer==0.14.0; extra == "frozen"
277
+ Requires-Dist: rpds-py==0.30.0; extra == "frozen"
278
+ Requires-Dist: s3transfer==0.16.0; extra == "frozen"
276
279
  Requires-Dist: scikit-image==0.25.2; extra == "frozen"
277
280
  Requires-Dist: scikit-learn==1.6.1; extra == "frozen"
278
281
  Requires-Dist: scipy==1.15.3; extra == "frozen"
279
282
  Requires-Dist: semantic-version==2.10.0; extra == "frozen"
280
283
  Requires-Dist: setproctitle==1.3.7; extra == "frozen"
281
284
  Requires-Dist: six==1.17.0; extra == "frozen"
282
- Requires-Dist: sniffio==1.3.1; extra == "frozen"
283
- Requires-Dist: solar-wavelength-calibration==1.0.1; extra == "frozen"
285
+ Requires-Dist: solar-wavelength-calibration==2.0.0; extra == "frozen"
284
286
  Requires-Dist: sqids==0.5.1; extra == "frozen"
285
- Requires-Dist: sqlparse==0.5.3; extra == "frozen"
287
+ Requires-Dist: sqlparse==0.5.4; extra == "frozen"
286
288
  Requires-Dist: sunpy==6.1.1; extra == "frozen"
287
289
  Requires-Dist: tabulate==0.9.0; extra == "frozen"
288
290
  Requires-Dist: talus==1.3.4; extra == "frozen"
@@ -297,16 +299,17 @@ Requires-Dist: traitlets==5.14.3; extra == "frozen"
297
299
  Requires-Dist: typing-inspection==0.4.2; extra == "frozen"
298
300
  Requires-Dist: typing_extensions==4.15.0; extra == "frozen"
299
301
  Requires-Dist: tzdata==2025.2; extra == "frozen"
302
+ Requires-Dist: tzlocal==5.3.1; extra == "frozen"
300
303
  Requires-Dist: uc-micro-py==1.0.3; extra == "frozen"
301
304
  Requires-Dist: uncertainties==3.2.3; extra == "frozen"
302
- Requires-Dist: universal_pathlib==0.3.5; extra == "frozen"
305
+ Requires-Dist: universal_pathlib==0.3.6; extra == "frozen"
303
306
  Requires-Dist: urllib3==2.5.0; extra == "frozen"
304
307
  Requires-Dist: vine==5.1.0; extra == "frozen"
305
308
  Requires-Dist: voluptuous==0.15.2; extra == "frozen"
306
309
  Requires-Dist: wcwidth==0.2.14; extra == "frozen"
307
310
  Requires-Dist: wirerope==1.0.0; extra == "frozen"
308
311
  Requires-Dist: wrapt==1.17.3; extra == "frozen"
309
- Requires-Dist: yamale==6.0.0; extra == "frozen"
312
+ Requires-Dist: yamale==6.1.0; extra == "frozen"
310
313
  Requires-Dist: yarl==1.22.0; extra == "frozen"
311
314
  Requires-Dist: zipp==3.23.0; extra == "frozen"
312
315
 
@@ -1,3 +1,22 @@
1
+ v5.0.0 (2025-12-02)
2
+ ===================
3
+
4
+
5
+
6
+
7
+ - Major update to the gain algorithm to mitigate polarization artifacts in L1 science frames. This change can be split into
8
+ three parts. See the `gain correction <https://docs.dkist.nso.edu/projects/visp/en/stable/gain_correction.html>`_ page for more information.
9
+
10
+ #. Compute a single gain correction image for each beam. In the past we had computed a separate gain image for each modstate as well, but this was found to couple residual polarization structure into the final science frames.
11
+
12
+ #. Stop "refining" (i.e., applying small spectral offsets to) the characteristic solar spectrum on a per-spatial-pixel basis. This was initially done to minimize line residuals in Telluric lines but was found to have a more-negative on polarimetric residuals.
13
+
14
+ #. Separate vignetting caused by aperture masks from the solar signal used to remove spectral lines in the final gain image. This is done by fitting a solar atlas and taking the deviation in continuum to be the vignetting signal.
15
+
16
+ Computing a single gain per beam will greatly reduce the polarization artifacts in L1 data. Measuring the vignette
17
+ signal directly will further reduce these artifacts and improve flatness across the array. (`#246 <https://bitbucket.org/dkistdc/dkist-processing-visp/pull-requests/246>`__)
18
+
19
+
1
20
  v4.0.0 (2025-11-12)
2
21
  ===================
3
22
 
@@ -2,12 +2,15 @@
2
2
 
3
3
  from enum import Enum
4
4
 
5
+ import astropy.units as u
6
+ from astropy.units import Quantity
5
7
  from dkist_processing_common.models.constants import ConstantsBase
6
8
 
7
9
 
8
10
  class VispBudName(Enum):
9
11
  """Names to be used in Visp buds."""
10
12
 
13
+ arm_id = "ARM_ID"
11
14
  num_raster_steps = "NUM_RASTER_STEPS"
12
15
  polarimeter_mode = "POLARIMETER_MODE"
13
16
  wavelength = "WAVELENGTH"
@@ -22,6 +25,10 @@ class VispBudName(Enum):
22
25
  polcal_readout_exp_times = "POLCAL_READOUT_EXP_TIMES"
23
26
  non_dark_task_readout_exp_times = "NON_DARK_TASK_READOUT_EXP_TIMES"
24
27
  num_map_scans = "NUM_MAP_SCANS"
28
+ incident_light_angle_deg = "INCIDENT_LIGHT_ANGLE_DEG"
29
+ reflected_light_angle_deg = "REFLECTED_LIGHT_ANGLE_DEG"
30
+ grating_constant_inverse_mm = "GRATING_CONSTANT_INVERSE_MM"
31
+ solar_gain_ip_start_time = "SOLAR_GAIN_IP_START_TIME"
25
32
  axis_1_type = "AXIS_1_TYPE"
26
33
  axis_2_type = "AXIS_2_TYPE"
27
34
  axis_3_type = "AXIS_3_TYPE"
@@ -31,6 +38,16 @@ class VispBudName(Enum):
31
38
  class VispConstants(ConstantsBase):
32
39
  """Visp specific constants to add to the common constants."""
33
40
 
41
+ @property
42
+ def arm_id(self) -> str:
43
+ """
44
+ Return the current ViSP arm ID.
45
+
46
+ Arm IDs are ints in the headers, but we convert them to str here because that's what downstream machinery expects
47
+ the type to be.
48
+ """
49
+ return str(self._db_dict[VispBudName.arm_id])
50
+
34
51
  @property
35
52
  def wavelength(self) -> float:
36
53
  """Wavelength."""
@@ -76,17 +93,17 @@ class VispConstants(ConstantsBase):
76
93
  raise ValueError(f"No init set known for {retarder_name = }")
77
94
 
78
95
  @property
79
- def lamp_exposure_times(self) -> [float]:
96
+ def lamp_exposure_times(self) -> list[float]:
80
97
  """Find the lamp exposure time."""
81
98
  return self._db_dict[VispBudName.lamp_exposure_times.value]
82
99
 
83
100
  @property
84
- def solar_exposure_times(self) -> [float]:
101
+ def solar_exposure_times(self) -> list[float]:
85
102
  """Find the solar exposure time."""
86
103
  return self._db_dict[VispBudName.solar_exposure_times.value]
87
104
 
88
105
  @property
89
- def polcal_exposure_times(self) -> [float]:
106
+ def polcal_exposure_times(self) -> list[float]:
90
107
  """Find the polarization calibration exposure time."""
91
108
  if self.correct_for_polarization:
92
109
  return self._db_dict[VispBudName.polcal_exposure_times.value]
@@ -94,22 +111,22 @@ class VispConstants(ConstantsBase):
94
111
  return []
95
112
 
96
113
  @property
97
- def observe_exposure_times(self) -> [float]:
114
+ def observe_exposure_times(self) -> list[float]:
98
115
  """Find the observation exposure time."""
99
116
  return self._db_dict[VispBudName.observe_exposure_times.value]
100
117
 
101
118
  @property
102
- def lamp_readout_exp_times(self) -> [float]:
119
+ def lamp_readout_exp_times(self) -> list[float]:
103
120
  """Find the lamp readout exposure time."""
104
121
  return self._db_dict[VispBudName.lamp_readout_exp_times.value]
105
122
 
106
123
  @property
107
- def solar_readout_exp_times(self) -> [float]:
124
+ def solar_readout_exp_times(self) -> list[float]:
108
125
  """Find the solar readout exposure time."""
109
126
  return self._db_dict[VispBudName.solar_readout_exp_times.value]
110
127
 
111
128
  @property
112
- def polcal_readout_exp_times(self) -> [float]:
129
+ def polcal_readout_exp_times(self) -> list[float]:
113
130
  """Find the polarization calibration readout exposure time."""
114
131
  if self.correct_for_polarization:
115
132
  return self._db_dict[VispBudName.polcal_readout_exp_times.value]
@@ -117,7 +134,7 @@ class VispConstants(ConstantsBase):
117
134
  return []
118
135
 
119
136
  @property
120
- def non_dark_task_readout_exp_times(self) -> [float]:
137
+ def non_dark_task_readout_exp_times(self) -> list[float]:
121
138
  """
122
139
  Find all readout exposure times that *need* to exist in a dark IP.
123
140
 
@@ -127,10 +144,34 @@ class VispConstants(ConstantsBase):
127
144
  return self._db_dict[VispBudName.non_dark_task_readout_exp_times.value]
128
145
 
129
146
  @property
130
- def observe_readout_exp_times(self) -> [float]:
147
+ def observe_readout_exp_times(self) -> list[float]:
131
148
  """Find the observation readout exposure time."""
132
149
  return self._db_dict[VispBudName.observe_readout_exp_times.value]
133
150
 
151
+ @property
152
+ def incident_light_angle_deg(self) -> Quantity:
153
+ """Return the spectrograph incident light angle [deg]."""
154
+ return self._db_dict[VispBudName.incident_light_angle_deg] * u.deg
155
+
156
+ @property
157
+ def reflected_light_angle_deg(self) -> Quantity:
158
+ """
159
+ Return the spectrograph reflected light angle [deg].
160
+
161
+ This angle is the incident light angle plus the angular position of the ViSP arm.
162
+ """
163
+ return self._db_dict[VispBudName.reflected_light_angle_deg] * u.deg
164
+
165
+ @property
166
+ def grating_constant_inverse_mm(self) -> Quantity:
167
+ """Return the spectrograph grating constant [1/mm]."""
168
+ return self._db_dict[VispBudName.grating_constant_inverse_mm] / u.mm
169
+
170
+ @property
171
+ def solar_gain_ip_start_time(self) -> str:
172
+ """Return the start time of the SOLAR GAIN Instrument Program."""
173
+ return self._db_dict[VispBudName.solar_gain_ip_start_time]
174
+
134
175
  @property
135
176
  def axis_1_type(self) -> str:
136
177
  """Find the type of the first array axis."""
@@ -6,11 +6,15 @@ from enum import StrEnum
6
6
  class VispMetadataKey(StrEnum):
7
7
  """Controlled list of names for FITS metadata header keys."""
8
8
 
9
+ arm_id = "VSPARMID"
10
+ number_of_modulator_states = "VSPNUMST"
9
11
  raster_scan_step = "VSPSTP"
10
12
  total_raster_steps = "VSPNSTP"
11
13
  modulator_state = "VSPSTNUM"
12
- number_of_modulator_states = "VSPNUMST"
13
14
  polarimeter_mode = "VISP_006"
15
+ grating_angle_deg = "VSPGRTAN"
16
+ arm_position_deg = "VSPARMPS"
17
+ grating_constant_inverse_mm = "VSPGRTCN"
14
18
  axis_1_type = "CTYPE1"
15
19
  axis_2_type = "CTYPE2"
16
20
  axis_3_type = "CTYPE3"
@@ -0,0 +1,10 @@
1
+ """Controlled list of quality metric codes."""
2
+
3
+ from enum import StrEnum
4
+
5
+
6
+ class VispMetricCode(StrEnum):
7
+ """Controlled list of quality metric codes."""
8
+
9
+ solar_first_vignette = "SOLAR_CAL_FIRST_VIGNETTE"
10
+ solar_final_vignette = "SOLAR_CAL_FINAL_VIGNETTE"
@@ -1,9 +1,14 @@
1
1
  """Visp calibration pipeline parameters."""
2
2
 
3
3
  from datetime import datetime
4
+ from random import randint
5
+ from typing import Any
4
6
 
7
+ import astropy.units as u
8
+ from dkist_processing_common.models.parameters import ParameterArmIdMixin
5
9
  from dkist_processing_common.models.parameters import ParameterBase
6
10
  from dkist_processing_common.models.parameters import ParameterWavelengthMixin
11
+ from solar_wavelength_calibration import DownloadConfig
7
12
 
8
13
 
9
14
  class VispParsingParameters(ParameterBase):
@@ -22,7 +27,7 @@ class VispParsingParameters(ParameterBase):
22
27
  )
23
28
 
24
29
 
25
- class VispParameters(ParameterBase, ParameterWavelengthMixin):
30
+ class VispParameters(ParameterBase, ParameterWavelengthMixin, ParameterArmIdMixin):
26
31
  """Put all Visp parameters parsed from the input dataset document in a single property."""
27
32
 
28
33
  @property
@@ -69,7 +74,7 @@ class VispParameters(ParameterBase, ParameterWavelengthMixin):
69
74
 
70
75
  @property
71
76
  def hairline_mask_spatial_smoothing_width_px(self) -> float:
72
- """Amount to smooth the hairling mask in the spatial direction.
77
+ """Amount to smooth the hairline mask in the spatial direction.
73
78
 
74
79
  This helps capture the higher-flux wings of the hairlines that would otherwise require a `hairline_fraction`
75
80
  that was so low it captures other optical features.
@@ -134,9 +139,34 @@ class VispParameters(ParameterBase, ParameterWavelengthMixin):
134
139
  return self._find_most_recent_past_value("visp_geo_poly_fit_order")
135
140
 
136
141
  @property
137
- def solar_spectral_avg_window(self):
142
+ def geo_zone_prominence(self):
143
+ """Relative peak prominence threshold used to identify strong spectral features."""
144
+ return self._find_parameter_closest_wavelength("visp_geo_zone_prominence")
145
+
146
+ @property
147
+ def geo_zone_width(self):
148
+ """Pixel width used to search for strong spectral features."""
149
+ return self._find_parameter_closest_wavelength("visp_geo_zone_width")
150
+
151
+ @property
152
+ def geo_zone_bg_order(self):
153
+ """Order of polynomial fit used to remove continuum when identifying strong spectral features."""
154
+ return self._find_parameter_closest_wavelength("visp_geo_zone_bg_order")
155
+
156
+ @property
157
+ def geo_zone_normalization_percentile(self):
158
+ """Fraction of CDF to use for normalizing spectrum when search for strong features."""
159
+ return self._find_parameter_closest_wavelength("visp_geo_zone_normalization_percentile")
160
+
161
+ @property
162
+ def geo_zone_rel_height(self):
163
+ """Relative height at which to compute the width of strong spectral features."""
164
+ return self._find_most_recent_past_value("visp_geo_zone_rel_height")
165
+
166
+ @property
167
+ def solar_spatial_median_filter_width_px(self):
138
168
  """Pixel width of spatial median filter used to compute characteristic solar spectra."""
139
- return self._find_parameter_closest_wavelength("visp_solar_spectral_avg_window")
169
+ return self._find_parameter_closest_wavelength("visp_solar_spatial_median_filter_width_px")
140
170
 
141
171
  @property
142
172
  def solar_characteristic_spatial_normalization_percentile(self) -> float:
@@ -146,29 +176,108 @@ class VispParameters(ParameterBase, ParameterWavelengthMixin):
146
176
  )
147
177
 
148
178
  @property
149
- def solar_zone_prominence(self):
150
- """Relative peak prominence threshold used to identify strong spectral features."""
151
- return self._find_parameter_closest_wavelength("visp_solar_zone_prominence")
179
+ def solar_vignette_initial_continuum_poly_fit_order(self) -> int:
180
+ """
181
+ Define the order of polynomial to use when fitting the initial continuum function.
182
+
183
+ Note that "initial" in this context does not refer to an initial guess in the wavecal fitter, but rather the
184
+ fact that this represents the initial estimate of the vignette signal.
185
+ """
186
+ return self._find_most_recent_past_value(
187
+ "visp_solar_vignette_initial_continuum_poly_fit_order"
188
+ )
152
189
 
153
190
  @property
154
- def solar_zone_width(self):
155
- """Pixel width used to search for strong spectral features."""
156
- return self._find_parameter_closest_wavelength("visp_solar_zone_width")
191
+ def solar_vignette_crval_bounds_px(self) -> float:
192
+ """
193
+ Define the bounds (in *pixels*) on crval when fitting the initial vignette signal.
194
+
195
+ The actual bounds on the value of crval are equal to ± the initial dispersion times this number. Note that the
196
+ total range searched by the fitting algorithm will be twice this number (in pixels).
197
+ """
198
+ return self._find_most_recent_past_value("visp_solar_vignette_crval_bounds_px") * u.pix
157
199
 
158
200
  @property
159
- def solar_zone_bg_order(self):
160
- """Order of polynomial fit used to remove continuum when identifying strong spectral features."""
161
- return self._find_parameter_closest_wavelength("visp_solar_zone_bg_order")
201
+ def solar_vignette_dispersion_bounds_fraction(self) -> float:
202
+ """
203
+ Define the ± fraction away from the initial value for bounds on dispersion when fitting the initial vignette signal.
204
+
205
+ This value should be between 0 and 1. For example, the minimum bound is `init_value * (1 - solar_vignette_dispersion_bounds_fraction)`.
206
+ """
207
+ return self._find_most_recent_past_value("visp_solar_vignette_dispersion_bounds_fraction")
162
208
 
163
209
  @property
164
- def solar_zone_normalization_percentile(self):
165
- """Fraction of CDF to use for normalzing spectrum when search for strong features."""
166
- return self._find_parameter_closest_wavelength("visp_solar_zone_normalization_percentile")
210
+ def solar_vignette_wavecal_fit_kwargs(self) -> dict[str, Any]:
211
+ """Define extra keyword arguments to pass to the wavelength calibration fitter."""
212
+ doc_dict = self._find_most_recent_past_value("visp_solar_vignette_wavecal_fit_kwargs")
213
+ rng_kwarg = dict()
214
+ fitting_method = doc_dict.get("method", False)
215
+ if fitting_method in ["basinhopping", "differential_evolution", "dual_annealing"]:
216
+ rng = randint(1, 1_000_000)
217
+ rng_kwarg["rng"] = rng
218
+
219
+ # The order here allows us to override `rng` in a parameter value
220
+ fit_kwargs = rng_kwarg | doc_dict
221
+ return fit_kwargs
167
222
 
168
223
  @property
169
- def solar_zone_rel_height(self):
170
- """Relative height at which to compute the width of strong spectral features."""
171
- return self._find_most_recent_past_value("visp_solar_zone_rel_height")
224
+ def solar_vignette_spectral_poly_fit_order(self) -> int:
225
+ """Define the order of spectral polynomial used when computing the full, 2D vignette signal."""
226
+ return self._find_most_recent_past_value("visp_solar_vignette_spectral_poly_fit_order")
227
+
228
+ @property
229
+ def solar_vignette_min_samples(self) -> float:
230
+ """Return fractional number of samples required for the RANSAC regressor used to fit the 2D vignette signal."""
231
+ return self._find_most_recent_past_value("visp_solar_vignette_min_samples")
232
+
233
+ @property
234
+ def wavecal_camera_lens_parameters(self) -> list[u.Quantity]:
235
+ r"""
236
+ Define the 2nd order polynomial coefficients for computing the total camera focal length as a function of wavelength.
237
+
238
+ The total focal length of the lens is :math:`f = a_0 + a_1\lambda + a_2\lambda^2` where this property is
239
+ :math:`[a_0, a_1, a_2]`
240
+ """
241
+ value_list = self._find_parameter_for_arm("visp_wavecal_camera_lens_parameters")
242
+ unit_list = [u.m, u.m / u.nm, u.m / u.nm**2]
243
+ return [v * u for v, u in zip(value_list, unit_list)]
244
+
245
+ @property
246
+ def wavecal_pixel_pitch_micron_per_pix(self) -> u.Quantity:
247
+ """Define the physical size of ViSP detector pixels."""
248
+ return (
249
+ self._find_most_recent_past_value("visp_wavecal_pixel_pitch_micron_per_pix")
250
+ * u.micron
251
+ / u.pix
252
+ )
253
+
254
+ @property
255
+ def wavecal_atlas_download_config(self) -> DownloadConfig:
256
+ """Define the `~solar_wavelength_calibration.DownloadConfig` used to grab the Solar atlas used for wavelength calibration."""
257
+ config_dict = self._find_most_recent_past_value("visp_wavecal_atlas_download_config")
258
+ return DownloadConfig.model_validate(config_dict)
259
+
260
+ @property
261
+ def wavecal_init_crval_guess_normalization_percentile(self) -> float | None:
262
+ """Define the CDF percentage used to normalize the Atlas to the input spectrum level when computing an initial CRVAL guess."""
263
+ return self._find_most_recent_past_value(
264
+ "visp_wavecal_init_crval_guess_normalization_percentile"
265
+ )
266
+
267
+ @property
268
+ def wavecal_init_resolving_power(self) -> int:
269
+ """Define the initial guess for ViSP resolving power in wavecal fits."""
270
+ return self._find_most_recent_past_value("visp_wavecal_init_resolving_power")
271
+
272
+ @property
273
+ def wavecal_init_straylight_fraction(self) -> float:
274
+ """Define the initial guess for straylight fraction in wavecal fits."""
275
+ return self._find_most_recent_past_value("visp_wavecal_init_straylight_fraction")
276
+
277
+ @property
278
+ def wavecal_init_opacity_factor(self) -> float:
279
+ """Define the initial guess for opacity factor in wavecal fits."""
280
+ return self._find_most_recent_past_value("visp_wavecal_init_opacity_factor")
172
281
 
173
282
  @property
174
283
  def polcal_spatial_median_filter_width_px(self) -> int: