dkist-processing-cryonirsp 2.0.1__tar.gz → 2.0.2__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 (137) hide show
  1. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/CHANGELOG.rst +13 -0
  2. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/PKG-INFO +28 -26
  3. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/models/constants.py +19 -28
  4. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/models/exposure_conditions.py +19 -11
  5. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/models/tags.py +1 -1
  6. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/parsers/cryonirsp_l0_fits_access.py +2 -1
  7. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/parsers/exposure_conditions.py +33 -22
  8. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/parsers/polarimetric_check.py +16 -15
  9. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tests/conftest.py +27 -9
  10. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tests/header_models.py +6 -1
  11. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tests/test_ci_science.py +2 -2
  12. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tests/test_cryo_constants.py +11 -3
  13. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tests/test_dark.py +24 -12
  14. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tests/test_gain.py +6 -2
  15. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tests/test_instrument_polarization.py +7 -5
  16. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tests/test_linearity_correction.py +2 -2
  17. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tests/test_parse.py +124 -58
  18. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tests/test_polcal_as_science.py +3 -3
  19. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tests/test_sp_geometric.py +6 -5
  20. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tests/test_sp_science.py +2 -2
  21. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tests/test_sp_solar.py +2 -2
  22. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tests/test_write_dataset_extras.py +12 -5
  23. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp.egg-info/PKG-INFO +28 -26
  24. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp.egg-info/requires.txt +27 -25
  25. dkist_processing_cryonirsp-2.0.2/dkist_processing_cryonirsp.egg-info/scm_version.json +8 -0
  26. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/pyproject.toml +29 -27
  27. dkist_processing_cryonirsp-2.0.1/dkist_processing_cryonirsp.egg-info/scm_version.json +0 -8
  28. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/.gitignore +0 -0
  29. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/.pre-commit-config.yaml +0 -0
  30. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/.readthedocs.yml +0 -0
  31. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/.rovodev/.review-agent.md +0 -0
  32. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/.snyk +0 -0
  33. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/README.rst +0 -0
  34. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/SCIENCE_CHANGELOG.rst +0 -0
  35. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/bitbucket-pipelines.yml +0 -0
  36. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/changelog/.gitempty +0 -0
  37. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/__init__.py +0 -0
  38. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/codecs/__init__.py +0 -0
  39. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/codecs/fits.py +0 -0
  40. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/config.py +0 -0
  41. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/models/__init__.py +0 -0
  42. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/models/beam_boundaries.py +0 -0
  43. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/models/dataset_extras.py +0 -0
  44. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/models/fits_access.py +0 -0
  45. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/models/parameters.py +0 -0
  46. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/models/task_name.py +0 -0
  47. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/parsers/__init__.py +0 -0
  48. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/parsers/check_for_gains.py +0 -0
  49. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/parsers/cryonirsp_l1_fits_access.py +0 -0
  50. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/parsers/map_repeats.py +0 -0
  51. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/parsers/measurements.py +0 -0
  52. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/parsers/modstates.py +0 -0
  53. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/parsers/optical_density_filters.py +0 -0
  54. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/parsers/scan_step.py +0 -0
  55. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/parsers/time.py +0 -0
  56. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tasks/__init__.py +0 -0
  57. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tasks/assemble_movie.py +0 -0
  58. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tasks/bad_pixel_map.py +0 -0
  59. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tasks/beam_boundaries_base.py +0 -0
  60. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tasks/ci_beam_boundaries.py +0 -0
  61. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tasks/ci_science.py +0 -0
  62. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tasks/cryonirsp_base.py +0 -0
  63. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tasks/dark.py +0 -0
  64. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tasks/gain.py +0 -0
  65. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tasks/instrument_polarization.py +0 -0
  66. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tasks/l1_output_data.py +0 -0
  67. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tasks/linearity_correction.py +0 -0
  68. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tasks/make_movie_frames.py +0 -0
  69. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tasks/mixin/__init__.py +0 -0
  70. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tasks/mixin/corrections.py +0 -0
  71. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tasks/mixin/shift_measurements.py +0 -0
  72. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tasks/parse.py +0 -0
  73. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tasks/polcal_as_science.py +0 -0
  74. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tasks/quality_metrics.py +0 -0
  75. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tasks/science_base.py +0 -0
  76. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tasks/sp_beam_boundaries.py +0 -0
  77. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tasks/sp_geometric.py +0 -0
  78. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tasks/sp_science.py +0 -0
  79. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tasks/sp_solar_gain.py +0 -0
  80. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tasks/sp_wavelength_calibration.py +0 -0
  81. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tasks/write_dataset_extras.py +0 -0
  82. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tasks/write_l1.py +0 -0
  83. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tests/__init__.py +0 -0
  84. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tests/local_trial_workflows/__init__.py +0 -0
  85. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tests/local_trial_workflows/l0_cals_only.py +0 -0
  86. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tests/local_trial_workflows/l0_to_l1.py +0 -0
  87. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tests/local_trial_workflows/linearize_only.py +0 -0
  88. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tests/local_trial_workflows/local_trial_helpers.py +0 -0
  89. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tests/test_assemble_movie.py +0 -0
  90. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tests/test_assemble_qualilty.py +0 -0
  91. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tests/test_bad_pixel_maps.py +0 -0
  92. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tests/test_ci_beam_boundaries.py +0 -0
  93. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tests/test_corrections.py +0 -0
  94. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tests/test_cryo_base.py +0 -0
  95. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tests/test_fits_access.py +0 -0
  96. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tests/test_make_movie_frames.py +0 -0
  97. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tests/test_parameters.py +0 -0
  98. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tests/test_quality.py +0 -0
  99. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tests/test_sp_beam_boundaries.py +0 -0
  100. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tests/test_sp_make_movie_frames.py +0 -0
  101. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tests/test_sp_wavelength_calibration.py +0 -0
  102. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tests/test_trial_create_quality_report.py +0 -0
  103. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tests/test_workflows.py +0 -0
  104. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/tests/test_write_l1.py +0 -0
  105. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/workflows/__init__.py +0 -0
  106. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/workflows/ci_l0_processing.py +0 -0
  107. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/workflows/sp_l0_processing.py +0 -0
  108. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp/workflows/trial_workflows.py +0 -0
  109. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp.egg-info/SOURCES.txt +0 -0
  110. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp.egg-info/dependency_links.txt +0 -0
  111. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp.egg-info/scm_file_list.json +94 -94
  112. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/dkist_processing_cryonirsp.egg-info/top_level.txt +0 -0
  113. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/docs/Makefile +0 -0
  114. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/docs/bad_pixel_calibration.rst +0 -0
  115. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/docs/beam_angle_calculation.rst +0 -0
  116. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/docs/beam_boundary_computation.rst +0 -0
  117. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/docs/changelog.rst +0 -0
  118. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/docs/ci_science_calibration.rst +0 -0
  119. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/docs/conf.py +0 -0
  120. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/docs/dataset_extras.rst +0 -0
  121. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/docs/index.rst +0 -0
  122. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/docs/l0_to_l1_cryonirsp_ci-full-trial.rst +0 -0
  123. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/docs/l0_to_l1_cryonirsp_ci.rst +0 -0
  124. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/docs/l0_to_l1_cryonirsp_sp-full-trial.rst +0 -0
  125. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/docs/l0_to_l1_cryonirsp_sp.rst +0 -0
  126. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/docs/landing_page.rst +0 -0
  127. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/docs/linearization.rst +0 -0
  128. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/docs/make.bat +0 -0
  129. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/docs/requirements.txt +0 -0
  130. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/docs/requirements_table.rst +0 -0
  131. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/docs/scientific_changelog.rst +0 -0
  132. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/docs/sp_science_calibration.rst +0 -0
  133. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/docs/wavelength_calibration.rst +0 -0
  134. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/licenses/LICENSE.rst +0 -0
  135. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/science_towncrier.sh +0 -0
  136. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/setup.cfg +0 -0
  137. {dkist_processing_cryonirsp-2.0.1 → dkist_processing_cryonirsp-2.0.2}/towncrier_science.toml +0 -0
