dkist-processing-common 11.9.2__tar.gz → 11.9.3rc1__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 (139) hide show
  1. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/PKG-INFO +1 -1
  2. dkist_processing_common-11.9.3rc1/changelog/281.feature.1.rst +3 -0
  3. dkist_processing_common-11.9.3rc1/changelog/281.feature.rst +2 -0
  4. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/models/constants.py +8 -0
  5. dkist_processing_common-11.9.3rc1/dkist_processing_common/parsers/lookup_bud.py +129 -0
  6. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tasks/parse_l0_input_data.py +7 -0
  7. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tests/test_parse_l0_input_data.py +36 -16
  8. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tests/test_stems.py +49 -1
  9. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tests/test_workflow_task_base.py +11 -0
  10. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common.egg-info/PKG-INFO +1 -1
  11. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common.egg-info/SOURCES.txt +3 -0
  12. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/.gitignore +0 -0
  13. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/.pre-commit-config.yaml +0 -0
  14. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/.readthedocs.yml +0 -0
  15. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/.snyk +0 -0
  16. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/CHANGELOG.rst +0 -0
  17. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/README.rst +0 -0
  18. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/bitbucket-pipelines.yml +0 -0
  19. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/changelog/.gitempty +0 -0
  20. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/__init__.py +0 -0
  21. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/_util/__init__.py +0 -0
  22. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/_util/constants.py +0 -0
  23. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/_util/graphql.py +0 -0
  24. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/_util/scratch.py +0 -0
  25. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/_util/tags.py +0 -0
  26. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/codecs/__init__.py +0 -0
  27. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/codecs/array.py +0 -0
  28. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/codecs/asdf.py +0 -0
  29. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/codecs/basemodel.py +0 -0
  30. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/codecs/bytes.py +0 -0
  31. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/codecs/fits.py +0 -0
  32. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/codecs/iobase.py +0 -0
  33. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/codecs/json.py +0 -0
  34. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/codecs/path.py +0 -0
  35. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/codecs/quality.py +0 -0
  36. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/codecs/str.py +0 -0
  37. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/config.py +0 -0
  38. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/fonts/Lato-Regular.ttf +0 -0
  39. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/fonts/__init__.py +0 -0
  40. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/manual.py +0 -0
  41. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/models/__init__.py +0 -0
  42. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/models/dkist_location.py +0 -0
  43. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/models/fits_access.py +0 -0
  44. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/models/flower_pot.py +0 -0
  45. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/models/fried_parameter.py +0 -0
  46. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/models/graphql.py +0 -0
  47. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/models/input_dataset.py +0 -0
  48. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/models/message.py +0 -0
  49. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/models/message_queue_binding.py +0 -0
  50. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/models/metric_code.py +0 -0
  51. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/models/parameters.py +0 -0
  52. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/models/quality.py +0 -0
  53. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/models/tags.py +0 -0
  54. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/models/task_name.py +0 -0
  55. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/models/telemetry.py +0 -0
  56. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/models/wavelength.py +0 -0
  57. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/parsers/__init__.py +0 -0
  58. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/parsers/average_bud.py +0 -0
  59. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/parsers/cs_step.py +0 -0
  60. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/parsers/dsps_repeat.py +0 -0
  61. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/parsers/experiment_id_bud.py +0 -0
  62. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/parsers/id_bud.py +0 -0
  63. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/parsers/l0_fits_access.py +0 -0
  64. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/parsers/l1_fits_access.py +0 -0
  65. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/parsers/near_bud.py +0 -0
  66. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/parsers/observing_program_id_bud.py +0 -0
  67. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/parsers/proposal_id_bud.py +0 -0
  68. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/parsers/quality.py +0 -0
  69. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/parsers/retarder.py +0 -0
  70. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/parsers/single_value_single_key_flower.py +0 -0
  71. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/parsers/task.py +0 -0
  72. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/parsers/time.py +0 -0
  73. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/parsers/unique_bud.py +0 -0
  74. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/parsers/wavelength.py +0 -0
  75. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tasks/__init__.py +0 -0
  76. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tasks/assemble_movie.py +0 -0
  77. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tasks/base.py +0 -0
  78. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tasks/l1_output_data.py +0 -0
  79. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tasks/mixin/__init__.py +0 -0
  80. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tasks/mixin/globus.py +0 -0
  81. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tasks/mixin/interservice_bus.py +0 -0
  82. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tasks/mixin/metadata_store.py +0 -0
  83. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tasks/mixin/object_store.py +0 -0
  84. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tasks/mixin/quality/__init__.py +0 -0
  85. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tasks/mixin/quality/_base.py +0 -0
  86. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tasks/mixin/quality/_metrics.py +0 -0
  87. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tasks/output_data_base.py +0 -0
  88. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tasks/quality_metrics.py +0 -0
  89. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tasks/teardown.py +0 -0
  90. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tasks/transfer_input_data.py +0 -0
  91. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tasks/trial_catalog.py +0 -0
  92. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tasks/trial_output_data.py +0 -0
  93. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tasks/write_l1.py +0 -0
  94. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tests/__init__.py +0 -0
  95. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tests/conftest.py +0 -0
  96. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tests/mock_metadata_store.py +0 -0
  97. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tests/test_assemble_movie.py +0 -0
  98. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tests/test_assemble_quality.py +0 -0
  99. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tests/test_base.py +0 -0
  100. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tests/test_codecs.py +0 -0
  101. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tests/test_constants.py +0 -0
  102. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tests/test_cs_step.py +0 -0
  103. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tests/test_dkist_location.py +0 -0
  104. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tests/test_fits_access.py +0 -0
  105. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tests/test_flower_pot.py +0 -0
  106. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tests/test_fried_parameter.py +0 -0
  107. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tests/test_input_dataset.py +0 -0
  108. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tests/test_interservice_bus.py +0 -0
  109. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tests/test_interservice_bus_mixin.py +0 -0
  110. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tests/test_manual_processing.py +0 -0
  111. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tests/test_output_data_base.py +0 -0
  112. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tests/test_parameters.py +0 -0
  113. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tests/test_publish_catalog_messages.py +0 -0
  114. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tests/test_quality.py +0 -0
  115. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tests/test_quality_mixin.py +0 -0
  116. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tests/test_scratch.py +0 -0
  117. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tests/test_submit_dataset_metadata.py +0 -0
  118. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tests/test_tags.py +0 -0
  119. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tests/test_task_name.py +0 -0
  120. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tests/test_task_parsing.py +0 -0
  121. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tests/test_teardown.py +0 -0
  122. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tests/test_transfer_input_data.py +0 -0
  123. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tests/test_transfer_l1_output_data.py +0 -0
  124. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tests/test_trial_catalog.py +0 -0
  125. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tests/test_trial_output_data.py +0 -0
  126. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common/tests/test_write_l1.py +0 -0
  127. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common.egg-info/dependency_links.txt +0 -0
  128. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common.egg-info/requires.txt +0 -0
  129. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/dkist_processing_common.egg-info/top_level.txt +0 -0
  130. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/docs/Makefile +0 -0
  131. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/docs/changelog.rst +0 -0
  132. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/docs/conf.py +0 -0
  133. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/docs/index.rst +0 -0
  134. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/docs/landing_page.rst +0 -0
  135. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/docs/make.bat +0 -0
  136. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/docs/requirements.txt +0 -0
  137. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/licenses/LICENSE.rst +0 -0
  138. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/pyproject.toml +0 -0
  139. {dkist_processing_common-11.9.2 → dkist_processing_common-11.9.3rc1}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dkist-processing-common
