dkist-processing-cryonirsp 0.0.47__tar.gz → 0.0.49__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.

Potentially problematic release.


This version of dkist-processing-cryonirsp might be problematic. Click here for more details.

Files changed (119) hide show
  1. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/CHANGELOG.rst +19 -0
  2. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/PKG-INFO +1 -1
  3. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/bitbucket-pipelines.yml +1 -1
  4. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/models/constants.py +66 -22
  5. dkist_processing_cryonirsp-0.0.49/dkist_processing_cryonirsp/models/exposure_conditions.py +26 -0
  6. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/models/parameters.py +1 -3
  7. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/models/tags.py +18 -0
  8. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/parsers/cryonirsp_l0_fits_access.py +8 -0
  9. dkist_processing_cryonirsp-0.0.49/dkist_processing_cryonirsp/parsers/exposure_conditions.py +163 -0
  10. dkist_processing_cryonirsp-0.0.49/dkist_processing_cryonirsp/parsers/map_repeats.py +40 -0
  11. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/parsers/optical_density_filters.py +1 -3
  12. dkist_processing_cryonirsp-0.0.49/dkist_processing_cryonirsp/parsers/scan_step.py +412 -0
  13. dkist_processing_cryonirsp-0.0.49/dkist_processing_cryonirsp/parsers/time.py +49 -0
  14. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tasks/ci_science.py +18 -15
  15. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tasks/dark.py +16 -10
  16. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tasks/gain.py +23 -24
  17. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tasks/instrument_polarization.py +56 -35
  18. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tasks/mixin/intermediate_frame.py +19 -7
  19. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tasks/mixin/linearized_frame.py +42 -40
  20. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tasks/parse.py +27 -15
  21. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tasks/science_base.py +9 -8
  22. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tasks/sp_geometric.py +7 -7
  23. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tasks/sp_science.py +14 -15
  24. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tasks/sp_solar_gain.py +49 -45
  25. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tests/conftest.py +17 -16
  26. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tests/header_models.py +23 -35
  27. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tests/local_trial_workflows/l0_to_l1.py +12 -11
  28. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tests/test_ci_science.py +11 -3
  29. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tests/test_cryo_constants.py +11 -3
  30. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tests/test_dark.py +71 -55
  31. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tests/test_gain.py +10 -11
  32. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tests/test_instrument_polarization.py +20 -12
  33. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tests/test_linearity_correction.py +5 -1
  34. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tests/test_parse.py +603 -148
  35. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tests/test_sp_geometric.py +23 -9
  36. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tests/test_sp_science.py +8 -3
  37. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tests/test_sp_solar.py +10 -3
  38. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp.egg-info/PKG-INFO +1 -1
  39. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp.egg-info/SOURCES.txt +2 -1
  40. dkist_processing_cryonirsp-0.0.47/dkist_processing_cryonirsp/models/optical_density_filter_names.py +0 -12
  41. dkist_processing_cryonirsp-0.0.47/dkist_processing_cryonirsp/parsers/map_repeats.py +0 -157
  42. dkist_processing_cryonirsp-0.0.47/dkist_processing_cryonirsp/parsers/scan_step.py +0 -103
  43. dkist_processing_cryonirsp-0.0.47/dkist_processing_cryonirsp/parsers/time.py +0 -192
  44. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/.gitignore +0 -0
  45. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/.pre-commit-config.yaml +0 -0
  46. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/.readthedocs.yml +0 -0
  47. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/README.rst +0 -0
  48. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/SCIENCE_CHANGELOG.rst +0 -0
  49. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/changelog/.gitempty +0 -0
  50. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/check_changelog_updated.sh +0 -0
  51. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/__init__.py +0 -0
  52. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/models/__init__.py +0 -0
  53. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/models/filter.py +0 -0
  54. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/models/task_name.py +0 -0
  55. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/parsers/__init__.py +0 -0
  56. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/parsers/cryonirsp_l1_fits_access.py +0 -0
  57. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/parsers/measurements.py +0 -0
  58. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/parsers/modstates.py +0 -0
  59. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/parsers/polarimetric_check.py +0 -0
  60. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/parsers/wavelength.py +0 -0
  61. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tasks/__init__.py +0 -0
  62. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tasks/assemble_movie.py +0 -0
  63. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tasks/bad_pixel_map.py +0 -0
  64. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tasks/beam_boundaries_base.py +0 -0
  65. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tasks/ci_beam_boundaries.py +0 -0
  66. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tasks/cryonirsp_base.py +0 -0
  67. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tasks/l1_output_data.py +0 -0
  68. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tasks/linearity_correction.py +0 -0
  69. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tasks/make_movie_frames.py +0 -0
  70. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tasks/mixin/__init__.py +0 -0
  71. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tasks/mixin/beam_access.py +0 -0
  72. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tasks/mixin/corrections.py +0 -0
  73. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tasks/mixin/shift_measurements.py +0 -0
  74. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tasks/quality_metrics.py +0 -0
  75. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tasks/sp_beam_boundaries.py +0 -0
  76. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tasks/trial_output_data.py +0 -0
  77. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tasks/write_l1.py +0 -0
  78. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tests/__init__.py +0 -0
  79. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tests/local_trial_workflows/__init__.py +0 -0
  80. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tests/local_trial_workflows/l0_cals_only.py +0 -0
  81. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tests/local_trial_workflows/linearize_only.py +0 -0
  82. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tests/local_trial_workflows/local_trial_helpers.py +0 -0
  83. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tests/test_assemble_movie.py +0 -0
  84. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tests/test_bad_pixel_maps.py +0 -0
  85. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tests/test_build_quality_report.py +0 -0
  86. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tests/test_ci_beam_boundaries.py +0 -0
  87. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tests/test_cryo_base.py +0 -0
  88. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tests/test_make_movie_frames.py +0 -0
  89. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tests/test_parameters.py +0 -0
  90. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tests/test_quality.py +0 -0
  91. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tests/test_sp_beam_boundaries.py +0 -0
  92. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tests/test_sp_make_movie_frames.py +0 -0
  93. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tests/test_submit_qualilty.py +0 -0
  94. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tests/test_trial_output_data.py +0 -0
  95. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tests/test_workflows.py +0 -0
  96. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/tests/test_write_l1.py +0 -0
  97. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/workflows/__init__.py +0 -0
  98. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/workflows/ci_l0_processing.py +0 -0
  99. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/workflows/sp_l0_processing.py +0 -0
  100. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp/workflows/trial_workflows.py +0 -0
  101. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp.egg-info/dependency_links.txt +0 -0
  102. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp.egg-info/requires.txt +0 -0
  103. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/dkist_processing_cryonirsp.egg-info/top_level.txt +0 -0
  104. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/docs/Makefile +0 -0
  105. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/docs/changelog.rst +0 -0
  106. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/docs/conf.py +0 -0
  107. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/docs/index.rst +0 -0
  108. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/docs/l0_to_l1_cryonirsp_ci.rst +0 -0
  109. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/docs/l0_to_l1_cryonirsp_sp.rst +0 -0
  110. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/docs/make.bat +0 -0
  111. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/docs/requirements.txt +0 -0
  112. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/docs/requirements_table.rst +0 -0
  113. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/docs/scientific_changelog.rst +0 -0
  114. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/licenses/LICENSE.rst +0 -0
  115. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/pyproject.toml +0 -0
  116. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/science_towncrier.sh +0 -0
  117. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/setup.cfg +0 -0
  118. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/setup.py +0 -0
  119. {dkist_processing_cryonirsp-0.0.47 → dkist_processing_cryonirsp-0.0.49}/towncrier_science.toml +0 -0
