dkist-processing-common 14.1.1__tar.gz → 14.2.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 (141) hide show
  1. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/CHANGELOG.rst +21 -0
  2. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/PKG-INFO +1 -1
  3. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/parsers/unique_bud.py +78 -0
  4. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tasks/parse_l0_input_data.py +7 -4
  5. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tests/test_stems.py +80 -0
  6. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common.egg-info/PKG-INFO +1 -1
  7. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/.gitignore +0 -0
  8. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/.pre-commit-config.yaml +0 -0
  9. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/.readthedocs.yml +0 -0
  10. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/.snyk +0 -0
  11. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/README.rst +0 -0
  12. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/bitbucket-pipelines.yml +0 -0
  13. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/changelog/.gitempty +0 -0
  14. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/__init__.py +0 -0
  15. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/_util/__init__.py +0 -0
  16. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/_util/constants.py +0 -0
  17. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/_util/graphql.py +0 -0
  18. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/_util/scratch.py +0 -0
  19. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/_util/tags.py +0 -0
  20. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/codecs/__init__.py +0 -0
  21. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/codecs/array.py +0 -0
  22. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/codecs/asdf.py +0 -0
  23. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/codecs/basemodel.py +0 -0
  24. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/codecs/bytes.py +0 -0
  25. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/codecs/fits.py +0 -0
  26. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/codecs/iobase.py +0 -0
  27. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/codecs/json.py +0 -0
  28. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/codecs/path.py +0 -0
  29. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/codecs/quality.py +0 -0
  30. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/codecs/str.py +0 -0
  31. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/config.py +0 -0
  32. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/fonts/Lato-Regular.ttf +0 -0
  33. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/fonts/__init__.py +0 -0
  34. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/manual.py +0 -0
  35. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/models/__init__.py +0 -0
  36. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/models/constants.py +0 -0
  37. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/models/dkist_location.py +0 -0
  38. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/models/extras.py +0 -0
  39. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/models/fits_access.py +0 -0
  40. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/models/flower_pot.py +0 -0
  41. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/models/fried_parameter.py +0 -0
  42. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/models/graphql.py +0 -0
  43. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/models/input_dataset.py +0 -0
  44. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/models/message.py +0 -0
  45. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/models/message_queue_binding.py +0 -0
  46. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/models/metric_code.py +0 -0
  47. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/models/parameters.py +0 -0
  48. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/models/quality.py +0 -0
  49. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/models/tags.py +0 -0
  50. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/models/task_name.py +0 -0
  51. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/models/telemetry.py +0 -0
  52. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/models/wavelength.py +0 -0
  53. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/parsers/__init__.py +0 -0
  54. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/parsers/average_bud.py +0 -0
  55. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/parsers/cs_step.py +0 -0
  56. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/parsers/dsps_repeat.py +0 -0
  57. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/parsers/experiment_id_bud.py +0 -0
  58. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/parsers/id_bud.py +0 -0
  59. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/parsers/l0_fits_access.py +0 -0
  60. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/parsers/l1_fits_access.py +0 -0
  61. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/parsers/lookup_bud.py +0 -0
  62. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/parsers/near_bud.py +0 -0
  63. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/parsers/observing_program_id_bud.py +0 -0
  64. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/parsers/proposal_id_bud.py +0 -0
  65. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/parsers/quality.py +0 -0
  66. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/parsers/retarder.py +0 -0
  67. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/parsers/single_value_single_key_flower.py +0 -0
  68. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/parsers/task.py +0 -0
  69. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/parsers/time.py +0 -0
  70. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/parsers/wavelength.py +0 -0
  71. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tasks/__init__.py +0 -0
  72. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tasks/assemble_movie.py +0 -0
  73. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tasks/base.py +0 -0
  74. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tasks/l1_output_data.py +0 -0
  75. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tasks/mixin/__init__.py +0 -0
  76. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tasks/mixin/globus.py +0 -0
  77. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tasks/mixin/interservice_bus.py +0 -0
  78. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tasks/mixin/metadata_store.py +0 -0
  79. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tasks/mixin/object_store.py +0 -0
  80. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tasks/mixin/quality/__init__.py +0 -0
  81. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tasks/mixin/quality/_base.py +0 -0
  82. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tasks/mixin/quality/_metrics.py +0 -0
  83. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tasks/output_data_base.py +0 -0
  84. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tasks/quality_metrics.py +0 -0
  85. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tasks/teardown.py +0 -0
  86. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tasks/transfer_input_data.py +0 -0
  87. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tasks/trial_catalog.py +0 -0
  88. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tasks/trial_output_data.py +0 -0
  89. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tasks/write_extra.py +0 -0
  90. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tasks/write_l1.py +0 -0
  91. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tasks/write_l1_base.py +0 -0
  92. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tests/__init__.py +0 -0
  93. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tests/conftest.py +0 -0
  94. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tests/mock_metadata_store.py +0 -0
  95. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tests/test_assemble_movie.py +0 -0
  96. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tests/test_assemble_quality.py +0 -0
  97. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tests/test_base.py +0 -0
  98. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tests/test_codecs.py +0 -0
  99. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tests/test_constants.py +0 -0
  100. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tests/test_construct_dataset_extras.py +0 -0
  101. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tests/test_cs_step.py +0 -0
  102. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tests/test_dkist_location.py +0 -0
  103. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tests/test_fits_access.py +0 -0
  104. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tests/test_flower_pot.py +0 -0
  105. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tests/test_fried_parameter.py +0 -0
  106. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tests/test_input_dataset.py +0 -0
  107. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tests/test_interservice_bus.py +0 -0
  108. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tests/test_interservice_bus_mixin.py +0 -0
  109. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tests/test_manual_processing.py +0 -0
  110. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tests/test_output_data_base.py +0 -0
  111. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tests/test_parameters.py +0 -0
  112. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tests/test_parse_l0_input_data.py +0 -0
  113. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tests/test_publish_catalog_messages.py +0 -0
  114. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tests/test_quality.py +0 -0
  115. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tests/test_quality_mixin.py +0 -0
  116. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tests/test_scratch.py +0 -0
  117. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tests/test_submit_dataset_metadata.py +0 -0
  118. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tests/test_tags.py +0 -0
  119. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tests/test_task_name.py +0 -0
  120. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tests/test_task_parsing.py +0 -0
  121. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tests/test_teardown.py +0 -0
  122. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tests/test_transfer_input_data.py +0 -0
  123. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tests/test_transfer_l1_output_data.py +0 -0
  124. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tests/test_trial_catalog.py +0 -0
  125. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tests/test_trial_output_data.py +0 -0
  126. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tests/test_workflow_task_base.py +0 -0
  127. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common/tests/test_write_l1.py +0 -0
  128. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common.egg-info/SOURCES.txt +0 -0
  129. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common.egg-info/dependency_links.txt +0 -0
  130. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common.egg-info/requires.txt +0 -0
  131. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/dkist_processing_common.egg-info/top_level.txt +0 -0
  132. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/docs/Makefile +0 -0
  133. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/docs/changelog.rst +0 -0
  134. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/docs/conf.py +0 -0
  135. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/docs/index.rst +0 -0
  136. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/docs/landing_page.rst +0 -0
  137. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/docs/make.bat +0 -0
  138. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/docs/requirements.txt +0 -0
  139. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/licenses/LICENSE.rst +0 -0
  140. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/pyproject.toml +0 -0
  141. {dkist_processing_common-14.1.1 → dkist_processing_common-14.2.0}/setup.cfg +0 -0