@@ -1,3 +1,16 @@
1
+ v2.0.2 (2026-07-28)
2
+ ===================
3
+
4
+ Misc
5
+ ----
6
+
7
+ - Replace the named tuple ExposureConditions with a Pydantic BaseModel of the same name.
8
+ To be added to the constants database, ExposureConditions are converted to a simple tuple.
9
+ When retrieved from the constants database, the tuples are converted back to model instances. (`#280 <https://bitbucket.org/dkistdc/dkist-processing-cryonirsp/pull-requests/280>`__)
10
+ - Replace the named tuples PolarimetricValueDataContainer and DarkTaskTestAndExposureConditionsContainer
11
+ with dataclasses PolarimetricValueData and DarkTaskTestAndExposureConditions, respectively. (`#280 <https://bitbucket.org/dkistdc/dkist-processing-cryonirsp/pull-requests/280>`__)
12
+
13
+
1
14
  v2.0.1 (2026-07-22)
2
15
  ===================
3
16
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dkist-processing-cryonirsp
3
- Version: 2.0.1
3
+ Version: 2.0.2
4
4
  Summary: Science processing code for the Cryo-NIRSP instrument on DKIST
5
5
  Author-email: NSO / AURA <dkistdc@nso.edu>
6
6
  License: BSD-3-Clause
@@ -77,22 +77,22 @@ Requires-Dist: Send2Trash==2.1.0; extra == "frozen"
77
77
  Requires-Dist: a2wsgi==1.10.10; extra == "frozen"
78
78
  Requires-Dist: aioftp==0.27.2; extra == "frozen"
79
79
  Requires-Dist: aiohappyeyeballs==2.7.1; extra == "frozen"
80
- Requires-Dist: aiohttp==3.14.2; extra == "frozen"
80
+ Requires-Dist: aiohttp==3.14.3; extra == "frozen"
81
81
  Requires-Dist: aiosignal==1.4.0; extra == "frozen"
82
82
  Requires-Dist: aiosmtplib==5.1.2; extra == "frozen"
83
83
  Requires-Dist: aiosqlite==0.21.0; extra == "frozen"
84
84
  Requires-Dist: alembic==1.18.5; extra == "frozen"
85
85
  Requires-Dist: amqp==5.3.1; extra == "frozen"
86
- Requires-Dist: annotated-doc==0.0.4; extra == "frozen"
87
- Requires-Dist: annotated-types==0.7.0; extra == "frozen"
86
+ Requires-Dist: annotated-doc==0.0.5; extra == "frozen"
87
+ Requires-Dist: annotated-types==0.8.0; extra == "frozen"
88
88
  Requires-Dist: anyio==4.14.2; extra == "frozen"
89
89
  Requires-Dist: apache-airflow==3.2.1; extra == "frozen"
90
90
  Requires-Dist: apache-airflow-core==3.2.1; extra == "frozen"
91
- Requires-Dist: apache-airflow-providers-celery==3.22.0; extra == "frozen"
92
- Requires-Dist: apache-airflow-providers-common-compat==1.16.0; extra == "frozen"
91
+ Requires-Dist: apache-airflow-providers-celery==3.23.0; extra == "frozen"
92
+ Requires-Dist: apache-airflow-providers-common-compat==1.17.0; extra == "frozen"
93
93
  Requires-Dist: apache-airflow-providers-common-io==1.8.0; extra == "frozen"
94
- Requires-Dist: apache-airflow-providers-common-sql==2.0.2; extra == "frozen"
95
- Requires-Dist: apache-airflow-providers-postgres==6.8.0; extra == "frozen"
94
+ Requires-Dist: apache-airflow-providers-common-sql==2.0.3; extra == "frozen"
95
+ Requires-Dist: apache-airflow-providers-postgres==7.0.0; extra == "frozen"
96
96
  Requires-Dist: apache-airflow-providers-smtp==3.0.2; extra == "frozen"