@@ -1,3 +1,22 @@
1
+ v0.0.49 (2024-03-15)
2
+ ====================
3
+
4
+ Bugfixes
5
+ --------
6
+
7
+ - Correctly identify *partially* incomplete scan steps. Previously any scan step that had at least a single file was
8
+ considered to exist in its entirety, even if some of its files were missing. (`#108 <https://bitbucket.org/dkistdc/dkist-processing-cryonirsp/pull-requests/108>`__)
9
+
10
+
11
+ v0.0.48 (2024-03-15)
12
+ ====================
13
+
14
+ Bugfixes
15
+ --------
16
+
17
+ - Fixes a bug in `ParseL0CryonirspLinearizedData` which conflated dark frames with the same exposure time but different OD filters. We need to be able to identify dark frame based on their exposure conditions (exposure time, Optical Density Filter) and use the exposure conditions to correlate the sets of dark frames with the frames sets they will be used to correct (lamp gain, solar gain, observe). (`#106 <https://bitbucket.org/dkistdc/dkist-processing-cryonirsp/pull-requests/106>`__)
18
+
19
+
1
20
  v0.0.47 (2024-03-15)
2
21
  ====================
3
22
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dkist_processing_cryonirsp
3
- Version: 0.0.47
3
+ Version: 0.0.49
4
4
  Summary: Science processing code for the Cryo-NIRSP instrument on DKIST