3
- Version: 11.9.2
3
+ Version: 11.9.3rc1
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
@@ -0,0 +1,3 @@
1
+ Add TimeLookupBud, which makes a dictionary that maps values of a time metadata key to values of another metadata key.
2
+ Values of the time metadata key are rounded to avoid jitter. Also add TaskTimeLookupBud, which makes the dictionary
3
+ only for frames of a particular task type.
@@ -0,0 +1,2 @@
1
+ Add a constant for dark number of frames per FPA. The constant returns a dictionary of exposure times as keys
2
+ and a list of number of frames per FPA as values.
@@ -53,6 +53,7 @@ class BudName(StrEnum):
53
53
  dark_date_end = "DARK_DATE_END"
54
54
  solar_gain_date_end = "SOLAR_GAIN_DATE_END"
55
55
  polcal_date_end = "POLCAL_DATE_END"
56
+ dark_num_raw_frames_per_fpa = "DARK_NUM_RAW_FRAMES_PER_FPA"
56
57
  solar_gain_num_raw_frames_per_fpa = "SOLAR_GAIN_NUM_RAW_FRAMES_PER_FPA"
57
58
  polcal_num_raw_frames_per_fpa = "POLCAL_NUM_RAW_FRAMES_PER_FPA"
58
59
  solar_gain_telescope_tracking_mode = "SOLAR_GAIN_TELESCOPE_TRACKING_MODE"
