dkist-processing-common 14.3.0__tar.gz → 14.3.1__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 (142) hide show
  1. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/CHANGELOG.rst +11 -0
  2. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/PKG-INFO +1 -1
  3. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/models/quality.py +16 -1
  4. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tasks/l1_output_data.py +1 -6
  5. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tasks/mixin/quality/_base.py +0 -13
  6. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tasks/mixin/quality/_metrics.py +5 -41
  7. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tasks/quality_metrics.py +40 -10
  8. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tests/test_quality.py +42 -0
  9. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tests/test_quality_mixin.py +5 -46
  10. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common.egg-info/PKG-INFO +1 -1
  11. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/.gitignore +0 -0
  12. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/.pre-commit-config.yaml +0 -0
  13. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/.readthedocs.yml +0 -0
  14. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/.rovodev/.review-agent.md +0 -0
  15. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/.snyk +0 -0
  16. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/README.rst +0 -0
  17. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/bitbucket-pipelines.yml +0 -0
  18. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/changelog/.gitempty +0 -0
  19. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/__init__.py +0 -0
  20. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/_util/__init__.py +0 -0
  21. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/_util/constants.py +0 -0
  22. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/_util/graphql.py +0 -0
  23. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/_util/scratch.py +0 -0
  24. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/_util/tags.py +0 -0
  25. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/codecs/__init__.py +0 -0
  26. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/codecs/array.py +0 -0
  27. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/codecs/asdf.py +0 -0
  28. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/codecs/basemodel.py +0 -0
  29. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/codecs/bytes.py +0 -0
  30. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/codecs/fits.py +0 -0
  31. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/codecs/iobase.py +0 -0
  32. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/codecs/json.py +0 -0
  33. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/codecs/path.py +0 -0
  34. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/codecs/quality.py +0 -0
  35. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/codecs/str.py +0 -0
  36. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/config.py +0 -0
  37. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/fonts/Lato-Regular.ttf +0 -0
  38. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/fonts/__init__.py +0 -0
  39. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/manual.py +0 -0
  40. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/models/__init__.py +0 -0
  41. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/models/constants.py +0 -0
  42. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/models/dkist_location.py +0 -0
  43. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/models/extras.py +0 -0
  44. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/models/fits_access.py +0 -0
  45. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/models/flower_pot.py +0 -0
  46. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/models/fried_parameter.py +0 -0
  47. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/models/graphql.py +0 -0
  48. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/models/input_dataset.py +0 -0
  49. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/models/message.py +0 -0
  50. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/models/message_queue_binding.py +0 -0
  51. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/models/metric_code.py +0 -0
  52. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/models/parameters.py +0 -0
  53. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/models/tags.py +0 -0
  54. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/models/task_name.py +0 -0
  55. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/models/telemetry.py +0 -0
  56. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/models/wavelength.py +0 -0
  57. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/parsers/__init__.py +0 -0
  58. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/parsers/average_bud.py +0 -0
  59. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/parsers/cs_step.py +0 -0
  60. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/parsers/dsps_repeat.py +0 -0
  61. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/parsers/experiment_id_bud.py +0 -0
  62. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/parsers/id_bud.py +0 -0
  63. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/parsers/l0_fits_access.py +0 -0
  64. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/parsers/l1_fits_access.py +0 -0
  65. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/parsers/lookup_bud.py +0 -0
  66. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/parsers/near_bud.py +0 -0
  67. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/parsers/observing_program_id_bud.py +0 -0
  68. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/parsers/proposal_id_bud.py +0 -0
  69. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/parsers/quality.py +0 -0
  70. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/parsers/retarder.py +0 -0
  71. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/parsers/single_value_single_key_flower.py +0 -0
  72. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/parsers/task.py +0 -0
  73. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/parsers/time.py +0 -0
  74. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/parsers/unique_bud.py +0 -0
  75. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/parsers/wavelength.py +0 -0
  76. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tasks/__init__.py +0 -0
  77. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tasks/assemble_movie.py +0 -0
  78. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tasks/base.py +0 -0
  79. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tasks/mixin/__init__.py +0 -0
  80. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tasks/mixin/globus.py +0 -0
  81. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tasks/mixin/interservice_bus.py +0 -0
  82. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tasks/mixin/metadata_store.py +0 -0
  83. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tasks/mixin/object_store.py +0 -0
  84. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tasks/mixin/quality/__init__.py +0 -0
  85. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tasks/output_data_base.py +0 -0
  86. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tasks/parse_l0_input_data.py +0 -0
  87. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tasks/teardown.py +0 -0
  88. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tasks/transfer_input_data.py +0 -0
  89. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tasks/trial_catalog.py +0 -0
  90. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tasks/trial_output_data.py +0 -0
  91. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tasks/write_extra.py +0 -0
  92. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tasks/write_l1.py +0 -0
  93. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tasks/write_l1_base.py +0 -0
  94. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tests/__init__.py +0 -0
  95. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tests/conftest.py +0 -0
  96. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tests/mock_metadata_store.py +0 -0
  97. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tests/test_assemble_movie.py +0 -0
  98. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tests/test_assemble_quality.py +0 -0
  99. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tests/test_base.py +0 -0
  100. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tests/test_codecs.py +0 -0
  101. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tests/test_constants.py +0 -0
  102. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tests/test_construct_dataset_extras.py +0 -0
  103. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tests/test_cs_step.py +0 -0
  104. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tests/test_dkist_location.py +0 -0
  105. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tests/test_fits_access.py +0 -0
  106. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tests/test_flower_pot.py +0 -0
  107. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tests/test_fried_parameter.py +0 -0
  108. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tests/test_input_dataset.py +0 -0
  109. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tests/test_interservice_bus.py +0 -0
  110. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tests/test_interservice_bus_mixin.py +0 -0
  111. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tests/test_manual_processing.py +0 -0
  112. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tests/test_output_data_base.py +0 -0
  113. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tests/test_parameters.py +0 -0
  114. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tests/test_parse_l0_input_data.py +0 -0
  115. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tests/test_publish_catalog_messages.py +0 -0
  116. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tests/test_scratch.py +0 -0
  117. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tests/test_stems.py +0 -0
  118. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tests/test_submit_dataset_metadata.py +0 -0
  119. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tests/test_tags.py +0 -0
  120. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tests/test_task_name.py +0 -0
  121. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tests/test_task_parsing.py +0 -0
  122. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tests/test_teardown.py +0 -0
  123. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tests/test_transfer_input_data.py +0 -0
  124. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tests/test_transfer_l1_output_data.py +0 -0
  125. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tests/test_trial_catalog.py +0 -0
  126. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tests/test_trial_output_data.py +0 -0
  127. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tests/test_workflow_task_base.py +0 -0
  128. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common/tests/test_write_l1.py +0 -0
  129. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common.egg-info/SOURCES.txt +0 -0
  130. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common.egg-info/dependency_links.txt +0 -0
  131. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common.egg-info/requires.txt +0 -0
  132. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/dkist_processing_common.egg-info/top_level.txt +0 -0
  133. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/docs/Makefile +0 -0
  134. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/docs/changelog.rst +0 -0
  135. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/docs/conf.py +0 -0
  136. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/docs/index.rst +0 -0
  137. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/docs/landing_page.rst +0 -0
  138. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/docs/make.bat +0 -0
  139. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/docs/requirements.txt +0 -0
  140. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/licenses/LICENSE.rst +0 -0
  141. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/pyproject.toml +0 -0
  142. {dkist_processing_common-14.3.0 → dkist_processing_common-14.3.1}/setup.cfg +0 -0