5
5
  Home-page: https://bitbucket.org/dkistdc/dkist_processing_cryonirsp/src/main/
6
6
  Author: NSO / AURA
@@ -50,7 +50,7 @@ definitions:
50
50
  script:
51
51
  - pip install -U pip
52
52
  - pip install .[test]
53
- - pytest -v -n auto --cov -m "not development" dkist_processing_cryonirsp
53
+ - pytest -v -n auto --dist worksteal --cov -m "not development" dkist_processing_cryonirsp
54
54
  services:
55
55
  - redis
56
56
  - step: &push_workflow
@@ -5,6 +5,8 @@ from enum import unique
5
5
  from dkist_processing_common.models.constants import BudName
6
6
  from dkist_processing_common.models.constants import ConstantsBase
7
7
 
8
+ from dkist_processing_cryonirsp.models.exposure_conditions import ExposureConditions
9
+
8
10
 
9
11
  @unique
10
12
  class CryonirspBudName(Enum):
@@ -19,11 +21,16 @@ class CryonirspBudName(Enum):
19
21
  camera_readout_mode = "CAM_READOUT_MODE"
20
22
  num_meas = "NUM_MEAS"
21
23
  time_obs_list = "TIME_OBS_LIST"
22
- lamp_gain_exposure_times = "LAMP_GAIN_EXPOSURE_TIMES"
23
- solar_gain_exposure_times = "SOLAR_GAIN_EXPOSURE_TIMES"
24
- polcal_exposure_times = "POLCAL_EXPOSURE_TIMES"
25
- observe_exposure_times = "OBSERVE_EXPOSURE_TIMES"
26
- non_dark_and_non_polcal_task_exposure_times = "NON_DARK_AND_NON_POLCAL_TASK_EXPOSURE_TIMES"
24
+ exposure_conditions_list = "EXPOSURE_CONDITIONS_LIST"
25
+ dark_frame_exposure_conditions_list = "DARK_FRAME_EXPOSURE_CONDITIONS_LIST"
26
+ lamp_gain_exposure_conditions_list = "LAMP_GAIN_EXPOSURE_CONDITIONS_LIST"
27
+ solar_gain_exposure_conditions_list = "SOLAR_GAIN_EXPOSURE_CONDITIONS_LIST"
28
+ polcal_exposure_conditions_list = "POLCAL_EXPOSURE_CONDITIONS_LIST"
29
+ observe_exposure_conditions_list = "OBSERVE_EXPOSURE_CONDITIONS_LIST"
30
+ non_dark_and_non_polcal_task_exposure_conditions_list = (
31
+ "NON_DARK_AND_NON_POLCAL_TASK_EXPOSURE_CONDITIONS_LIST"
32
+ )
33
+ picky_dark_exposure_conditions_list = "PICKY_DARK_EXPOSURE_CONDITIONS_LIST"
27
34
  modulator_spin_mode = "MODULATOR_SPIN_MODE"