@@ -328,6 +329,13 @@ class ConstantsBase:
328
329
  """Return the date end constant for the polcal task."""
329
330
  return self._db_dict[BudName.polcal_date_end]
330
331
 
332
+ @property
333
+ def dark_num_raw_frames_per_fpa(self) -> dict[float, list]:
334
+ """Return the dictionary of exposure times to number of raw frames per fpa."""
335
+ raw_return = self._db_dict[BudName.dark_num_raw_frames_per_fpa]
336
+ # convert nested lists to dictionary
337
+ return {k: v for k, v in raw_return}
338
+
331
339
  @property
332
340
  def solar_gain_num_raw_frames_per_fpa(self) -> int:
333
341
  """Return the number of raw frames per fpa constant for the solar gain task."""
@@ -0,0 +1,129 @@
1
+ """Simple bud that is used to set a constant to a mapping dictionary."""
2
+
3
+ from collections import defaultdict
4
+ from enum import StrEnum
5
+ from typing import Any
6
+ from typing import Callable
7
+ from typing import DefaultDict
8
+
9
+ from dkist_processing_common.models.flower_pot import SpilledDirt
10
+ from dkist_processing_common.models.flower_pot import Stem
11
+ from dkist_processing_common.models.tags import EXP_TIME_ROUND_DIGITS
12
+ from dkist_processing_common.parsers.l0_fits_access import L0FitsAccess
13
+ from dkist_processing_common.parsers.task import passthrough_header_ip_task
14
+
15
+
16
+ class TimeLookupBud(Stem):
17
+ """
18
+ Bud that reads two header keys from all files and creates a dictionary mapping a time KEY value to sets of a VALUE value.
19
+
20
+ Parameters
21
+ ----------
22
+ constant_name
23
+ The name for the constant to be defined
24
+
25
+ key_metadata_key
26
+ The time metadata key for the resulting dictionary key
27
+
28
+ value_metadata_key
29
+ The metadata key for the resulting dictionary value
30
+ """
31
+
32
+ def __init__(
33
+ self,
34
+ constant_name: str,
35
+ key_metadata_key: str | StrEnum,
36
+ value_metadata_key: str | StrEnum,
37
+ ):
38
+ super().__init__(stem_name=constant_name)
39
+
40
+ if isinstance(key_metadata_key, StrEnum):
41
+ key_metadata_key = key_metadata_key.name
42
+ self.key_metadata_key = key_metadata_key
43
+ if isinstance(value_metadata_key, StrEnum):
44
+ value_metadata_key = value_metadata_key.name
45
+ self.value_metadata_key = value_metadata_key
46
+
47
+ self.mapping: DefaultDict[float, set[Any]] = defaultdict(set)
48
+
49
+ def setter(self, fits_obj: L0FitsAccess):
50
+ """
51
+ Update the mapping dictionary.
52
+
53
+ Parameters
54
+ ----------
55
+ fits_obj
56
+ The input fits object
57
+ Returns
58
+ -------
59
+ Updates the dictionary and returns None
60
+ """
61
+ key = getattr(fits_obj, self.key_metadata_key)
62
+ rounded_key = round(key, EXP_TIME_ROUND_DIGITS)
63
+ value = getattr(fits_obj, self.value_metadata_key)
64
+ self.mapping[rounded_key].add(value)
65
+ return None
66
+
67
+ def getter(self, key):
68
+ """
69
+ Get the dictionary mapping created by the setter converted into hashable nested tuples.
70
+
71
+ Parameters
72
+ ----------
73
+ key
74
+ The input key
75
+ Returns
76
+ -------
77
+ The mapping dictionary converted into hashable nested tuples
78
+ """
79
+ hashable_mapping = tuple((k, tuple(v)) for k, v in self.mapping.items())
80
+ return hashable_mapping
81
+
82
+
83
+ class TaskTimeLookupBud(TimeLookupBud):
84
+ """
85
+ Subclass of `TimeLookupBud` that only considers objects that have specific task types.
86
+
87
+ Parameters
88
+ ----------
89
+ constant_name
90
+ The name for the constant to be defined
91
+
92
+ key_metadata_key
93
+ The time metadata key for the resulting dictionary key
94
+
95
+ value_metadata_key
96
+ The metadata key for the resulting dictionary value
97
+
98
+ ip_task_types
99
+ Only consider objects whose parsed header IP task type matches a string in this list
100
+
101
+ task_type_parsing_function
102
+ The function used to convert a header into an IP task type
103
+ """
104
+
105
+ def __init__(
106
+ self,
107
+ constant_name: str,
108
+ key_metadata_key: str | StrEnum,
109
+ value_metadata_key: str | StrEnum,
110
+ ip_task_types: str | list[str],
111
+ task_type_parsing_function: Callable = passthrough_header_ip_task,
112
+ ):
113
+ super().__init__(
114
+ constant_name=constant_name,
115
+ key_metadata_key=key_metadata_key,
116
+ value_metadata_key=value_metadata_key,
117
+ )
118
+ if isinstance(ip_task_types, str):
119
+ ip_task_types = [ip_task_types]
120
+ self.ip_task_types = [task.casefold() for task in ip_task_types]
121
+ self.parsing_function = task_type_parsing_function
122
+
123
+ def setter(self, fits_obj: L0FitsAccess):
124
+ """Ingest an object only if its parsed IP task type matches what's desired."""
125
+ task = self.parsing_function(fits_obj)
126
+ if task.casefold() in self.ip_task_types:
127
+ return super().setter(fits_obj)
128
+
129
+ return SpilledDirt
@@ -37,6 +37,7 @@ from dkist_processing_common.models.task_name import TaskName
37
37
  from dkist_processing_common.parsers.average_bud import TaskAverageBud