@@ -1,3 +1,14 @@
1
+ v14.3.1 (2026-05-19)
2
+ ====================
3
+
4
+ Misc
5
+ ----
6
+
7
+ - Migrate `_find_iqr_outliers` from the quality mixin to the `QualityL0Metrics` workflow task. (`#340 <https://bitbucket.org/dkistdc/dkist-processing-common/pull-requests/340>`__)
8
+ - Migrate `quality_task_types` from the quality mixin to the `QualityL0Metrics` workflow task. (`#341 <https://bitbucket.org/dkistdc/dkist-processing-common/pull-requests/341>`__)
9
+ - Migrate `_format_facet` from the quality mixin to the `QualityMetric` `BaseModel`. (`#342 <https://bitbucket.org/dkistdc/dkist-processing-common/pull-requests/342>`__)
10
+
11
+
1
12
  v14.3.0 (2026-05-19)
2
13
  ====================
3
14
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dkist-processing-common
3
- Version: 14.3.0
3
+ Version: 14.3.1
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
@@ -333,13 +333,28 @@ class EfficiencyData(QualityModel):
333
333
  pass
334
334
 
335
335
 
336
+ def format_facet(v: Any) -> Any:
337
+ """Format the string input as a typical key. For example, `Beam 1` becomes `BEAM_1`."""
338
+ if v is None:
339
+ return None
340
+ if isinstance(v, str) and v.strip() == "":
341
+ return None
342
+ return str(v).replace(" ", "_").upper()
343
+
344
+
345
+ QualityFacet = Annotated[
346
+ str | None,
347
+ BeforeValidator(format_facet),
348
+ ]
349
+
350
+
336
351
  class QualityMetric(QualityModel):