97
97
  Requires-Dist: apache-airflow-providers-standard==1.16.0; extra == "frozen"
98
98
  Requires-Dist: apache-airflow-task-sdk==1.2.1; extra == "frozen"
@@ -105,7 +105,7 @@ Requires-Dist: asdf_standard==1.5.0; extra == "frozen"
105
105
  Requires-Dist: asgiref==3.12.1; extra == "frozen"
106
106
  Requires-Dist: asteval==1.0.9; extra == "frozen"
107
107
  Requires-Dist: astropy==7.0.2; extra == "frozen"
108
- Requires-Dist: astropy-iers-data==0.2026.7.20.15.31.18; extra == "frozen"
108
+ Requires-Dist: astropy-iers-data==0.2026.7.27.0.56.29; extra == "frozen"
109
109
  Requires-Dist: asttokens==3.0.2; extra == "frozen"
110
110
  Requires-Dist: async-lru==2.3.0; extra == "frozen"
111
111
  Requires-Dist: asyncpg==0.31.0; extra == "frozen"
@@ -114,9 +114,9 @@ Requires-Dist: babel==2.18.0; extra == "frozen"
114
114
  Requires-Dist: beautifulsoup4==4.15.0; extra == "frozen"
115
115
  Requires-Dist: billiard==4.2.4; extra == "frozen"
116
116
  Requires-Dist: bleach==6.4.0; extra == "frozen"
117
- Requires-Dist: boto3==1.43.53; extra == "frozen"
118
- Requires-Dist: botocore==1.43.53; extra == "frozen"
119
- Requires-Dist: cadwyn==7.1.1; extra == "frozen"
117
+ Requires-Dist: boto3==1.43.57; extra == "frozen"
118
+ Requires-Dist: botocore==1.43.57; extra == "frozen"
119
+ Requires-Dist: cadwyn==7.1.2; extra == "frozen"
120
120
  Requires-Dist: celery==5.6.3; extra == "frozen"
121
121
  Requires-Dist: certifi==2026.7.22; extra == "frozen"
122
122
  Requires-Dist: cffi==2.1.0; extra == "frozen"
@@ -125,7 +125,7 @@ Requires-Dist: click==8.4.2; extra == "frozen"
125
125
  Requires-Dist: click-didyoumean==0.3.1; extra == "frozen"
126
126
  Requires-Dist: click-plugins==1.1.1.2; extra == "frozen"
127
127
  Requires-Dist: click-repl==0.3.0; extra == "frozen"
128
- Requires-Dist: colorlog==6.11.0; extra == "frozen"
128
+ Requires-Dist: colorlog==6.12.0; extra == "frozen"
129
129
  Requires-Dist: comm==0.2.3; extra == "frozen"
130
130
  Requires-Dist: contourpy==1.3.3; extra == "frozen"
131
131
  Requires-Dist: cron_descriptor==2.1.0; extra == "frozen"
@@ -139,7 +139,7 @@ Requires-Dist: dill==0.4.1; extra == "frozen"
139
139
  Requires-Dist: dkist-header-validator==5.4.0; extra == "frozen"
140
140
  Requires-Dist: dkist-processing-common==14.3.4; extra == "frozen"
141
141
  Requires-Dist: dkist-processing-core==7.3.0; extra == "frozen"
142
- Requires-Dist: dkist-processing-cryonirsp==2.0.1; extra == "frozen"
142
+ Requires-Dist: dkist-processing-cryonirsp==2.0.2; 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
145
  Requires-Dist: dkist-service-configuration==4.3.0; extra == "frozen"
@@ -148,20 +148,20 @@ Requires-Dist: dkist_fits_specifications==4.28.0; extra == "frozen"
148
148
  Requires-Dist: dnspython==2.8.0; extra == "frozen"
149
149
  Requires-Dist: email-validator==2.3.0; extra == "frozen"
150
150
  Requires-Dist: executing==2.2.1; extra == "frozen"
151
- Requires-Dist: fastapi==0.139.2; extra == "frozen"
151
+ Requires-Dist: fastapi==0.140.13; extra == "frozen"
152
152
  Requires-Dist: fastapi-cli==0.0.32; extra == "frozen"
153
- Requires-Dist: fastjsonschema==2.21.2; extra == "frozen"
153
+ Requires-Dist: fastjsonschema==2.22.1; extra == "frozen"
154
154
  Requires-Dist: flower==2.0.1; extra == "frozen"
155
155
  Requires-Dist: fonttools==4.63.0; extra == "frozen"
156
156
  Requires-Dist: fqdn==1.5.1; extra == "frozen"
157
157
  Requires-Dist: frozenlist==1.8.0; extra == "frozen"
158
- Requires-Dist: fsspec==2026.6.0; extra == "frozen"
158
+ Requires-Dist: fsspec==2026.7.0; extra == "frozen"
159
159
  Requires-Dist: globus-sdk==4.8.1; extra == "frozen"
160
160
  Requires-Dist: googleapis-common-protos==1.75.0; extra == "frozen"
161
161
  Requires-Dist: gqlclient==2.0.0; extra == "frozen"
162
162
  Requires-Dist: greenback==1.3.0; extra == "frozen"
163
163
  Requires-Dist: greenlet==3.5.4; extra == "frozen"
164
- Requires-Dist: grpcio==1.82.1; extra == "frozen"
164
+ Requires-Dist: grpcio==1.83.0; extra == "frozen"
165
165
  Requires-Dist: h11==0.16.0; extra == "frozen"
166
166
  Requires-Dist: httpcore==1.0.9; extra == "frozen"
167
167
  Requires-Dist: httptools==0.8.0; extra == "frozen"
@@ -252,7 +252,7 @@ Requires-Dist: opentelemetry-semantic-conventions==0.65b0; extra == "frozen"
252
252
  Requires-Dist: opentelemetry-util-http==0.65b0; extra == "frozen"