28
35
  axis_1_type = "AXIS_1_TYPE"
29
36
  axis_2_type = "AXIS_2_TYPE"
@@ -32,7 +39,6 @@ class CryonirspBudName(Enum):
32
39
  roi_1_origin_y = "ROI_1_ORIGIN_Y"
33
40
  roi_1_size_x = "ROI_1_SIZE_X"
34
41
  roi_1_size_y = "ROI_1_SIZE_Y"
35
- picky_dark_exposure_times = "PICKY_DARK_EXPOSURE_TIMES"
36
42
  optical_density_filter_picky_bud = "OPTICAL_DENSITY_FILTER_PICKY_BUD"
37
43
 
38
44
 
@@ -83,32 +89,70 @@ class CryonirspConstants(ConstantsBase):
83
89
  return self._db_dict[CryonirspBudName.time_obs_list.value]
84
90
 
85
91
  @property
86
- def lamp_gain_exposure_times(self) -> [float]:
87
- """Construct a list of lamp gain exposure times for the dataset."""
88
- return self._db_dict[CryonirspBudName.lamp_gain_exposure_times.value]
92
+ def exposure_conditions_list(self) -> [ExposureConditions]:
93
+ """Construct a list of ExposureConditions tuples for the dataset."""
94
+ raw_conditions: list[list[int, str]] = self._db_dict[
95
+ CryonirspBudName.exposure_conditions.value
96
+ ]
97
+ conditions = [ExposureConditions(*item) for item in raw_conditions]
98
+ return conditions
99
+
100
+ @property
101
+ def dark_exposure_conditions_list(self) -> [ExposureConditions]:
102
+ """Construct a list of dark frame ExposureConditions tuples for the dataset."""
103
+ raw_conditions: list[list[int, str]] = self._db_dict[
104
+ CryonirspBudName.dark_frame_exposure_conditions_list.value
105
+ ]
106
+ conditions = [ExposureConditions(*item) for item in raw_conditions]
107
+ return conditions
108
+
109
+ @property
110
+ def lamp_gain_exposure_conditions_list(self) -> [ExposureConditions]:
111
+ """Construct a list of lamp gain ExposureConditions tuples for the dataset."""
112
+ raw_conditions: list[list[int, str]] = self._db_dict[
113
+ CryonirspBudName.lamp_gain_exposure_conditions_list.value
114
+ ]
115
+ conditions = [ExposureConditions(*item) for item in raw_conditions]
116
+ return conditions
89
117
 
90
118
  @property
91
- def solar_gain_exposure_times(self) -> [float]:
92
- """Construct a list of solar gain exposure times for the dataset."""
93
- return self._db_dict[CryonirspBudName.solar_gain_exposure_times.value]
119
+ def solar_gain_exposure_conditions_list(self) -> [ExposureConditions]:
120
+ """Construct a list of solar gain ExposureConditions tuples for the dataset."""
121
+ raw_conditions: list[list[int, str]] = self._db_dict[
122
+ CryonirspBudName.solar_gain_exposure_conditions_list.value
123
+ ]
124
+ conditions = [ExposureConditions(*item) for item in raw_conditions]
125
+ return conditions
94
126
 
95
127
  @property
96
- def polcal_exposure_times(self) -> [float]:
97
- """Construct a list of polcal exposure times for the dataset."""
128
+ def observe_exposure_conditions_list(self) -> [ExposureConditions]:
129
+ """Construct a list of observe ExposureConditions tuples for the dataset."""
130
+ raw_conditions: list[list[int, str]] = self._db_dict[
131
+ CryonirspBudName.observe_exposure_conditions_list.value
132
+ ]
133
+ conditions = [ExposureConditions(*item) for item in raw_conditions]
134
+ return conditions
135
+
136
+ @property
137
+ def polcal_exposure_conditions_list(self) -> [ExposureConditions]:
138
+ """Construct a list of polcal ExposureConditions tuples for the dataset."""
98
139
  if self.correct_for_polarization:
99
- return self._db_dict[CryonirspBudName.polcal_exposure_times.value]
140
+ raw_conditions: list[list[int, str]] = self._db_dict[
141
+ CryonirspBudName.polcal_exposure_conditions_list.value
142
+ ]
143
+ conditions = [ExposureConditions(*item) for item in raw_conditions]
144
+ return conditions
100
145
  else:
101
146
  return []
102
147
 
103
148
  @property
104
- def observe_exposure_times(self) -> [float]:
105
- """Construct a list of observe exposure times."""
106
- return self._db_dict[CryonirspBudName.observe_exposure_times.value]
107
-
108
- @property
109
- def non_dark_and_non_polcal_task_exposure_times(self) -> [float]:
149
+ def non_dark_and_non_polcal_task_exposure_conditions_list(self) -> [ExposureConditions]:
110
150
  """Return a list of all exposure times required for all tasks other than dark and polcal."""
111
- return self._db_dict[CryonirspBudName.non_dark_and_non_polcal_task_exposure_times.value]
151
+ raw_conditions: list[list[int, str]] = self._db_dict[
152
+ CryonirspBudName.non_dark_and_non_polcal_task_exposure_conditions_list.value
153
+ ]
154
+ conditions = [ExposureConditions(*item) for item in raw_conditions]
155
+ return conditions
112
156
 
113
157
  @property
114
158
  def num_modstates(self) -> int:
@@ -0,0 +1,26 @@
1
+ """Support classes for exposure conditions."""
2
+ from collections import namedtuple
3
+ from enum import StrEnum
4
+
5
+ # Number of digits used to round the exposure when creating the ExposureConditions tuple in fits_access
6
+ CRYO_EXP_TIME_ROUND_DIGITS: int = 3
7
+
8
+ """Base class to hold a tuple of exposure time and filter name."""
9
+ ExposureConditionsBase = namedtuple("ExposureConditions", ["exposure_time", "filter_name"])
10
+
11
+
12
+ class ExposureConditions(ExposureConditionsBase):
13
+ """Define str to make tags look reasonable."""
14
+
15
+ def __str__(self):
16
+ return f"{self.exposure_time}_{self.filter_name}"
17
+
18
+
19
+ class AllowableOpticalDensityFilterNames(StrEnum):
20
+ """Enum to implement list of allowable Optical Density Filter names."""
21
+
22
+ G278 = "G278"
23
+ G358 = "G358"
24
+ G408 = "G408"
25
+ OPEN = "OPEN"
26
+ NONE = "NONE"
@@ -6,9 +6,7 @@ import numpy as np
6
6
  from dkist_processing_common.models.parameters import ParameterBase
7
7
  from dkist_processing_common.tasks.mixin.input_dataset import InputDatasetParameterValue
8
8
 
9
- from dkist_processing_cryonirsp.models.optical_density_filter_names import (
10
- AllowableOpticalDensityFilterNames,
11
- )
9
+ from dkist_processing_cryonirsp.models.exposure_conditions import AllowableOpticalDensityFilterNames
12
10
 
13
11
 
14
12
  class CryonirspParameters(ParameterBase):
@@ -5,6 +5,7 @@ from dkist_processing_common.models.tags import StemName
5
5
  from dkist_processing_common.models.tags import Tag
6
6
  from dkist_processing_common.models.task_name import TaskName
7
7
 
8
+ from dkist_processing_cryonirsp.models.exposure_conditions import ExposureConditions
8
9
  from dkist_processing_cryonirsp.models.task_name import CryonirspTaskName
9
10
 
10
11
 
@@ -19,6 +20,7 @@ class CryonirspStemName(str, Enum):
19
20
  meas_num = "MEAS_NUM"
20
21
  modstate = "MODSTATE"
21
22
  map_scan = "MAP_SCAN"
23
+ exposure_conditions = "EXPOSURE_CONDITIONS"
22
24
 