337
352
  """Quality Metric."""
338
353
 
339
354
  name: str
340
355
  description: str
341
356
  metric_code: str
342
- facet: str | None = None
357
+ facet: QualityFacet = None
343
358
  statement: list[str] | None = None
344
359
  plot_data: list[XYData] | None = None
345
360
  multi_plot_data: list[MultiPlotData] | None = None
@@ -158,12 +158,7 @@ class TransferL1Data(TransferDataBase, GlobusMixin):
158
158
 
159
159
 
160
160
  class AssembleQualityData(L1OutputDataBase, QualityMixin):
161
- """
162
- Assemble quality data from the various quality metrics.
163
-
164
- **NOTE:** Please set `~dkist_processing_common.tasks.mixin.quality.QualityMixin.quality_task_types` in any subclass
165
- to the same value that was used in a subclass of `~dkist_processing_common.tasks.quality_metrics.QualityL0Metrics`.
166
- """
161
+ """Assemble quality data from the various quality metrics."""
167
162
 
168
163
  @property
169
164
  def polcal_label_list(self) -> list[str] | None:
@@ -5,14 +5,11 @@ from typing import Iterable
5
5
  from dkist_processing_common.codecs.json import json_encoder
6
6
  from dkist_processing_common.codecs.quality import QualityValueEncoder
7
7
  from dkist_processing_common.models.tags import Tag
8
- from dkist_processing_common.models.task_name import TaskName
9
8
  from dkist_processing_common.tasks.mixin.quality._metrics import _PolcalQualityMixin
10
- from dkist_processing_common.tasks.mixin.quality._metrics import _SimplePlotQualityMixin
11
9
  from dkist_processing_common.tasks.mixin.quality._metrics import _WavecalQualityMixin
12
10
 
13
11
 
14
12
  class QualityMixin(
15
- _SimplePlotQualityMixin,
16
13
  _PolcalQualityMixin,
17
14
  _WavecalQualityMixin,
18
15
  ):
@@ -46,16 +43,6 @@ class QualityMixin(
46
43
 
47
44
  return result
48
45
 
49
- @property
50
- def quality_task_types(self) -> list[str]:
51
- """Task types to use in generating metrics that work on several task types."""
52
- return [
53
- TaskName.dark.value,
54
- TaskName.gain.value,
55
- TaskName.lamp_gain.value,
56
- TaskName.solar_gain.value,
57
- ]
58
-
59
46
  @property
60
47
  def quality_metrics_no_task_dependence(self) -> dict:
61
48
  """Return a dict of the quality metrics with no task dependence."""
@@ -6,8 +6,6 @@ These classes should not be directly mixed in to anything. They are pre-mixed in
6
6
  import copy
7
7
  import json
8
8
  import logging
9
- from datetime import datetime
10
- from typing import Sequence
11
9
 
12
10
  import astropy.units as u
13
11
  import numpy as np
@@ -29,39 +27,12 @@ from dkist_processing_common.models.quality import PlotRaincloud
29
27
  from dkist_processing_common.models.quality import ReportMetric
30
28
  from dkist_processing_common.models.quality import SimpleTable
31
29
  from dkist_processing_common.models.quality import VerticalMultiPanePlot2D
30
+ from dkist_processing_common.models.quality import format_facet
32
31
  from dkist_processing_common.models.tags import Tag
33
32
 
34
33
  logger = logging.getLogger(__name__)
35
34
 
36
35
 
37
- class _SimplePlotQualityMixin:
38
- """Mixin containing metrics that present as simple x/y plots."""
39
-
40
- @staticmethod
41
- def _find_iqr_outliers(datetimes: Sequence[datetime], values: Sequence[float]) -> list[str]:
42
- """
43
- Given a list of values, find values that fall more than (1.5 * iqr) outside the quartiles of the data.
44
-
45
- Parameters
46
- ----------
47
- datetimes: list of datetime strings used to reference the files that are outliers
48
- values: values to use to determine outliers from the iqr
49
- """
50
- if len(values) == 0:
51
- raise ValueError("No values provided.")
52
- warnings = []
53
- q1 = np.quantile(values, 0.25)
54
- q3 = np.quantile(values, 0.75)
55
- iqr = q3 - q1
56
- for i, val in enumerate(values):
57
- if val < q1 - (iqr * 1.5) or val > q3 + (iqr * 1.5):
58
- warnings.append(
59
- f"File with datetime {datetimes[i]} has a value considered to be an outlier "
60
- f"for this metric"
61
- )
62
- return warnings
63
-
64
-
65
36
  class _PolcalQualityMixin:
66
37
  """Mixin Class supporting the building of polcal-specific metrics."""
67
38
 
@@ -112,13 +83,6 @@ class _PolcalQualityMixin:
112
83
  thinning_stride=thinning_stride,
113
84
  )