253
253
  Requires-Dist: outcome==1.3.0.post0; extra == "frozen"
254
254
  Requires-Dist: packaging==26.2; extra == "frozen"
255
- Requires-Dist: pandas==3.0.3; extra == "frozen"
255
+ Requires-Dist: pandas==3.0.5; extra == "frozen"
256
256
  Requires-Dist: pandocfilters==1.5.1; extra == "frozen"
257
257
  Requires-Dist: parfive==2.3.1; extra == "frozen"
258
258
  Requires-Dist: parso==0.8.7; extra == "frozen"
@@ -260,18 +260,20 @@ Requires-Dist: pathlib_abc==0.5.2; extra == "frozen"
260
260
  Requires-Dist: pathspec==1.1.1; extra == "frozen"
261
261
  Requires-Dist: pendulum==3.2.0; extra == "frozen"
262
262
  Requires-Dist: pexpect==4.9.0; extra == "frozen"
263
- Requires-Dist: pika==1.4.1; extra == "frozen"
263
+ Requires-Dist: pika==1.4.2; extra == "frozen"
264
264
  Requires-Dist: pillow==10.4.0; extra == "frozen"
265
265
  Requires-Dist: pip==26.1.2; extra == "frozen"
266
266
  Requires-Dist: platformdirs==4.11.0; extra == "frozen"
267
267
  Requires-Dist: pluggy==1.6.0; extra == "frozen"
268
268
  Requires-Dist: pooch==1.9.0; extra == "frozen"
269
269
  Requires-Dist: proglog==0.1.12; extra == "frozen"
270
- Requires-Dist: prometheus_client==0.25.0; extra == "frozen"
271
- Requires-Dist: prompt_toolkit==3.0.52; extra == "frozen"
270
+ Requires-Dist: prometheus_client==0.26.0; extra == "frozen"
271
+ Requires-Dist: prompt_toolkit==3.0.53; extra == "frozen"
272
272
  Requires-Dist: propcache==0.5.2; extra == "frozen"
273
273
  Requires-Dist: protobuf==7.35.1; extra == "frozen"
274
274
  Requires-Dist: psutil==7.2.2; extra == "frozen"
275
+ Requires-Dist: psycopg==3.3.4; extra == "frozen"
276
+ Requires-Dist: psycopg-binary==3.3.4; extra == "frozen"
275
277
  Requires-Dist: psycopg2-binary==2.9.12; extra == "frozen"
276
278
  Requires-Dist: ptyprocess==0.7.0; extra == "frozen"
277
279
  Requires-Dist: pure_eval==0.2.3; extra == "frozen"
@@ -289,7 +291,7 @@ Requires-Dist: python-dotenv==1.2.2; extra == "frozen"
289
291
  Requires-Dist: python-json-logger==4.1.0; extra == "frozen"
290
292
  Requires-Dist: python-multipart==0.0.32; extra == "frozen"
291
293
  Requires-Dist: python-slugify==8.0.4; extra == "frozen"
292
- Requires-Dist: pytz==2026.2; extra == "frozen"
294
+ Requires-Dist: pytz==2026.3.post1; extra == "frozen"
293
295
  Requires-Dist: pyzmq==27.1.0; extra == "frozen"
294
296
  Requires-Dist: redis==6.4.0; extra == "frozen"
295
297
  Requires-Dist: referencing==0.37.0; extra == "frozen"
@@ -301,7 +303,7 @@ Requires-Dist: rich==15.0.0; extra == "frozen"
301
303
  Requires-Dist: rich-argparse==1.8.0; extra == "frozen"
302
304
  Requires-Dist: rich-toolkit==0.20.3; extra == "frozen"
303
305
  Requires-Dist: rpds-py==2026.6.3; extra == "frozen"
304
- Requires-Dist: s3transfer==0.19.1; extra == "frozen"
306
+ Requires-Dist: s3transfer==0.19.2; extra == "frozen"
305
307
  Requires-Dist: scikit-image==0.25.2; extra == "frozen"
306
308
  Requires-Dist: scikit-learn==1.9.0; extra == "frozen"
307
309
  Requires-Dist: scipy==1.15.3; extra == "frozen"
@@ -329,7 +331,7 @@ Requires-Dist: threadpoolctl==3.6.0; extra == "frozen"
329
331
  Requires-Dist: tifffile==2026.7.14; extra == "frozen"
330
332
  Requires-Dist: tinycss2==1.5.1; extra == "frozen"
331
333
  Requires-Dist: tornado==6.5.7; extra == "frozen"
332
- Requires-Dist: tqdm==4.69.0; extra == "frozen"
334
+ Requires-Dist: tqdm==4.70.0; extra == "frozen"
333
335
  Requires-Dist: traitlets==5.15.1; extra == "frozen"
334
336
  Requires-Dist: typer==0.27.0; extra == "frozen"
335
337
  Requires-Dist: typing-inspection==0.4.2; extra == "frozen"
@@ -353,7 +355,7 @@ Requires-Dist: webencodings==0.5.1; extra == "frozen"
353
355
  Requires-Dist: websocket-client==1.9.0; extra == "frozen"
354
356
  Requires-Dist: websockets==16.1.1; extra == "frozen"
355
357
  Requires-Dist: wirerope==1.0.0; extra == "frozen"
356
- Requires-Dist: wrapt==2.2.2; extra == "frozen"
358
+ Requires-Dist: wrapt==2.3.0; extra == "frozen"
357
359
  Requires-Dist: yamale==6.1.0; extra == "frozen"
358
360
  Requires-Dist: yarl==1.24.5; extra == "frozen"
359
361
  Requires-Dist: zipp==4.1.0; extra == "frozen"
@@ -63,6 +63,11 @@ class CryonirspBudName(StrEnum):
63
63
  class CryonirspConstants(ConstantsBase):
64
64
  """CryoNIRSP specific constants to add to the common constants."""
65
65
 