23
25
 
24
26
  class CryonirspTag(Tag):
@@ -147,6 +149,22 @@ class CryonirspTag(Tag):
147
149
  """
148
150
  return cls.format_tag(CryonirspStemName.meas_num, meas_num)
149
151
 
152
+ @classmethod
153
+ def exposure_conditions(cls, exposure_conditions: ExposureConditions) -> str:
154
+ """
155
+ Tags by the measurement number.
156
+
157
+ Parameters
158
+ ----------
159
+ exposure_conditions
160
+ A tuple of (exposure time, filter name)
161
+
162
+ Returns
163
+ -------
164
+ The formatted tag string
165
+ """
166
+ return cls.format_tag(CryonirspStemName.exposure_conditions, exposure_conditions)
167
+
150
168
  @classmethod
151
169
  def task_beam_boundaries(cls) -> str:
152
170
  """Tags intermediate beam boundary calibration objects."""
@@ -2,6 +2,9 @@
2
2
  from astropy.io import fits
3
3
  from dkist_processing_common.parsers.l0_fits_access import L0FitsAccess
4
4
 
5
+ from dkist_processing_cryonirsp.models.exposure_conditions import CRYO_EXP_TIME_ROUND_DIGITS
6
+ from dkist_processing_cryonirsp.models.exposure_conditions import ExposureConditions
7
+
5
8
 
6
9
  class CryonirspRampFitsAccess(L0FitsAccess):
7
10
  """
@@ -84,6 +87,11 @@ class CryonirspL0FitsAccess(L0FitsAccess):
84
87
  self.axis_2_type: str = self.header["CTYPE2"]
85
88
  self.axis_3_type: str = self.header["CTYPE3"]
86
89
  self.obs_ip_start_time = self.header["DKIST011"]
90
+ # The ExposureConditions are a combination of the exposure time and the OD filter name:
91
+ self.exposure_conditions = ExposureConditions(
92
+ round(self.fpa_exposure_time_ms, CRYO_EXP_TIME_ROUND_DIGITS),
93
+ self.header["CNFILTNP"].upper(),
94
+ )
87
95
 
88
96
  @property
89
97
  def cn1_scan_step(self):