@@ -1,3 +1,24 @@
1
+ v14.2.0 (2026-05-12)
2
+ ====================
3
+
4
+ Features
5
+ --------
6
+
7
+ - Add the `TaskMostFrequentBud`. This parser is like the `TaskUniqueBud` except that when there is more than one unique
8
+ value the most frequent value is returned. (`#333 <https://bitbucket.org/dkistdc/dkist-processing-common/pull-requests/333>`__)
9
+ - Parse the TELTRACK, TTBLTRCK, and TELSCAN header keys for POLCAL data with the new `TaskMostFrequentBud`. These keys are
10
+ only used to populate headers in dataset extras and there are some cases where the input data have multiple values in these
11
+ keys. While technically "incorrect", this doesn't affect any aspect of the pipeline or L1 data. In this case we log the
12
+ situation and move on. Parse HLS_VERS the same way for all dataset extra input data. (`#333 <https://bitbucket.org/dkistdc/dkist-processing-common/pull-requests/333>`__)
13
+
14
+
15
+ Misc
16
+ ----
17
+
18
+ - Only parse HLS_VERS header information for DARK, SOLAR_GAIN, and POLCAL task types. This key is only used for dataset
19
+ extra headers and these are the task types associated with dataset extras. (`#333 <https://bitbucket.org/dkistdc/dkist-processing-common/pull-requests/333>`__)
20
+
21
+
1
22
  v14.1.1 (2026-05-08)