66
+ def _build_exposure_conditions_list(self, key: str) -> list[ExposureConditions]:
67
+ """Fetch exposure conditions from database and rebuild as ExposureConditions objects."""
68
+ raw_conditions: list[list[float | str]] = self._db_dict[key]
69
+ return [ExposureConditions.model_validate_json(conditions) for conditions in raw_conditions]
70
+
66
71
  @property
67
72
  def arm_id(self) -> str:
68
73
  """Arm used to record the data, SP or CI."""
@@ -144,48 +149,38 @@ class CryonirspConstants(ConstantsBase):
144
149
  @property
145
150
  def dark_exposure_conditions_list(self) -> list[ExposureConditions]:
146
151
  """Construct a list of dark frame ExposureConditions tuples for the dataset."""
147
- raw_conditions: list[list[float | str]] = self._db_dict[
152
+ return self._build_exposure_conditions_list(
148
153
  CryonirspBudName.dark_exposure_conditions_list.value
149
- ]
150
- conditions = [ExposureConditions(*item) for item in raw_conditions]
151
- return conditions
154
+ )
152
155
 
153
156
  @property
154
157
  def lamp_gain_exposure_conditions_list(self) -> list[ExposureConditions]:
155
158
  """Construct a list of lamp gain ExposureConditions tuples for the dataset."""
156
- raw_conditions: list[list[float | str]] = self._db_dict[
159
+ return self._build_exposure_conditions_list(
157
160
  CryonirspBudName.lamp_gain_exposure_conditions_list.value
158
- ]
159
- conditions = [ExposureConditions(*item) for item in raw_conditions]
160
- return conditions
161
+ )
161
162
 
162
163
  @property
163
164
  def solar_gain_exposure_conditions_list(self) -> list[ExposureConditions]:
164
165
  """Construct a list of solar gain ExposureConditions tuples for the dataset."""
165
- raw_conditions: list[list[float | str]] = self._db_dict[
166
+ return self._build_exposure_conditions_list(
166
167
  CryonirspBudName.solar_gain_exposure_conditions_list.value
167
- ]
168
- conditions = [ExposureConditions(*item) for item in raw_conditions]
169
- return conditions
168
+ )
170
169
 
171
170
  @property
172
171
  def observe_exposure_conditions_list(self) -> list[ExposureConditions]:
173
172
  """Construct a list of observe ExposureConditions tuples for the dataset."""
174
- raw_conditions: list[list[float | str]] = self._db_dict[
173
+ return self._build_exposure_conditions_list(
175
174
  CryonirspBudName.observe_exposure_conditions_list.value
176
- ]
177
- conditions = [ExposureConditions(*item) for item in raw_conditions]
178
- return conditions
175
+ )
179
176
 
180
177
  @property
181
178
  def polcal_exposure_conditions_list(self) -> list[ExposureConditions]:
182
179
  """Construct a list of polcal ExposureConditions tuples for the dataset."""
183
180
  if self.correct_for_polarization:
184
- raw_conditions: list[list[float | str]] = self._db_dict[
181
+ return self._build_exposure_conditions_list(
185
182
  CryonirspBudName.polcal_exposure_conditions_list.value
186
- ]
187
- conditions = [ExposureConditions(*item) for item in raw_conditions]
188
- return conditions
183
+ )
189
184
  else:
190
185
  return []
191
186
 
@@ -194,20 +189,16 @@ class CryonirspConstants(ConstantsBase):
194
189
  self,
195
190
  ) -> list[ExposureConditions]:
196
191
  """Return a list of all exposure times required for all tasks other than dark, polcal, and lamp gain."""
197
- raw_conditions: list[list[float | str]] = self._db_dict[
192
+ return self._build_exposure_conditions_list(
198
193
  CryonirspBudName.ci_non_dark_and_non_polcal_and_non_lamp_gain_task_exposure_conditions_list.value
199
- ]
200
- conditions = [ExposureConditions(*item) for item in raw_conditions]
201
- return conditions
194
+ )
202
195
 
203
196
  @property
204
197
  def sp_non_dark_and_non_polcal_task_exposure_conditions_list(self) -> list[ExposureConditions]:
205
198
  """Return a list of all exposure times required for all tasks other than dark and polcal."""
206
- raw_conditions: list[list[float | str]] = self._db_dict[
199
+ return self._build_exposure_conditions_list(
207
200
  CryonirspBudName.sp_non_dark_and_non_polcal_task_exposure_conditions_list.value
208
- ]
209
- conditions = [ExposureConditions(*item) for item in raw_conditions]
210
- return conditions
201
+ )
211
202
 
212
203
  @property
213
204
  def stokes_I_list(self) -> list[str]:
@@ -1,22 +1,14 @@
1
1
  """Support classes for exposure conditions."""
2
2
 
3
3
  from enum import StrEnum
4
- from typing import NamedTuple
4
+
5
+ from pydantic import BaseModel
6
+ from pydantic import ConfigDict
5
7
 
6
8
  # Number of digits used to round the exposure when creating the ExposureConditions tuple in fits_access
7
9
  CRYO_EXP_TIME_ROUND_DIGITS: int = 3
8
10
 
9
11
 
10
- class ExposureConditions(NamedTuple):
11
- """Named tuple to hold exposure time and filter name."""
12
-
13
- exposure_time: float
14
- filter_name: str
15
-
16
- def __str__(self):
17
- return f"{self.exposure_time}_{self.filter_name}"
18
-
19
-
20
12
  class AllowableOpticalDensityFilterNames(StrEnum):
21
13
  """Enum to implement list of allowable Optical Density Filter names."""
22
14
 
@@ -25,3 +17,19 @@ class AllowableOpticalDensityFilterNames(StrEnum):
25
17
  G408 = "G408"
26
18
  OPEN = "OPEN"
27
19
  NONE = "NONE"