@@ -0,0 +1,163 @@
1
+ """Buds to parse the combination of exposure time and filter name."""
2
+ from collections import namedtuple
3
+ from typing import Hashable
4
+ from typing import Type
5
+
6
+ from dkist_processing_common.models.flower_pot import SpilledDirt
7
+ from dkist_processing_common.models.flower_pot import Stem
8
+ from dkist_processing_common.models.flower_pot import Thorn
9
+ from dkist_processing_common.models.task_name import TaskName
10
+ from dkist_processing_common.parsers.task import parse_header_ip_task_with_gains
11
+
12
+ from dkist_processing_cryonirsp.models.constants import CryonirspBudName
13
+ from dkist_processing_cryonirsp.models.exposure_conditions import ExposureConditions
14
+ from dkist_processing_cryonirsp.parsers.cryonirsp_l0_fits_access import CryonirspL0FitsAccess
15
+
16
+ _DARK_AND_POLCAL_TASK_TYPES = (TaskName.dark.value, TaskName.polcal.value)
17
+
18
+
19
+ class CryonirspTaskExposureConditionsBud(Stem):
20
+ """
21
+ Bud to allow custom parsing of exposure conditions based on ip task type.
22
+
23
+ Parameters
24
+ ----------
25
+ stem_name : str
26
+ The name of the stem of the tag
27
+ ip_task_type : str
28
+ Instrument program task type
29
+ """
30
+
31
+ def __init__(self, stem_name: str, ip_task_type: str):
32
+ super().__init__(stem_name=stem_name)
33
+ self.metadata_key = "exposure_conditions"
34
+ self.ip_task_type = ip_task_type
35
+
36
+ def setter(self, fits_obj: CryonirspL0FitsAccess):
37
+ """
38
+ Set the value of the bud.
39
+
40
+ Parameters
41
+ ----------
42
+ fits_obj:
43
+ A single FitsAccess object
44
+ """
45
+ ip_task_type = parse_header_ip_task_with_gains(fits_obj)
46
+ if ip_task_type.lower() == self.ip_task_type.lower():
47
+ return getattr(fits_obj, self.metadata_key)
48
+ return SpilledDirt
49
+
50
+ def getter(self, key: Hashable) -> tuple[ExposureConditions, ...]:
51
+ """Return a list of the ExposureConditions for this ip task type."""
52
+ exposure_conditions_tuple = tuple(sorted(set(self.key_to_petal_dict.values())))
53
+ return exposure_conditions_tuple
54
+
55
+
56
+ class CryonirspNonDarkAndNonPolcalTaskExposureConditionsBud(Stem):
57
+ """For ip task types that are neither DARK nor POLCAL, produce a list of exposure conditions tuples."""
58
+
59
+ def __init__(self):
60
+ super().__init__(
61
+ stem_name=CryonirspBudName.non_dark_and_non_polcal_task_exposure_conditions_list.value
62
+ )
63
+ self.metadata_key = "exposure_conditions"
64
+
65
+ def setter(self, fits_obj: CryonirspL0FitsAccess) -> ExposureConditions | Type[SpilledDirt]:
66
+ """
67
+ Set the task exposure conditions tuple for this fits object.
68
+
69
+ Parameters
70
+ ----------
71
+ fits_obj
72
+ The input fits object
73
+ Returns
74
+ -------
75
+ The exposure time associated with this fits object
76
+ """
77
+ if fits_obj.ip_task_type.upper() not in _DARK_AND_POLCAL_TASK_TYPES:
78
+ return getattr(fits_obj, self.metadata_key)
79
+ return SpilledDirt
80
+
81
+ def getter(self, key: Hashable) -> tuple[ExposureConditions, ...]:
82
+ """
83
+ Get the list of exposure conditions tuples.
84
+
85
+ Parameters
86
+ ----------
87
+ key
88
+ The input key
89
+
90
+ Returns
91
+ -------
92
+ A tuple of (exposure time, filter name) tuples
93
+ """
94
+ exposure_conditions_tuple = tuple(sorted(set(self.key_to_petal_dict.values())))
95
+ return exposure_conditions_tuple
96
+
97
+
98
+ class CryonirspPickyDarkExposureConditionsBud(Stem):
99
+ """Parse exposure conditions tuples to ensure existence of dark frames with the required exposure conditions."""
100
+
101
+ DarkTaskTestAndExposureConditions = namedtuple(
102
+ "DarkTaskTestAndExposureConditions", ["is_dark", "exposure_conditions"]
103
+ )
104
+
105
+ def __init__(self):
106
+ super().__init__(stem_name=CryonirspBudName.picky_dark_exposure_conditions_list.value)
107
+ self.metadata_key = "exposure_conditions"
108
+
109
+ def setter(self, fits_obj: CryonirspL0FitsAccess) -> tuple | Type[SpilledDirt]:
110
+ """
111
+ Set the task exposure conditions tuple and whether it is a DARK task for this fits object.
112
+
113
+ Parameters
114
+ ----------
115
+ fits_obj
116
+ The input fits object
117
+ Returns
118
+ -------
119
+ A tuple of a boolean indicating if the task is a dark task, and the exposure conditions for this fits object
120
+ """
121
+ if fits_obj.ip_task_type.upper() == TaskName.dark.value:
122
+ return self.DarkTaskTestAndExposureConditions(
123
+ is_dark=True, exposure_conditions=getattr(fits_obj, self.metadata_key)
124
+ )
125
+ if fits_obj.ip_task_type.upper() not in _DARK_AND_POLCAL_TASK_TYPES:
126
+ return self.DarkTaskTestAndExposureConditions(
127
+ is_dark=False, exposure_conditions=getattr(fits_obj, self.metadata_key)
128
+ )
129
+ # Polcal falls through
130
+ return SpilledDirt
131
+
132
+ def getter(self, key: Hashable) -> Type[Thorn]:
133
+ """
134
+ Parse all exposure conditions and raise an error if any non-dark exposure condition is missing from the set of dark exposure conditions.
135
+
136
+ Parameters
137
+ ----------
138
+ key
139
+ The input key
140
+
141
+ Returns
142
+ -------
143
+ Thorn
144
+ """
145
+ dark_task_test_and_exposure_conditions_set = set(self.key_to_petal_dict.values())
146
+ dark_exposure_conditions_set = {
147
+ item.exposure_conditions
148
+ for item in dark_task_test_and_exposure_conditions_set
149
+ if item.is_dark
150
+ }
151
+ other_exposure_conditions_set = {
152
+ item.exposure_conditions
153
+ for item in dark_task_test_and_exposure_conditions_set
154
+ if not item.is_dark
155
+ }
156
+ other_exposure_conditions_missing_from_dark_exposure_conditions = (
157
+ other_exposure_conditions_set - dark_exposure_conditions_set
158
+ )
159
+ if other_exposure_conditions_missing_from_dark_exposure_conditions:
160
+ raise ValueError(
161
+ f"Exposure conditions required in the set of dark frames not found. Missing conditions = {other_exposure_conditions_missing_from_dark_exposure_conditions}"
162
+ )
163
+ return Thorn
@@ -0,0 +1,40 @@
1
+ """Stems for organizing files into separate dsps repeats."""
2
+ from dkist_processing_cryonirsp.models.constants import CryonirspBudName
3
+ from dkist_processing_cryonirsp.models.tags import CryonirspStemName
4
+ from dkist_processing_cryonirsp.parsers.scan_step import MapScanStepStemBase
5
+
6
+
7
+ class MapScanFlower(MapScanStepStemBase):
8
+ """Flower for computing and assigning map scan numbers."""
9
+
10
+ def __init__(self):
11
+ super().__init__(stem_name=CryonirspStemName.map_scan.value)
12
+
13
+ def getter(self, key: str) -> int:
14
+ """Compute the map scan number for a single frame.
15
+
16
+ The frame implies a SingleScanStep. That object is then compared to the sorted list of objects for a single
17
+ (raster_step, meas_num, modstate, sub_repeat) tuple. The location within that sorted list is the map scan number.
18
+ """
19
+ return self.get_map_scan_for_key(key)
20
+
21
+
22
+ class NumMapScansBud(MapScanStepStemBase):
23
+ """
24
+ Bud for determining the total number of dsps repeats.
25
+
26
+ Also checks that all scan steps have the same number of dsps repeats.
27
+ """
28
+
29
+ def __init__(self):
30
+ super().__init__(stem_name=CryonirspBudName.num_map_scans.value)
31
+
32
+ def getter(self, key: str) -> int:
33
+ """
34
+ Compute the total number of dsps repeats.
35
+
36
+ The number of map_scans for every scan step are calculated and if a map_scan is incomplete,
37
+ it will not be included.
38
+ Assumes the incomplete map_scan is always the last one due to summit abort or cancellation.
39
+ """
40
+ return self.number_of_complete_map_scans
@@ -4,9 +4,7 @@ from typing import Hashable
4
4
  from dkist_processing_common.models.flower_pot import Stem
5
5
  from dkist_processing_common.models.flower_pot import Thorn
6
6
 
7
- from dkist_processing_cryonirsp.models.optical_density_filter_names import (
8
- AllowableOpticalDensityFilterNames,
9
- )
7
+ from dkist_processing_cryonirsp.models.exposure_conditions import AllowableOpticalDensityFilterNames
10
8
  from dkist_processing_cryonirsp.parsers.cryonirsp_l0_fits_access import CryonirspRampFitsAccess
11
9
 
12
10
  ALLOWABLE_OPTICAL_DENSITY_FILTERS = {f for f in AllowableOpticalDensityFilterNames}