38
38
  from dkist_processing_common.parsers.experiment_id_bud import ContributingExperimentIdsBud
39
39
  from dkist_processing_common.parsers.experiment_id_bud import ExperimentIdBud
40
+ from dkist_processing_common.parsers.lookup_bud import TaskTimeLookupBud
40
41
  from dkist_processing_common.parsers.observing_program_id_bud import (
41
42
  TaskContributingObservingProgramExecutionIdsBud,
42
43
  )
@@ -103,6 +104,12 @@ def dataset_extra_bud_factory() -> list[S]:
103
104
  constant_name=BudName.polcal_observing_program_execution_ids,
104
105
  ip_task_types=TaskName.polcal,
105
106
  ),
107
+ TaskTimeLookupBud(
108
+ constant_name=BudName.dark_num_raw_frames_per_fpa,
109
+ key_metadata_key=MetadataKey.sensor_readout_exposure_time_ms,
110
+ value_metadata_key=MetadataKey.num_raw_frames_per_fpa,
111
+ ip_task_types=TaskName.dark,
112
+ ),
106
113
  TaskUniqueBud(
107
114
  constant_name=BudName.solar_gain_num_raw_frames_per_fpa,
108
115
  metadata_key=MetadataKey.num_raw_frames_per_fpa,
@@ -17,6 +17,7 @@ from dkist_processing_common.models.flower_pot import Stem
17
17
  from dkist_processing_common.models.flower_pot import Thorn
18
18
  from dkist_processing_common.models.tags import StemName
19
19
  from dkist_processing_common.models.tags import Tag
20
+ from dkist_processing_common.parsers.lookup_bud import TimeLookupBud
20
21
  from dkist_processing_common.parsers.single_value_single_key_flower import (
21
22
  SingleValueSingleKeyFlower,
22
23
  )
@@ -117,6 +118,17 @@ def visp_buds():
117
118
  return [UniqueBud(constant_name=BudName.num_modstates, metadata_key=ViSPMetadataKey.num_mod)]
118
119
 
119
120
 
121
+ @pytest.fixture(scope="function")
122
+ def visp_lookup_buds():
123
+ return [
124
+ TimeLookupBud(
125
+ constant_name="LOOKUP_BUD",
126
+ key_metadata_key=ViSPMetadataKey.num_mod,
127
+ value_metadata_key=ViSPMetadataKey.modstate,
128
+ )
129
+ ]
130
+
131
+
120
132
  @pytest.fixture(scope="function")
121
133
  def empty_flowers():
122
134
  class EmptyFlower(Stem):
@@ -161,8 +173,17 @@ def picky_buds():
161
173
 
162
174
  @pytest.fixture(scope="function")
163
175
  def parse_inputs_task(
164
- tmp_path, visp_flowers, visp_buds, empty_flowers, empty_buds, picky_buds, recipe_run_id
176
+ tmp_path,
177
+ visp_flowers,
178
+ visp_buds,
179
+ visp_lookup_buds,
180
+ empty_flowers,
181
+ empty_buds,
182
+ picky_buds,
183
+ recipe_run_id,
165
184
  ):
185
+ """Override parse task class and make data for testing."""
186
+
166
187
  class TaskClass(ParseL0InputDataBase):
167
188
  @property
168
189
  def tag_flowers(self):
@@ -170,7 +191,7 @@ def parse_inputs_task(
170
191
 
171
192
  @property
172
193
  def constant_buds(self):
173
- return visp_buds + empty_buds + picky_buds
194
+ return visp_buds + visp_lookup_buds + empty_buds + picky_buds
174
195
 
175
196
  @property
176
197
  def fits_parsing_class(self):
@@ -210,6 +231,8 @@ def parse_inputs_task(
210
231
 
211
232
  @pytest.fixture()
212
233
  def visp_parse_inputs_task(tmp_path, visp_flowers, visp_buds, recipe_run_id):
234
+ """Extend parse task class, but don't make data for testing."""
235
+
213
236
  class TaskClass(ParseL0InputDataBase):
214
237
  @property
215
238
  def tag_flowers(self):
@@ -243,12 +266,13 @@ def test_make_flowerpots(parse_inputs_task):
243
266
  tag_pot, constant_pot = parse_inputs_task.make_flower_pots()
244
267
 
245
268
  assert len(tag_pot.stems) == 2
246
- assert len(constant_pot.stems) == 3
269
+ assert len(constant_pot.stems) == 4
247
270
  assert tag_pot.stems[0].stem_name == StemName.modstate
248
271
  assert tag_pot.stems[1].stem_name == "EMPTY_FLOWER"
249
272
  assert constant_pot.stems[0].stem_name == BudName.num_modstates
250
- assert constant_pot.stems[1].stem_name == "EMPTY_BUD"
251
- assert constant_pot.stems[2].stem_name == "PICKY_BUD"
273
+ assert constant_pot.stems[1].stem_name == "LOOKUP_BUD"
274
+ assert constant_pot.stems[2].stem_name == "EMPTY_BUD"
275
+ assert constant_pot.stems[3].stem_name == "PICKY_BUD"
252
276
 
253
277
 
254
278
  def test_subclass_flowers(visp_parse_inputs_task, max_cs_step_time_sec):
@@ -260,7 +284,7 @@ def test_subclass_flowers(visp_parse_inputs_task, max_cs_step_time_sec):
260
284
  tag_pot, constant_pot = visp_parse_inputs_task.make_flower_pots()
261
285
 
262
286
  assert len(tag_pot.stems) == 1
263
- assert len(constant_pot.stems) == 60
287
+ assert len(constant_pot.stems) == 61
264
288
  all_flower_names = [StemName.modstate]
265
289
  assert sorted([f.stem_name for f in tag_pot.stems]) == sorted(all_flower_names)
266
290
  all_bud_names = [b.stem_name for b in default_constant_bud_factory()] + [BudName.num_modstates]
@@ -296,27 +320,23 @@ def test_dataset_extra_bud_factory(visp_parse_inputs_task, max_cs_step_time_sec)
296
320
  ]
297
321
  for base in bud_name_base:
298
322
  assert "SOLAR_GAIN_" + base in stem_names
299
- if base not in [
300
- "NUM_RAW_FRAMES_PER_FPA",
301
- "TELESCOPE_TRACKING_MODE",
302
- "COUDE_TABLE_TRACKING_MODE",
303
- "TELESCOPE_SCANNING_MODE",
304
- ]:
305
- assert "DARK_" + base in stem_names
306
- if "GOS" not in base:
307
- assert "POLCAL_" + base in stem_names
323
+ # telescope mode keys are not constant for dark frames
324
+ assert ("DARK_" + base in stem_names) ^ ("MODE" in base)
325
+ # gos keys are not constant for polcal frames
326
+ assert ("POLCAL_" + base in stem_names) ^ ("GOS" in base)
308
327
 
309
328
 
310
329
  def test_constants_correct(parse_inputs_task):
311
330
  """
312
331
  Given: ParseInputData task with a populated constant FlowerPot
313
332
  When: Updating pipeline constants
314
- Then: A pipeline constant is correctly populated
333
+ Then: A pipeline constant is correctly populated and the values return correctly
315
334
  """
316
335
  _, constant_pot = parse_inputs_task.make_flower_pots()
317
336
  parse_inputs_task.update_constants(constant_pot)
318
337
  assert dict(parse_inputs_task.constants._db_dict) == {
319
338
  BudName.num_modstates.value: parse_inputs_task._num_mod,
339
+ "LOOKUP_BUD": [[parse_inputs_task._num_mod, [0, 1]]],
320
340
  }
321
341
 
322
342
 
@@ -1,3 +1,4 @@
1
+ import collections
1
2
  from enum import StrEnum
2
3
  from itertools import chain
3
4
 
@@ -17,6 +18,8 @@ from dkist_processing_common.parsers.dsps_repeat import TotalDspsRepeatsBud
17
18
  from dkist_processing_common.parsers.experiment_id_bud import ContributingExperimentIdsBud
18
19
  from dkist_processing_common.parsers.experiment_id_bud import ExperimentIdBud
19
20
  from dkist_processing_common.parsers.id_bud import TaskContributingIdsBud
21
+ from dkist_processing_common.parsers.lookup_bud import TaskTimeLookupBud
22
+ from dkist_processing_common.parsers.lookup_bud import TimeLookupBud
20
23
  from dkist_processing_common.parsers.near_bud import NearFloatBud
21
24
  from dkist_processing_common.parsers.near_bud import TaskNearFloatBud
22
25
  from dkist_processing_common.parsers.observing_program_id_bud import (
@@ -203,7 +206,7 @@ def basic_header_objs():
203
206
  "ID___012": "experiment_id_1",
204
207
  "XPOSURE": 100.0,
205
208
  "TEXPOSUR": 11.0,
206
- "NSUMEXP": 4,
209
+ "NSUMEXP": 5,
207
210
  "DSPSNUM": 2,
208
211
  "DSPSREPS": 2,
209
212
  "DATE-OBS": "2022-06-17T22:00:03.000",
@@ -1087,4 +1090,49 @@ def test_task_average_bud(basic_header_objs):
1087
1090
  assert round(petal[0].value, 3) == 1.227
1088
1091
 
1089
1092
 
1093
+ def test_time_lookup_bud(basic_header_objs):
1094
+ """
1095
+ Given: A set of headers with two differently valued header keys
1096
+ When: Ingesting headers with a TimeLookupBud and asking for the value
1097
+ Then: The bud's value is a dictionary of one key to sets of the other key as nested tuples
1098
+ """
1099
+ bud = TimeLookupBud(
1100
+ constant_name="lookup",
1101
+ key_metadata_key=FitsReaderMetadataKey.fpa_exposure_time_ms,
1102
+ value_metadata_key=FitsReaderMetadataKey.num_raw_frames_per_fpa,
1103
+ )
1104
+ assert bud.stem_name == "lookup"
1105
+ for fo in basic_header_objs:
1106
+ key = fo.name
1107
+ bud.update(key, fo)
1108
+
1109
+ assert type(bud.mapping) == collections.defaultdict
1110
+ assert bud.mapping == {0.0013: {3}, 12.345: {1}, 100.0: {4, 5}}
1111
+ assert len(bud.petals) == 1
1112
+ expected_value = ((0.0013, (3,)), (12.345, (1,)), (100.0, (4, 5)))
1113
+ assert bud.petals[0].value == expected_value
1114
+
1115
+
1116
+ def test_task_time_lookup_bud(basic_header_objs):
1117
+ """
1118
+ Given: A set of headers with two differently valued header keys
1119
+ When: Ingesting headers with a TaskTimeLookupBud and asking for the value
1120
+ Then: The bud's value is a dictionary of one key to sets of the other key as nested tuples
1121
+ """
1122
+ bud = TaskTimeLookupBud(
1123
+ constant_name="task_lookup",
1124
+ key_metadata_key=FitsReaderMetadataKey.fpa_exposure_time_ms,
1125
+ value_metadata_key=FitsReaderMetadataKey.num_raw_frames_per_fpa,
1126
+ ip_task_types="dark",
1127
+ )
1128
+ assert bud.stem_name == "task_lookup"
1129
+ for fo in basic_header_objs:
1130
+ key = fo.name
1131
+ bud.update(key, fo)
1132
+
1133
+ assert len(bud.petals) == 1
1134
+ expected_value = ((12.345, (1,)),)
1135
+ assert bud.petals[0].value == expected_value
1136
+
1137
+
1090
1138
  # TODO: test new stem types that have been added to parse_l0_input_data
@@ -175,6 +175,17 @@ def test_constants(workflow_data_task):
175
175
  assert task.constants.instrument_twice == "foofoo"
176
176
 
177
177
 
178
+ def test_constant_dark_num_raw_frames_per_fpa(workflow_data_task):
179
+ """
180
+ Given: a WorkflowDataTask's constants object
181
+ When: accessing a constant that does unusual processing in the property
182
+ Then: the value is correctly processed
183
+ """
184
+ task = workflow_data_task[0]
185
+ task.constants._update({BudName.dark_num_raw_frames_per_fpa: ((1.1, (2, 3)), (4.4, (5,)))})
186
+ assert task.constants.dark_num_raw_frames_per_fpa == {1.1: [2, 3], 4.4: [5]}
187
+
188
+
178
189
  def test_dataset_id(workflow_data_task):
179
190
  """
180
191
  Given: a ParsedL0InputTaskBase task
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dkist-processing-common
3
- Version: 11.9.2
3
+ Version: 11.9.3rc1
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
@@ -7,6 +7,8 @@ README.rst
7
7
  bitbucket-pipelines.yml
8
8
  pyproject.toml
9
9
  changelog/.gitempty
10
+ changelog/281.feature.1.rst
11
+ changelog/281.feature.rst
10
12
  dkist_processing_common/__init__.py
11
13
  dkist_processing_common/config.py
12
14
  dkist_processing_common/manual.py
@@ -58,6 +60,7 @@ dkist_processing_common/parsers/experiment_id_bud.py
58
60
  dkist_processing_common/parsers/id_bud.py
59
61
  dkist_processing_common/parsers/l0_fits_access.py
60
62
  dkist_processing_common/parsers/l1_fits_access.py
63
+ dkist_processing_common/parsers/lookup_bud.py
61
64
  dkist_processing_common/parsers/near_bud.py
62
65
  dkist_processing_common/parsers/observing_program_id_bud.py
63
66
  dkist_processing_common/parsers/proposal_id_bud.py