114
85
 
115
- @staticmethod
116
- def _format_facet(label: str | None) -> str | None:
117
- """Format the label as a typical key. For example, `Beam 1` becomes `BEAM_1`."""
118
- if label is None or label == "":
119
- return None
120
- return str(label).replace(" ", "_").upper()
121
-
122
86
  @staticmethod
123
87
  def _compute_thinning_stride(
124
88
  polcal_fitter: PolcalFitter, num_points_to_sample: int
@@ -340,7 +304,7 @@ class _PolcalQualityMixin:
340
304
  description="The deviation from database metrology values for Calibration Unit parameters used to compute "
341
305
  f"demodulation matrices. These parameters are fit the same across all polcal bins.",
342
306
  metric_code=MetricCode.polcal_global_par_vals,
343
- facet=self._format_facet(label),
307
+ facet=format_facet(label),
344
308
  table_data=SimpleTable(rows=table_data),
345
309
  warnings=self._format_warnings(data["warnings"]),
346
310
  )
@@ -481,7 +445,7 @@ class _PolcalQualityMixin:
481
445
  name=f"PolCal Local Bin Fits - {label}",
482
446
  description=description,
483
447
  metric_code=MetricCode.polcal_local_par_vals,
484
- facet=self._format_facet(label),
448
+ facet=format_facet(label),
485
449
  modmat_data=modmat_hist,
486
450
  histogram_data=param_histograms,
487
451
  )
@@ -601,7 +565,7 @@ class _PolcalQualityMixin:
601
565
  name=f"PolCal Fit Residuals - {label}",
602
566
  description=description,
603
567
  metric_code=MetricCode.polcal_fit_residuals,
604
- facet=self._format_facet(label),
568
+ facet=format_facet(label),
605
569
  histogram_data=chisq_hist,
606
570
  raincloud_data=residual_series,
607
571
  )
@@ -675,7 +639,7 @@ class _PolcalQualityMixin:
675
639
  name=f"PolCal Modulation Efficiency - {label}",
676
640
  description=description,
677
641
  metric_code=MetricCode.polcal_efficiency,
678
- facet=self._format_facet(label),
642
+ facet=format_facet(label),
679
643
  efficiency_data=EfficiencyHistograms(efficiency_list=data["efficiency_list"]),
680
644
  warnings=self._format_warnings(data["warnings"]),
681
645
  )
@@ -5,6 +5,7 @@ from collections import defaultdict
5
5
  from datetime import datetime
6
6
  from itertools import chain
7
7
  from typing import Iterable
8
+ from typing import Sequence
8
9
  from typing import Type
9
10
 
10
11
  import numpy as np
@@ -23,6 +24,7 @@ from dkist_processing_common.models.quality import TableData
23
24
  from dkist_processing_common.models.quality import TimeSeriesData
24
25
  from dkist_processing_common.models.quality import XYData
25
26
  from dkist_processing_common.models.tags import Tag
27
+ from dkist_processing_common.models.task_name import TaskName
26
28
  from dkist_processing_common.parsers.l0_fits_access import L0FitsAccess
27
29
  from dkist_processing_common.parsers.quality import L1QualityFitsAccess
28
30
  from dkist_processing_common.tasks.base import WorkflowTaskBase