2
23
  ====================
3
24
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dkist-processing-common
3
- Version: 14.1.1
3
+ Version: 14.2.0
4
4
  Summary: Common task classes used by the DKIST science data processing pipelines
5
5
  Author-email: NSO / AURA <dkistdc@nso.edu>
6
6
  License: BSD-3-Clause
@@ -1,13 +1,18 @@
1
1
  """Pre-made flower that reads a single header key from all files and raises a ValueError if it is not unique."""
2
2
 
3
+ import logging
4
+ from collections import Counter
3
5
  from enum import StrEnum
4
6
  from typing import Callable
5
7
 
8
+ from dkist_processing_common.models.flower_pot import ListStem
6
9
  from dkist_processing_common.models.flower_pot import SetStem
7
10
  from dkist_processing_common.models.flower_pot import SpilledDirt
8
11
  from dkist_processing_common.parsers.l0_fits_access import L0FitsAccess
9
12
  from dkist_processing_common.parsers.task import passthrough_header_ip_task
10
13
 
14
+ logger = logging.getLogger(__name__)
15
+
11
16
 
12
17
  class UniqueBud(SetStem):
13
18
  """
@@ -100,3 +105,76 @@ class TaskUniqueBud(UniqueBud):
100
105
  return super().setter(fits_obj)
101
106
 
102
107
  return SpilledDirt
108
+
109
+
110
+ class TaskMostFrequentBud(ListStem):
111
+ """
112
+ Bud that ingests values in a task-aware way and logs a warning if the set of values is not singular.
113
+
114
+ Unlike `TaskUniqueBud` this Bud will not raise an Error if there are more than one value; instead it will
115
+ return the most-common value.
116
+
117
+ This Bud is useful for cases where we expect the set of input values to contain a single value, but don't want to
118
+ stop processing if it isn't.
119
+
120
+ Parameters
121
+ ----------
122
+ constant_name
123
+ The name for the constant to be defined
124
+
125
+ metadata_key
126
+ The metadata key associated with the constant
127
+
128
+ ip_task_types
129
+ Only consider objects whose parsed header IP task type matches a string in this list
130
+
131
+ task_type_parsing_function
132
+ The function used to convert a header into an IP task type
133
+ """
134
+
135
+ def __init__(
136
+ self,
137
+ constant_name: str,
138
+ metadata_key: str | StrEnum,
139
+ ip_task_types: str | list[str],
140
+ task_type_parsing_function: Callable = passthrough_header_ip_task,
141
+ ):
142
+ super().__init__(stem_name=constant_name)
143
+
144
+ if isinstance(metadata_key, StrEnum):
145
+ metadata_key = metadata_key.name
146
+ self.metadata_key = metadata_key
147
+
148
+ if isinstance(ip_task_types, str):
149
+ ip_task_types = [ip_task_types]
150
+ self.ip_task_types = [task.casefold() for task in ip_task_types]
151
+
152
+ self.parsing_function = task_type_parsing_function
153
+
154
+ def setter(self, fits_obj: L0FitsAccess):
155
+ """Ingest an object only if its parsed IP task type matches what's desired."""
156
+ task = self.parsing_function(fits_obj)
157
+
158
+ if task.casefold() in self.ip_task_types:
159
+ return getattr(fits_obj, self.metadata_key)
160
+
161
+ return SpilledDirt
162
+
163
+ def getter(self):
164
+ """
165
+ Check the list of values, warn if the set of values is non-singular, and return the most-common value.
166
+
167
+ Returns
168
+ -------
169
+ Either the single or most-common value in `self.value_list`.
170
+ """
171
+ if (num_values := len(set(self.value_list))) > 1:
172
+ counts = Counter(self.value_list)
173
+ most_common_value = counts.most_common(1)[0][0]
174
+ logger.info(
175
+ f"Found {num_values} unique values for {self.stem_name}. "
176
+ f"Distribution is {counts}"
177
+ )
178
+ return most_common_value
179
+
180
+ return self.value_list[0]
@@ -51,6 +51,7 @@ from dkist_processing_common.parsers.time import TaskDateBeginBud
51
51
  from dkist_processing_common.parsers.time import TaskExposureTimesBud