20
+
21
+
22
+ class ExposureConditions(BaseModel):
23
+ """Model to validate and hold exposure time and filter name."""
24
+
25
+ model_config = ConfigDict(frozen=True)
26
+
27
+ exposure_time: float
28
+ filter_name: AllowableOpticalDensityFilterNames
29
+
30
+ def __lt__(self, other):
31
+ # Compare based on exposure time
32
+ return self.exposure_time < other.exposure_time
33
+
34
+ def __str__(self):
35
+ return f"{self.exposure_time}_{self.filter_name}"
@@ -140,7 +140,7 @@ class CryonirspTag(Tag):
140
140
  Parameters
141
141
  ----------
142
142
  exposure_conditions
143
- A tuple of (exposure time, filter name)
143
+ An ExposureConditions object
144
144
 
145
145
  Returns
146
146
  -------
@@ -108,7 +108,8 @@ class CryonirspL0FitsAccess(L0FitsAccess):
108
108
  self.filter_name = self.header[CryonirspMetadataKey.filter_name.value].upper()
109
109
  # The ExposureConditions are a combination of the exposure time and the OD filter name:
110
110
  self.exposure_conditions = ExposureConditions(
111
- round(self.fpa_exposure_time_ms, CRYO_EXP_TIME_ROUND_DIGITS), self.filter_name
111
+ exposure_time=round(self.fpa_exposure_time_ms, CRYO_EXP_TIME_ROUND_DIGITS),
112
+ filter_name=self.filter_name,
112
113
  )
113
114
  self.center_wavelength = self.header[CryonirspMetadataKey.center_wavelength]
114
115
  self.slit_width = self.header[CryonirspMetadataKey.slit_width]
@@ -1,6 +1,6 @@
1
1
  """Buds to parse the combination of exposure time and filter name."""
2
2
 
3
- from typing import NamedTuple
3
+ from dataclasses import dataclass
4
4
  from typing import Type
5
5
 
6
6
  from dkist_processing_common.models.flower_pot import SetStem
@@ -30,28 +30,38 @@ class CryonirspTaskExposureConditionsBud(SetStem):
30
30
  super().__init__(stem_name=stem_name)
31
31
  self.ip_task_type = ip_task_type
32
32
 
33
- def setter(self, fits_obj: CryonirspL0FitsAccess) -> Type[SpilledDirt] | ExposureConditions:
33
+ def setter(self, fits_obj: CryonirspL0FitsAccess) -> ExposureConditions | Type[SpilledDirt]:
34
34
  """
35
- Set the value of the bud.
35
+ Set the task exposure conditions for this fits object.
36
36
 
37
37
  Parameters
38
38
  ----------
39
39
  fits_obj:
40
40
  A single FitsAccess object
41
+
42
+ Returns
43
+ -------
44
+ The exposure conditions associated with this fits object
41
45
  """
42
46
  ip_task_type = parse_header_ip_task_with_gains(fits_obj)
43
47
  if ip_task_type.lower() == self.ip_task_type.lower():
44
48
  return fits_obj.exposure_conditions
45
49
  return SpilledDirt
46
50
 
47
- def getter(self) -> tuple[ExposureConditions, ...]:
48
- """Return a list of the ExposureConditions for this ip task type."""
49
- exposure_conditions_tuple = tuple(sorted(self.value_set))
50
- return exposure_conditions_tuple
51
+ def getter(self) -> tuple[str, ...]:
52
+ """
53
+ Return the set of exposure conditions.
54
+
55
+ Returns
56
+ -------
57
+ A sorted tuple of exposure conditions in JSON form
58
+ """
59
+ exposure_conditions = tuple(v.model_dump_json() for v in sorted(self.value_set))
60
+ return exposure_conditions
51
61
 
52
62
 
53
63
  class CryonirspConditionalTaskExposureConditionsBudBase(SetStem):
54
- """For ip task types that are not in task_types_to_ignore, produce a list of exposure conditions tuples."""
64
+ """For ip task types that are not in task_types_to_ignore, produce a set of exposure conditions."""
55
65
 
56
66
  def __init__(self, stem_name: str, task_types_to_ignore: list[str]):
57
67
  super().__init__(stem_name=stem_name)
@@ -59,7 +69,7 @@ class CryonirspConditionalTaskExposureConditionsBudBase(SetStem):
59
69
 
60
70
  def setter(self, fits_obj: CryonirspL0FitsAccess) -> ExposureConditions | Type[SpilledDirt]:
61
71
  """
62
- Set the task exposure conditions tuple for this fits object.
72
+ Set the task exposure conditions for this fits object.
63
73
 
64
74
  Parameters
65
75
  ----------
@@ -68,23 +78,23 @@ class CryonirspConditionalTaskExposureConditionsBudBase(SetStem):
68
78
 
69
79
  Returns
70
80
  -------
71
- The exposure time associated with this fits object
81
+ The exposure conditions associated with this fits object
72
82
  """
73
83
  task_type = parse_header_ip_task_with_gains(fits_obj=fits_obj)
74
84
  if task_type.upper() not in self.task_types_to_ignore:
75
85
  return fits_obj.exposure_conditions
76
86
  return SpilledDirt
77
87
 
78
- def getter(self) -> tuple[ExposureConditions, ...]:
88
+ def getter(self) -> tuple[str, ...]:
79
89
  """
80
- Get the list of exposure conditions tuples.
90
+ Return the set of exposure conditions.
81
91
 
82
92
  Returns
83
93
  -------
84
- A tuple of (exposure time, filter name) tuples
94
+ A sorted tuple of exposure conditions in JSON form
85
95
  """
86
- exposure_conditions_tuple = tuple(sorted(self.value_set))
87
- return exposure_conditions_tuple
96
+ exposure_conditions = tuple(v.model_dump_json() for v in sorted(self.value_set))
97
+ return exposure_conditions
88
98
 
89
99
 