@@ -76,20 +78,14 @@ class QualityL0Metrics(WorkflowTaskBase, QualityMixin):
76
78
  instruments this can be left as the default `Tag.input()`, but IR cameras will probably want to set this to
77
79
  `Tag.linearized()` or similar.
78
80
 
79
- `~dkist_processing_common.tasks.mixin.quality.QualityMixin.quality_task_types` (`list[str]`)
81
+ `quality_task_types` (`list[str]`)
80
82
  A list of IPTASK types. A separate set of L0 metrics will be reported for each task type listed here.
81
- See the definition of `~dkist_processing_common.tasks.mixin.quality.QualityMixin.quality_task_types` for the
82
- sensible defaults. If overloading, please use controlled `~dkist_processing_common.models.task_name.TaskName`
83
- values, if possible.
83
+ If overloading, please use controlled `~dkist_processing_common.models.task_name.TaskName` values, if possible.
84
84
 
85
85
  `modstate_list` (`list[int] | None`)
86
86
  A list of modstates over which to separate each metric. Adding modstates does not create new metric entries, but
87
87
  does sub-divide each TASK's metric into modstate bins. If you want *all* files of a single TASK to be considered
88
88
  together return ``None`` here.
89
-
90
- **NOTE:** The `~dkist_processing_common.tasks.mixin.quality.QualityMixin.quality_task_types` on an instrument
91
- subclass of `~dkist_processing_common.tasks.l1_output_data.AssembleQualityData` should match whatever is set here
92
- (although in both cases the default is probably fine).
93
89
  """
94
90
 
95
91
  @property
@@ -115,6 +111,40 @@ class QualityL0Metrics(WorkflowTaskBase, QualityMixin):
115
111
  """Define the `FitsAccess`-type class used to parse the headers of L0 frames."""
116
112
  return L0FitsAccess
117
113
 
114
+ @property
115
+ def quality_task_types(self) -> list[str]:
116
+ """Task types to use in generating metrics that work on several task types."""
117
+ return [
118
+ TaskName.dark.value,
119
+ TaskName.gain.value,
120
+ TaskName.lamp_gain.value,
121
+ TaskName.solar_gain.value,
122
+ ]
123
+
124
+ @staticmethod
125
+ def _find_iqr_outliers(datetimes: Sequence[datetime], values: Sequence[float]) -> list[str]:
126
+ """
127
+ Given a list of values, find values that fall more than (1.5 * iqr) outside the quartiles of the data.
128
+
129
+ Parameters
130
+ ----------
131
+ datetimes: list of datetime strings used to reference the files that are outliers
132
+ values: values to use to determine outliers from the iqr
133
+ """
134
+ if len(values) == 0:
135
+ raise ValueError("No values provided.")
136
+ warnings = []
137
+ q1 = np.quantile(values, 0.25)
138
+ q3 = np.quantile(values, 0.75)
139
+ iqr = q3 - q1
140
+ for i, val in enumerate(values):
141
+ if val < q1 - (iqr * 1.5) or val > q3 + (iqr * 1.5):
142
+ warnings.append(
143
+ f"File with datetime {datetimes[i]} has a value considered to be an outlier "
144
+ f"for this metric"
145
+ )
146
+ return warnings
147
+
118
148
  def run(self) -> None:
119
149
  """
120
150
  Calculate L0 quality metrics for all TASK/MODSTATE combinations.
@@ -316,7 +346,7 @@ class QualityL0Metrics(WorkflowTaskBase, QualityMixin):
316
346
  name=f"Average Across Frame - {task_type.upper()}",
317
347
  description=f"Average intensity value across frames of task type {task_type}. One measurement is taken per frame in each task type.",
318
348
  metric_code=MetricCode.frame_average,
319
- facet=task_type.upper(),
349
+ facet=task_type,
320
350
  plot_data=[xy_data],
321
351
  warnings=warnings,
322
352
  )
@@ -361,7 +391,7 @@ class QualityL0Metrics(WorkflowTaskBase, QualityMixin):
361
391
  name=f"Root Mean Square (RMS) Across Frame - {task_type.upper()}",
362
392
  description=f"RMS value across frames of task type {task_type}. One measurement is taken per frame in each task type.",
363
393
  metric_code=MetricCode.frame_rms,
364
- facet=task_type.upper(),
394
+ facet=task_type,
365
395
  plot_data=[xy_data],
366
396
  warnings=warnings,
367
397
  )