52
52
  from dkist_processing_common.parsers.time import TaskReadoutExpTimesBud
53
53
  from dkist_processing_common.parsers.time import VarianceCadenceBud
54
+ from dkist_processing_common.parsers.unique_bud import TaskMostFrequentBud
54
55
  from dkist_processing_common.parsers.unique_bud import TaskUniqueBud
55
56
  from dkist_processing_common.parsers.unique_bud import UniqueBud
56
57
  from dkist_processing_common.tasks.base import WorkflowTaskBase
@@ -87,9 +88,11 @@ def dataset_extra_bud_factory() -> list[S]:
87
88
  UniqueBud(
88
89
  constant_name=BudName.software_binning_y, metadata_key=MetadataKey.software_binning_y
89
90
  ),
90
- UniqueBud(
91
+ TaskMostFrequentBud(
91
92
  constant_name=BudName.hls_version,
92
93
  metadata_key=MetadataKey.hls_version,
94
+ ip_task_types=[TaskName.dark, TaskName.solar_gain, TaskName.polcal],
95
+ task_type_parsing_function=parse_header_ip_task_with_gains,
93
96
  ),
94
97
  TaskContributingObservingProgramExecutionIdsBud(
95
98
  constant_name=BudName.dark_observing_program_execution_ids,
@@ -127,7 +130,7 @@ def dataset_extra_bud_factory() -> list[S]:
127
130
  ip_task_types=TaskName.solar_gain,
128
131
  task_type_parsing_function=parse_header_ip_task_with_gains,
129
132
  ),
130
- TaskUniqueBud(
133
+ TaskMostFrequentBud(
131
134
  constant_name=BudName.polcal_telescope_tracking_mode,
132
135
  metadata_key=MetadataKey.telescope_tracking_mode,
133
136
  ip_task_types=TaskName.polcal,
@@ -138,7 +141,7 @@ def dataset_extra_bud_factory() -> list[S]:
138
141
  ip_task_types=TaskName.solar_gain,
139
142
  task_type_parsing_function=parse_header_ip_task_with_gains,
140
143
  ),
141
- TaskUniqueBud(
144
+ TaskMostFrequentBud(
142
145
  constant_name=BudName.polcal_coude_table_tracking_mode,
143
146
  metadata_key=MetadataKey.coude_table_tracking_mode,
144
147
  ip_task_types=TaskName.polcal,
@@ -149,7 +152,7 @@ def dataset_extra_bud_factory() -> list[S]:
149
152
  ip_task_types=TaskName.solar_gain,
150
153
  task_type_parsing_function=parse_header_ip_task_with_gains,
151
154
  ),
152
- TaskUniqueBud(
155
+ TaskMostFrequentBud(
153
156
  constant_name=BudName.polcal_telescope_scanning_mode,
154
157
  metadata_key=MetadataKey.telescope_scanning_mode,
155
158
  ip_task_types=TaskName.polcal,
@@ -1,4 +1,5 @@
1
1
  import collections
2
+ import logging
2
3
  from enum import StrEnum
3
4
  from itertools import chain
4
5
  from typing import Generator
@@ -50,6 +51,7 @@ from dkist_processing_common.parsers.time import TaskExposureTimesBud
50
51
  from dkist_processing_common.parsers.time import TaskReadoutExpTimesBud
51
52
  from dkist_processing_common.parsers.time import TaskRoundTimeBudBase
52
53
  from dkist_processing_common.parsers.time import VarianceCadenceBud
54
+ from dkist_processing_common.parsers.unique_bud import TaskMostFrequentBud
53
55
  from dkist_processing_common.parsers.unique_bud import TaskUniqueBud
54
56
  from dkist_processing_common.parsers.unique_bud import UniqueBud
55
57
  from dkist_processing_common.parsers.wavelength import ObserveWavelengthBud
@@ -321,6 +323,30 @@ def bad_header_objs() -> Generator[FitsReader, None, None]:
321
323
  "LINEWAV": 1.0,
322
324
  }
323
325
  ),
326
+ "thing5": fits.header.Header(
327
+ {
328
+ "id_key": 1,
329
+ "constant": 6.28,
330
+ "near": 1.76,
331
+ "DKIST004": "observe",
332
+ "DSPSREPS": 2,
333
+ "DSPSNUM": 2,
334
+ "DATE-OBS": "2022-06-17T22:00:03.000",
335
+ "LINEWAV": 1.0,
336
+ }
337
+ ),
338
+ "thing6": fits.header.Header(
339
+ {
340
+ "id_key": 1,
341
+ "constant": 6.66,
342
+ "near": 1.76,
343
+ "DKIST004": "dark",
344
+ "DSPSREPS": 2,
345
+ "DSPSNUM": 2,
346
+ "DATE-OBS": "2022-06-17T22:00:03.000",
347
+ "LINEWAV": 1.0,
348
+ }
349
+ ),
324
350
  }
325
351
  return (
326
352
  FitsReader(header=fits.Header(header), name=path) for path, header in bad_headers.items()
@@ -476,6 +502,60 @@ def test_task_unique_bud_non_unique_inputs(bad_header_objs, ip_task_type):
476
502
  _ = bud.bud
477
503
 
478
504
 
505
+ @pytest.mark.parametrize(
506
+ "ip_task_type",
507
+ [
508
+ pytest.param("observe", id="single_task_type"),
509
+ pytest.param(["observe", "gain"], id="task_type_list"),
510
+ ],
511
+ )
512
+ def test_task_most_frequent_bud(basic_header_objs, ip_task_type, caplog):
513
+ """
514
+ Given: A set of headers with a constant value header key
515
+ When: Ingesting headers with a TaskMostFrequentBud and asking for the value
516
+ Then: The bud's value is the header constant value
517
+ """
518
+ bud_obj = TaskMostFrequentBud(
519
+ constant_name="proposal", metadata_key="proposal_id", ip_task_types=ip_task_type
520
+ )
521
+ assert bud_obj.stem_name == "proposal"
522
+ for fo in basic_header_objs:
523
+ key = fo.name
524
+ bud_obj.update(key, fo)
525
+
526
+ with caplog.at_level(logging.INFO):
527
+ assert bud_obj.bud.value == "proposal_id_1"
528
+ assert caplog.text == ""
529
+
530
+
531
+ @pytest.mark.parametrize(
532
+ "ip_task_type, expected_value",
533
+ [
534
+ pytest.param("observe", 6.28, id="single_task_type"),
535
+ pytest.param(["dark", "gain"], 6.66, id="task_type_list"),
536
+ ],
537
+ )
538
+ def test_task_most_frequent_bud_non_unique_inputs(
539
+ bad_header_objs, ip_task_type, expected_value, caplog
540
+ ):
541
+ """
542
+ Given: A set of headers with a non-constant header key that is expected to be constant
543
+ When: Ingesting headers with a TaskMostFrequentBud and asking for the value
544
+ Then: The most-frequent value is returned and the correct warning is logged
545
+ """
546
+ bud_obj = TaskMostFrequentBud(
547
+ constant_name="constant", metadata_key="constant_thing", ip_task_types=ip_task_type
548
+ )
549
+ assert bud_obj.stem_name == "constant"
550
+ for fo in bad_header_objs:
551
+ key = fo.name
552
+ bud_obj.update(key, fo)
553
+
554
+ with caplog.at_level(logging.INFO):
555
+ assert bud_obj.bud.value == expected_value
556
+ assert "Found 2 unique values for constant" in caplog.text
557
+
558
+
479
559
  def test_single_value_single_key_flower(basic_header_objs):
480
560
  """
481
561
  Given: A set of filepaths and associated headers with a single key that has a limited set of values
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dkist-processing-common
3
- Version: 14.1.1
3
+ Version: 14.2.0
4
4
  Summary: Common task classes used by the DKIST science data processing pipelines
5
5
  Author-email: NSO / AURA <dkistdc@nso.edu>
6
6
  License: BSD-3-Clause