90
100
  class CryonirspSPConditionalTaskExposureConditionsBud(
@@ -115,8 +125,9 @@ class CryonirspCIConditionalTaskExposureConditionsBud(
115
125
  )
116
126
 
117
127
 
118
- class DarkTaskTestAndExposureConditionsContainer(NamedTuple):
119
- """Named tuple to hold whether the task is dark along with the associated exposure conditions."""
128
+ @dataclass(frozen=True, slots=True)
129
+ class DarkTaskTestAndExposureConditions:
130
+ """Dataclass to hold whether the task is dark along with the associated exposure conditions."""
120
131
 
121
132
  is_dark: bool
122
133
  exposure_conditions: ExposureConditions
@@ -125,15 +136,13 @@ class DarkTaskTestAndExposureConditionsContainer(NamedTuple):
125
136
  class CryonirspPickyDarkExposureConditionsBudBase(SetStem):
126
137
  """Parse exposure conditions tuples to ensure existence of dark frames with the required exposure conditions."""
127
138
 
128
- DarkTaskTestAndExposureConditions = DarkTaskTestAndExposureConditionsContainer
129
-
130
139
  def __init__(self, stem_name: str, task_types_to_ignore: list[str]):
131
140
  super().__init__(stem_name=stem_name)
132
141
  self.task_types_to_ignore = task_types_to_ignore
133
142
 
134
143
  def setter(
135
144
  self, fits_obj: CryonirspL0FitsAccess
136
- ) -> DarkTaskTestAndExposureConditionsContainer | Type[SpilledDirt]:
145
+ ) -> DarkTaskTestAndExposureConditions | Type[SpilledDirt]:
137
146
  """
138
147
  Set the task exposure conditions tuple and whether it is a DARK task for this fits object.
139
148
 
@@ -147,13 +156,15 @@ class CryonirspPickyDarkExposureConditionsBudBase(SetStem):
147
156
  """
148
157
  task_type = parse_header_ip_task_with_gains(fits_obj=fits_obj)
149
158
  if task_type.upper() == TaskName.dark.value:
150
- return self.DarkTaskTestAndExposureConditions(
159
+ dark_true_and_exposure_conditions = DarkTaskTestAndExposureConditions(
151
160
  is_dark=True, exposure_conditions=fits_obj.exposure_conditions
152
161
  )
162
+ return dark_true_and_exposure_conditions
153
163
  if task_type.upper() not in self.task_types_to_ignore:
154
- return self.DarkTaskTestAndExposureConditions(
164
+ dark_false_and_exposure_conditions = DarkTaskTestAndExposureConditions(
155
165
  is_dark=False, exposure_conditions=fits_obj.exposure_conditions
156
166
  )
167
+ return dark_false_and_exposure_conditions
157
168
  # Ignored task types fall through
158
169
  return SpilledDirt
159
170
 
@@ -1,7 +1,8 @@
1
1
  """Copy of UniqueBud from common that only activates if the frames are polarimetric "observe" or "polcal" task, or non-polarimetric "observe" task."""
2
2
 
3
+ from dataclasses import dataclass
3
4
  from enum import StrEnum
4
- from typing import NamedTuple
5
+ from typing import Iterator
5
6
  from typing import Type
6
7
 
7
8
  from dkist_processing_common.models.flower_pot import ListStem
@@ -13,8 +14,9 @@ from dkist_processing_cryonirsp.models.fits_access import CryonirspMetadataKey
13
14
  from dkist_processing_cryonirsp.parsers.cryonirsp_l0_fits_access import CryonirspL0FitsAccess
14
15
 
15
16
 
16
- class PolarimetricValueDataContainer(NamedTuple):
17
- """Named tuple to hold polarimetric metadata about a task."""
17
+ @dataclass(frozen=True, slots=True)
18
+ class PolarimetricValueData:
19
+ """Dataclass to hold polarimetric metadata about a task."""
18
20
 
19
21
  task: str
20
22
  num_modstates: int
@@ -25,7 +27,6 @@ class PolarimetricValueDataContainer(NamedTuple):
25
27
  class PolarimetricCheckingUniqueBud(ListStem):
26
28
  """Bud for checking if frames are polarimetric."""
27
29
 
28
- PolarimetricValueData = PolarimetricValueDataContainer
29
30
  observe_task_name = TaskName.observe.value.casefold()
30
31
  polcal_task_name = TaskName.polcal.value.casefold()
31
32
 
@@ -36,19 +37,19 @@ class PolarimetricCheckingUniqueBud(ListStem):
36
37
  self.metadata_key = metadata_key
37
38
 
38
39
  @property
39
- def observe_tuple_values(self) -> tuple:
40
- """Return all ingested namedtuples from observe frames."""
40
+ def observe_values(self) -> Iterator[PolarimetricValueData]:
41
+ """Return ingested values from observe frames."""
41
42
  return filter(lambda x: x.task == self.observe_task_name, self.value_list)
42
43
 
43
44
  @property
44
- def polcal_tuple_values(self) -> tuple:
45
- """Return all ingested namedtuples from polcal frames."""
45
+ def polcal_values(self) -> Iterator[PolarimetricValueData]:
46
+ """Return ingested values from polcal frames."""
46
47
  return filter(lambda x: x.task == self.polcal_task_name, self.value_list)
47
48
 
48
49
  def is_polarimetric(self) -> bool:
49
50
  """Check if data is polarimetric."""
50
- obs_num_mod_set = set((o.num_modstates for o in self.observe_tuple_values))
51
- obs_spin_mode_set = set((o.spin_mode for o in self.observe_tuple_values))
51
+ obs_num_mod_set = set((o.num_modstates for o in self.observe_values))
52
+ obs_spin_mode_set = set((o.spin_mode for o in self.observe_values))
52
53
 
53
54
  if len(obs_num_mod_set) > 1:
54
55
  raise ValueError(
@@ -68,9 +69,9 @@ class PolarimetricCheckingUniqueBud(ListStem):
68
69
  return True
69
70
  return False
70
71
 
71
- def setter(self, fits_obj: CryonirspL0FitsAccess) -> Type[SpilledDirt] | tuple:
72
+ def setter(self, fits_obj: CryonirspL0FitsAccess) -> Type[SpilledDirt] | PolarimetricValueData:
72
73
  """
73
- Return a `PolarimetricValueData` namedtuple only for OBSERVE and POLCAL frames.
74
+ Return a `PolarimetricValueData` dataclass object only for OBSERVE and POLCAL frames.
74
75
 
75
76
  Parameters
76
77
  ----------
@@ -88,7 +89,7 @@ class PolarimetricCheckingUniqueBud(ListStem):
88
89
  bud_value = getattr(fits_obj, self.metadata_key)
89
90
 
90
91
  if task in [self.observe_task_name, self.polcal_task_name]:
91
- return self.PolarimetricValueData(
92
+ return PolarimetricValueData(
92
93
  task=task,
93
94
  num_modstates=num_modstates,
94
95
  spin_mode=fits_obj.modulator_spin_mode,
@@ -103,7 +104,7 @@ class PolarimetricCheckingUniqueBud(ListStem):
103
104
  If data are from a polarimetric dataset then the values must match between observe and polcal frames.
104
105
  In all cases the value returned must be the same across all observe (and potentially polcal) frames.
105
106
  """
106
- obs_value_set = set((o.bud_value for o in self.observe_tuple_values))
107
+ obs_value_set = set((o.bud_value for o in self.observe_values))
107
108
  if len(obs_value_set) == 0:
108
109
  # For the rare case where we have polcal frames but not observe frames that are being parsed. This only
109
110
  # comes up in unit tests.
@@ -112,7 +113,7 @@ class PolarimetricCheckingUniqueBud(ListStem):
112
113
  obs_value = obs_value_set.pop()
113
114
 
114
115
  if self.is_polarimetric():
115
- pol_value_set = set((o.bud_value for o in self.polcal_tuple_values))
116
+ pol_value_set = set((o.bud_value for o in self.polcal_values))
116
117
 
117
118
  if len(pol_value_set) > 1:
118
119
  raise ValueError(
@@ -138,27 +138,45 @@ class CryonirspConstantsDb:
138
138
  SOFTWARE_BINNING_Y: int = 1
139
139
  HLS_VERSION: str = "1.8"
140
140
  LAMP_GAIN_EXPOSURE_CONDITIONS_LIST: tuple[ExposureConditions, ...] = (
141
- ExposureConditions(100.0, AllowableOpticalDensityFilterNames.OPEN.value),
141
+ ExposureConditions(
142
+ exposure_time=100.0, filter_name=AllowableOpticalDensityFilterNames.OPEN
143
+ ).model_dump_json(),
142
144
  )
143
145
  SOLAR_GAIN_EXPOSURE_CONDITIONS_LIST: tuple[ExposureConditions, ...] = (
144
- ExposureConditions(1.0, AllowableOpticalDensityFilterNames.OPEN.value),
146
+ ExposureConditions(
147
+ exposure_time=1.0, filter_name=AllowableOpticalDensityFilterNames.OPEN
148
+ ).model_dump_json(),
145
149
  )
146
150
  OBSERVE_EXPOSURE_CONDITIONS_LIST: tuple[ExposureConditions, ...] = (
147
- ExposureConditions(0.01, AllowableOpticalDensityFilterNames.OPEN.value),
151
+ ExposureConditions(
152
+ exposure_time=0.01, filter_name=AllowableOpticalDensityFilterNames.OPEN
153
+ ).model_dump_json(),
148
154
  )
149
155
  POLCAL_EXPOSURE_CONDITIONS_LIST: tuple[ExposureConditions] | tuple = ()
150
156
  DARK_FRAME_EXPOSURE_CONDITIONS_LIST: tuple[ExposureConditions] | tuple = ()
151
157
  SP_NON_DARK_AND_NON_POLCAL_TASK_EXPOSURE_CONDITIONS_LIST: tuple[ExposureConditions, ...] = (
152
- ExposureConditions(100.0, AllowableOpticalDensityFilterNames.OPEN.value),
153
- ExposureConditions(1.0, AllowableOpticalDensityFilterNames.OPEN.value),
154
- ExposureConditions(0.01, AllowableOpticalDensityFilterNames.OPEN.value),
158
+ ExposureConditions(
159
+ exposure_time=100.0, filter_name=AllowableOpticalDensityFilterNames.OPEN
160
+ ).model_dump_json(),
161
+ ExposureConditions(
162
+ exposure_time=1.0, filter_name=AllowableOpticalDensityFilterNames.OPEN
163
+ ).model_dump_json(),
164
+ ExposureConditions(
165
+ exposure_time=0.01, filter_name=AllowableOpticalDensityFilterNames.OPEN
166
+ ).model_dump_json(),
155
167
  )
156
168
  CI_NON_DARK_AND_NON_POLCAL_AND_NON_LAMP_GAIN_TASK_EXPOSURE_CONDITIONS_LIST: tuple[
157
169
  ExposureConditions, ...
158
170
  ] = (
159
- ExposureConditions(100.0, AllowableOpticalDensityFilterNames.OPEN.value),
160
- ExposureConditions(1.0, AllowableOpticalDensityFilterNames.OPEN.value),
161
- ExposureConditions(0.01, AllowableOpticalDensityFilterNames.OPEN.value),
171
+ ExposureConditions(
172
+ exposure_time=100.0, filter_name=AllowableOpticalDensityFilterNames.OPEN
173
+ ).model_dump_json(),
174
+ ExposureConditions(
175
+ exposure_time=1.0, filter_name=AllowableOpticalDensityFilterNames.OPEN
176
+ ).model_dump_json(),
177
+ ExposureConditions(
178
+ exposure_time=0.01, filter_name=AllowableOpticalDensityFilterNames.OPEN
179
+ ).model_dump_json(),
162
180
  )
163
181
  SPECTRAL_LINE: str = "CRSP Ca II H"
164
182
  MODULATOR_SPIN_MODE: str = "Continuous"