@@ -3,6 +3,7 @@
3
3
  from datetime import datetime
4
4
  from datetime import timedelta
5
5
  from pathlib import Path
6
+ from typing import Any
6
7
  from typing import Sequence
7
8
 
8
9
  import numpy as np
@@ -18,6 +19,7 @@ from dkist_processing_common.codecs.fits import fits_hdulist_encoder
18
19
  from dkist_processing_common.models.quality import QualityMetric
19
20
  from dkist_processing_common.models.quality import TableData
20
21
  from dkist_processing_common.models.quality import XYData
22
+ from dkist_processing_common.models.quality import format_facet
21
23
  from dkist_processing_common.models.tags import Tag
22
24
  from dkist_processing_common.models.task_name import TaskName
23
25
  from dkist_processing_common.tasks.quality_metrics import L0QualityData
@@ -1126,3 +1128,43 @@ def test_no_calibration_frames_no_l1_metrics(quality_l1_task_no_scratch_data: Qu
1126
1128
  task.read(tags=tags, decoder=basemodel_decoder, model=QualityMetric)
1127
1129
  )
1128
1130
  assert len(metrics) == 0
1131
+
1132
+
1133
+ def test_find_iqr_outliers(quality_l0_task):
1134
+ """
1135
+ Given: a list of float values
1136
+ When: checking data for outliers
1137
+ Then: the correct outliers are found
1138
+ """
1139
+ task = quality_l0_task
1140
+ start = datetime.now()
1141
+ datetimes = tuple([start + timedelta(milliseconds=i) for i in range(5)])
1142
+ values = [5.1, 4.9, 9.3, 5.3, 4.9]
1143
+ warnings = task._find_iqr_outliers(datetimes=datetimes, values=values)
1144
+ assert warnings == [
1145
+ f"File with datetime {datetimes[2]} has a value considered to be an outlier for this metric"
1146
+ ]
1147
+
1148
+
1149
+ @pytest.mark.parametrize(
1150
+ "label, expected_result",
1151
+ [
1152
+ pytest.param(None, None, id="none"),
1153
+ pytest.param("", None, id="empty"),
1154
+ pytest.param("abc", "ABC", id="lower"),
1155
+ pytest.param("XYZ", "XYZ", id="upper"),
1156
+ pytest.param("lMn", "LMN", id="mixed"),
1157
+ pytest.param("heLLo 1 abc", "HELLO_1__ABC", id="spaces"),
1158
+ pytest.param(0, "0", id="zero"),
1159
+ pytest.param(1, "1", id="one"),
1160
+ pytest.param(False, "FALSE", id="false"),
1161
+ pytest.param("@,$#", "@,$#", id="random"),
1162
+ ],
1163
+ )
1164
+ def test_format_facet(label: str | Any, expected_result: str):
1165
+ """
1166
+ Given: A label
1167
+ When: formatting the label as a key
1168
+ Then: the label is properly formatted
1169
+ """
1170
+ assert format_facet(label) == expected_result
@@ -1,6 +1,4 @@
1
1
  import json
2
- from datetime import datetime
3
- from datetime import timedelta
4
2
  from io import StringIO
5
3
  from typing import Any
6
4
 
@@ -19,6 +17,7 @@ from dkist_processing_common.codecs.quality import QualityValueEncoder
19
17
  from dkist_processing_common.models.metric_code import MetricCode
20
18
  from dkist_processing_common.models.quality import Plot2D
21
19
  from dkist_processing_common.models.quality import VerticalMultiPanePlot2D
20
+ from dkist_processing_common.models.quality import format_facet
22
21
  from dkist_processing_common.models.tags import Tag
23
22
  from dkist_processing_common.tasks import WorkflowTaskBase
24
23
  from dkist_processing_common.tasks.mixin.quality import QualityMixin
@@ -81,22 +80,6 @@ def test_format_warnings(quality_mixin_task):
81
80
  assert warnings is None
82
81
 
83
82
 
84
- def test_find_iqr_outliers(quality_mixin_task):
85
- """
86
- Given: a task with the QualityMixin
87
- When: checking data for outliers
88
- Then: the correct outliers are found
89
- """
90
- task = quality_mixin_task
91
- start = datetime.now()
92
- datetimes = tuple([start + timedelta(milliseconds=i) for i in range(5)])
93
- values = [5.1, 4.9, 9.3, 5.3, 4.9]
94
- warnings = task._find_iqr_outliers(datetimes=datetimes, values=values)
95
- assert warnings == [
96
- f"File with datetime {datetimes[2]} has a value considered to be an outlier for this metric"
97
- ]
98
-
99
-
100
83
  @pytest.mark.parametrize(
101
84
  "thin, samples_larger_than_total",
102
85
  [
@@ -362,7 +345,7 @@ def test_polcal_build_global_parameter_values(quality_mixin_task, polcal_global_
362
345
 
363
346
  assert metric["name"] == f"PolCal Global Calibration Unit Fit - {label}"
364
347
  assert metric["metric_code"] == "POLCAL_GLOBAL_PAR_VALS"
365
- assert metric["facet"] == quality_mixin_task._format_facet(label)
348
+ assert metric["facet"] == format_facet(label)
366
349
  assert metric["warnings"] == ["A thing is bad"]
367
350
  metric_table = metric["table_data"]["rows"]
368
351
  assert len(metric_table) == 4 # 3 rows + one for header
@@ -416,7 +399,7 @@ def test_polcal_build_local_parameter_values(quality_mixin_task, polcal_local_pa
416
399
 
417
400
  assert metric["name"] == f"PolCal Local Bin Fits - {label}"
418
401
  assert metric["metric_code"] == "POLCAL_LOCAL_PAR_VALS"
419
- assert metric["facet"] == quality_mixin_task._format_facet(label)
402
+ assert metric["facet"] == format_facet(label)
420
403
  assert metric["description"].endswith(
421
404
  "Data show 3 uniformly sampled points from 6 total points spanning 2 spatial and 3 radical bins."
422
405
  )
@@ -468,7 +451,7 @@ def test_polcal_build_fit_residuals(quality_mixin_task, polcal_fit_residuals_jso
468
451
 
469
452
  assert metric["name"] == f"PolCal Fit Residuals - {label}"
470
453
  assert metric["metric_code"] == "POLCAL_FIT_RESIDUALS"
471
- assert metric["facet"] == quality_mixin_task._format_facet(label)
454
+ assert metric["facet"] == format_facet(label)
472
455
 
473
456
  assert metric["description"].endswith(
474
457
  "Data show 3 uniformly sampled points from 6 total points spanning 21 financial bins."
@@ -521,7 +504,7 @@ def test_polcal_build_efficiency(quality_mixin_task, polcal_efficiency_json):
521
504
  "Data show 33 uniformly sampled points from 99 total points spanning 2 spatial, 4 forever, and 6 smelly bins."
522
505
  )
523
506
  assert metric["metric_code"] == "POLCAL_EFFICIENCY"
524
- assert metric["facet"] == quality_mixin_task._format_facet(label)
507
+ assert metric["facet"] == format_facet(label)
525
508
  efficiency_data = metric["efficiency_data"]
526
509
  assert efficiency_data["efficiency_list"] == [[1.0, 2.0], [2.0, 3.0]]
527
510
 
@@ -759,30 +742,6 @@ def test_compute_bin_description(
759
742
  assert result == expected_full
760
743
 
761
744
 
762
- @pytest.mark.parametrize(
763
- "label, expected_result",
764
- [
765
- pytest.param(None, None, id="none"),
766
- pytest.param("", None, id="empty"),
767
- pytest.param("abc", "ABC", id="lower"),
768
- pytest.param("XYZ", "XYZ", id="upper"),
769
- pytest.param("lMn", "LMN", id="mixed"),
770
- pytest.param("heLLo 1 abc", "HELLO_1__ABC", id="spaces"),
771
- pytest.param(0, "0", id="zero"),
772
- pytest.param(1, "1", id="one"),
773
- pytest.param(False, "FALSE", id="false"),
774
- pytest.param("@,$#", "@,$#", id="random"),
775
- ],
776
- )
777
- def test_format_facet(label: str | Any, expected_result: str):
778
- """
779
- Given: A label
780
- When: formatting the label as a key
781
- Then: the label is properly formatted
782
- """
783
- assert QualityMixin._format_facet(label) == expected_result
784
-
785
-
786
745
  def test_validate_vertical_multi_pane_plot_model():
787
746
  """
788
747
  Given: A `VerticalMultiPanePlot2D` model and some `Plot2D` models
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dkist-processing-common
3
- Version: 14.3.0
3
+ Version: 14.3.1
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