dkist-processing-common 6.2.1rc2__tar.gz → 6.2.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/CHANGELOG.rst +21 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/PKG-INFO +2 -1
- dkist-processing-common-6.2.2/dkist_processing_common/codecs/quality.py +88 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/models/tags.py +14 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/tasks/base.py +3 -1
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/tasks/l1_output_data.py +79 -56
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/tasks/mixin/metadata_store.py +5 -5
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/tasks/mixin/quality/_base.py +3 -3
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/tasks/quality_metrics.py +3 -1
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/tasks/trial_catalog.py +54 -1
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/tasks/trial_output_data.py +27 -0
- dkist-processing-common-6.2.2/dkist_processing_common/tests/test_assemble_quality.py +520 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/tests/test_codecs.py +346 -43
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/tests/test_quality.py +1 -6
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/tests/test_quality_mixin.py +3 -3
- dkist-processing-common-6.2.2/dkist_processing_common/tests/test_submit_dataset_metadata.py +111 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/tests/test_trial_catalog.py +62 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/tests/test_trial_output_data.py +130 -25
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common.egg-info/PKG-INFO +2 -1
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common.egg-info/SOURCES.txt +3 -5
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common.egg-info/requires.txt +4 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/setup.cfg +3 -0
- dkist-processing-common-6.2.1rc2/changelog/124.misc.rst +0 -1
- dkist-processing-common-6.2.1rc2/changelog/186.misc.rst +0 -1
- dkist-processing-common-6.2.1rc2/changelog/187.misc.rst +0 -1
- dkist-processing-common-6.2.1rc2/changelog/188.misc.rst +0 -1
- dkist-processing-common-6.2.1rc2/dkist_processing_common/models/quality_json_encoders.py +0 -31
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/.gitignore +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/.pre-commit-config.yaml +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/.readthedocs.yml +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/README.rst +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/bitbucket-pipelines.yml +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/changelog/.gitempty +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/check_changelog_updated.sh +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/__init__.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/_util/__init__.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/_util/config.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/_util/constants.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/_util/dkist_location.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/_util/graphql.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/_util/scratch.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/_util/tags.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/codecs/__init__.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/codecs/asdf.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/codecs/bytes.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/codecs/fits.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/codecs/iobase.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/codecs/json.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/codecs/path.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/codecs/str.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/fonts/Lato-Regular.ttf +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/fonts/__init__.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/manual.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/models/__init__.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/models/constants.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/models/fits_access.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/models/flower_pot.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/models/graphql.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/models/message.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/models/parameters.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/models/quality.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/models/task_name.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/models/wavelength.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/parsers/__init__.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/parsers/cs_step.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/parsers/dsps_repeat.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/parsers/experiment_id_bud.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/parsers/id_bud.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/parsers/l0_fits_access.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/parsers/l1_fits_access.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/parsers/proposal_id_bud.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/parsers/quality.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/parsers/single_value_single_key_flower.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/parsers/task.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/parsers/time.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/parsers/unique_bud.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/parsers/wavelength.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/tasks/__init__.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/tasks/assemble_movie.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/tasks/mixin/__init__.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/tasks/mixin/globus.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/tasks/mixin/input_dataset.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/tasks/mixin/interservice_bus.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/tasks/mixin/object_store.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/tasks/mixin/quality/__init__.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/tasks/mixin/quality/_metrics.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/tasks/output_data_base.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/tasks/parse_l0_input_data.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/tasks/teardown.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/tasks/transfer_input_data.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/tasks/write_l1.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/tests/__init__.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/tests/conftest.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/tests/test_assemble_movie.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/tests/test_base.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/tests/test_constants.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/tests/test_cs_step.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/tests/test_dkist_location.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/tests/test_fits_access.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/tests/test_flower_pot.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/tests/test_input_dataset.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/tests/test_output_data_base.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/tests/test_parameters.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/tests/test_parse_l0_input_data.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/tests/test_publish_catalog_messages.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/tests/test_scratch.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/tests/test_stems.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/tests/test_tags.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/tests/test_task_name.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/tests/test_task_parsing.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/tests/test_teardown.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/tests/test_transfer_input_data.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/tests/test_transfer_l1_output_data.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/tests/test_workflow_task_base.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common/tests/test_write_l1.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common.egg-info/dependency_links.txt +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/dkist_processing_common.egg-info/top_level.txt +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/docs/Makefile +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/docs/changelog.rst +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/docs/conf.py +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/docs/index.rst +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/docs/make.bat +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/docs/requirements.txt +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/licenses/LICENSE.rst +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/pyproject.toml +0 -0
- {dkist-processing-common-6.2.1rc2 → dkist-processing-common-6.2.2}/setup.py +0 -0
|
@@ -1,3 +1,24 @@
|
|
|
1
|
+
v6.2.2 (2024-05-07)
|
|
2
|
+
===================
|
|
3
|
+
|
|
4
|
+
Features
|
|
5
|
+
--------
|
|
6
|
+
|
|
7
|
+
- Add the ability to create a quality report from a trial workflow. (`#185 <https://bitbucket.org/dkistdc/dkist-processing-common/pull-requests/185>`__)
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
v6.2.1 (2024-05-01)
|
|
11
|
+
===================
|
|
12
|
+
|
|
13
|
+
Misc
|
|
14
|
+
----
|
|
15
|
+
|
|
16
|
+
- Change filenames of browse movie and quality report to free up namespace for other future files. (`#124 <https://bitbucket.org/dkistdc/dkist-processing-common/pull-requests/124>`__)
|
|
17
|
+
- Trial framework asdf filenames match production run asdf filenames. (`#186 <https://bitbucket.org/dkistdc/dkist-processing-common/pull-requests/186>`__)
|
|
18
|
+
- Capture tracing data for rollback calls to enhance observability. (`#187 <https://bitbucket.org/dkistdc/dkist-processing-common/pull-requests/187>`__)
|
|
19
|
+
- Update legacy type hinting. (`#188 <https://bitbucket.org/dkistdc/dkist-processing-common/pull-requests/188>`__)
|
|
20
|
+
|
|
21
|
+
|
|
1
22
|
v6.1.2 (2024-04-12)
|
|
2
23
|
===================
|
|
3
24
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: dkist-processing-common
|
|
3
|
-
Version: 6.2.
|
|
3
|
+
Version: 6.2.2
|
|
4
4
|
Summary: Common task classes used by the DKIST Science Data Processing pipelines to process DKIST data.
|
|
5
5
|
Home-page: https://bitbucket.org/dkistdc/dkist-processing-common/src/main/
|
|
6
6
|
Author: NSO / AURA
|
|
@@ -15,6 +15,7 @@ Provides-Extra: test
|
|
|
15
15
|
Provides-Extra: docs
|
|
16
16
|
Provides-Extra: inventory
|
|
17
17
|
Provides-Extra: asdf
|
|
18
|
+
Provides-Extra: quality
|
|
18
19
|
|
|
19
20
|
dkist-processing-common
|
|
20
21
|
=======================
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"""Encoder/decoders for writing and reading quality data."""
|
|
2
|
+
import json
|
|
3
|
+
import logging
|
|
4
|
+
from datetime import datetime
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import Any
|
|
7
|
+
|
|
8
|
+
import numpy as np
|
|
9
|
+
|
|
10
|
+
from dkist_processing_common.codecs.json import json_decoder
|
|
11
|
+
from dkist_processing_common.codecs.json import json_encoder
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
logger = logging.getLogger(__name__)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class QualityDataEncoder(json.JSONEncoder):
|
|
18
|
+
"""A JSON encoder for the quality data."""
|
|
19
|
+
|
|
20
|
+
def __init__(self, **dumps_kwargs):
|
|
21
|
+
# Raise a ValueError for NaN and Infinity.
|
|
22
|
+
dumps_kwargs["allow_nan"] = False
|
|
23
|
+
super().__init__(**dumps_kwargs)
|
|
24
|
+
|
|
25
|
+
def default(self, obj) -> dict:
|
|
26
|
+
"""Encode datetime as dict of iso formatted strings. JSONEncoder will later render the dict as a string."""
|
|
27
|
+
if isinstance(obj, datetime):
|
|
28
|
+
return {"iso_date": obj.isoformat("T")}
|
|
29
|
+
return super().default(obj)
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
def quality_data_encoder(
|
|
33
|
+
data: Any, encoding: str = "utf-8", errors="strict", **dumps_kwargs
|
|
34
|
+
) -> bytes:
|
|
35
|
+
"""Convert quality data to bytes by encoding as JSON."""
|
|
36
|
+
# This encoder is for the QualityDataEncoder class
|
|
37
|
+
if cls := dumps_kwargs.pop("cls", None):
|
|
38
|
+
logger.info(
|
|
39
|
+
f"Ignoring {cls=}. Default JSONEncoder for quality_data_encoder is QualityDataEncoder."
|
|
40
|
+
)
|
|
41
|
+
# allow_nan is per QualityDataEncoder class
|
|
42
|
+
if allow_nan := dumps_kwargs.pop("allow_nan", None):
|
|
43
|
+
logger.info(f"Ignoring {allow_nan=} for quality_data_encoder.")
|
|
44
|
+
|
|
45
|
+
return json_encoder(
|
|
46
|
+
data, encoding=encoding, errors=errors, cls=QualityDataEncoder, **dumps_kwargs
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def quality_data_hook(obj: dict):
|
|
51
|
+
"""
|
|
52
|
+
Decode iso date dict.
|
|
53
|
+
|
|
54
|
+
Convert object being json decoded into a datetime object if in the format `{"iso_date":"<iso formatted string>"}`
|
|
55
|
+
like those produced by QualityDataEncoder.
|
|
56
|
+
This is the same as datetime_json_object_hook in dkist-quality.
|
|
57
|
+
:param obj: dict of the object being json decoded
|
|
58
|
+
:return: datetime object
|
|
59
|
+
"""
|
|
60
|
+
# extract date string if present in the object dict
|
|
61
|
+
iso_date = obj.get("iso_date")
|
|
62
|
+
if iso_date is not None:
|
|
63
|
+
return datetime.fromisoformat(iso_date)
|
|
64
|
+
# iso_date not found - not covered by this hook
|
|
65
|
+
return obj
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
def quality_data_decoder(
|
|
69
|
+
path: Path, encoding: str = "utf-8", errors="strict", **loads_kwargs
|
|
70
|
+
) -> Any:
|
|
71
|
+
"""Read a file as JSON and return the decoded objects."""
|
|
72
|
+
if object_hook := loads_kwargs.pop("object_hook", None):
|
|
73
|
+
logger.info(f"Ignoring {object_hook=} for quality_data_decoder.")
|
|
74
|
+
|
|
75
|
+
return json_decoder(
|
|
76
|
+
path, encoding=encoding, errors=errors, object_hook=quality_data_hook, **loads_kwargs
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
class QualityValueEncoder(json.JSONEncoder):
|
|
81
|
+
"""A JSON encoder applied to the quality metrics."""
|
|
82
|
+
|
|
83
|
+
def default(self, obj: Any) -> Any:
|
|
84
|
+
"""Implement an encoder that correctly handles numpy float32 data."""
|
|
85
|
+
# np.float32 is only for single values. Even an array of np.float32 objects is a np.ndarray
|
|
86
|
+
if isinstance(obj, np.float32):
|
|
87
|
+
return float(obj)
|
|
88
|
+
return super().default(obj)
|
|
@@ -30,8 +30,12 @@ class StemName(str, Enum):
|
|
|
30
30
|
parameter = "PARAMETER"
|
|
31
31
|
workflow_task = "WORKFLOW_TASK"
|
|
32
32
|
debug = "DEBUG"
|
|
33
|
+
# The QUALITY_DATA is the json data that normally gets stored to the remote (metadata store) database.
|
|
34
|
+
quality_data = "QUALITY_DATA"
|
|
35
|
+
# For trial workflows.
|
|
33
36
|
dataset_inventory = "DATASET_INVENTORY"
|
|
34
37
|
asdf = "ASDF"
|
|
38
|
+
quality_report = "QUALITY_REPORT"
|
|
35
39
|
|
|
36
40
|
|
|
37
41
|
class Tag:
|
|
@@ -173,6 +177,16 @@ class Tag:
|
|
|
173
177
|
"""Return a debug tag."""
|
|
174
178
|
return cls.format_tag(StemName.debug)
|
|
175
179
|
|
|
180
|
+
@classmethod
|
|
181
|
+
def quality_data(cls) -> str:
|
|
182
|
+
"""Tags the quality data that normally gets stored to the remote database."""
|
|
183
|
+
return cls.format_tag(StemName.quality_data.value)
|
|
184
|
+
|
|
185
|
+
@classmethod
|
|
186
|
+
def quality_report(cls) -> str:
|
|
187
|
+
"""Tags the quality report .pdf that gets stored to the file system for trial workflows."""
|
|
188
|
+
return cls.format_tag(StemName.quality_report.value)
|
|
189
|
+
|
|
176
190
|
# Task type tags
|
|
177
191
|
@classmethod
|
|
178
192
|
def task_observe(cls) -> str:
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""Wrappers for all workflow tasks."""
|
|
2
2
|
import json
|
|
3
3
|
import logging
|
|
4
|
+
import re
|
|
4
5
|
from abc import ABC
|
|
5
6
|
from pathlib import Path
|
|
6
7
|
from typing import Any
|
|
@@ -279,7 +280,8 @@ class WorkflowTaskBase(TaskBase, MetadataStoreMixin, ABC):
|
|
|
279
280
|
sorted_remaining_tags = sorted(copied_tags)
|
|
280
281
|
filename_parts += sorted_remaining_tags
|
|
281
282
|
|
|
282
|
-
|
|
283
|
+
# replace spaces and underscores with dashes - dynamic part (e.g. polcal `Beam 1` label) may include spaces
|
|
284
|
+
dash_separated_parts = [re.sub("[ _]", "-", t) for t in filename_parts]
|
|
283
285
|
|
|
284
286
|
base_filename = "_".join(dash_separated_parts)
|
|
285
287
|
base_filename_counter = str(self.filename_counter.increment(base_filename))
|
|
@@ -1,31 +1,36 @@
|
|
|
1
1
|
"""Task(s) for the transfer and publishing of L1 data from a production run of a processing pipeline."""
|
|
2
2
|
import logging
|
|
3
|
+
from abc import ABC
|
|
4
|
+
from itertools import chain
|
|
3
5
|
from pathlib import Path
|
|
4
6
|
from typing import Iterable
|
|
5
7
|
|
|
8
|
+
from dkist_processing_common.codecs.quality import quality_data_decoder
|
|
9
|
+
from dkist_processing_common.codecs.quality import quality_data_encoder
|
|
6
10
|
from dkist_processing_common.models.message import CatalogFrameMessage
|
|
7
11
|
from dkist_processing_common.models.message import CatalogObjectMessage
|
|
8
12
|
from dkist_processing_common.models.message import CreateQualityReportMessage
|
|
9
13
|
from dkist_processing_common.models.tags import Tag
|
|
10
14
|
from dkist_processing_common.tasks.mixin.globus import GlobusMixin
|
|
11
15
|
from dkist_processing_common.tasks.mixin.interservice_bus import InterserviceBusMixin
|
|
16
|
+
from dkist_processing_common.tasks.mixin.quality import QualityMixin
|
|
17
|
+
from dkist_processing_common.tasks.output_data_base import OutputDataBase
|
|
18
|
+
from dkist_processing_common.tasks.output_data_base import TransferDataBase
|
|
12
19
|
|
|
13
20
|
|
|
14
21
|
__all__ = [
|
|
15
|
-
"AddDatasetReceiptAccount",
|
|
16
|
-
"PublishCatalogAndQualityMessages",
|
|
17
|
-
"TransferL1Data",
|
|
18
22
|
"L1OutputDataBase",
|
|
19
|
-
"
|
|
23
|
+
"TransferL1Data",
|
|
24
|
+
"AssembleQualityData",
|
|
25
|
+
"SubmitDatasetMetadata",
|
|
26
|
+
"PublishCatalogAndQualityMessages",
|
|
20
27
|
]
|
|
21
28
|
|
|
22
|
-
from dkist_processing_common.tasks.mixin.quality import QualityMixin
|
|
23
|
-
from dkist_processing_common.tasks.output_data_base import OutputDataBase, TransferDataBase
|
|
24
29
|
|
|
25
30
|
logger = logging.getLogger(__name__)
|
|
26
31
|
|
|
27
32
|
|
|
28
|
-
class L1OutputDataBase(OutputDataBase,
|
|
33
|
+
class L1OutputDataBase(OutputDataBase, ABC):
|
|
29
34
|
"""Subclass of OutputDataBase which encapsulates common level 1 output data methods."""
|
|
30
35
|
|
|
31
36
|
@property
|
|
@@ -94,6 +99,72 @@ class TransferL1Data(TransferDataBase, GlobusMixin):
|
|
|
94
99
|
)
|
|
95
100
|
|
|
96
101
|
|
|
102
|
+
class AssembleQualityData(L1OutputDataBase, QualityMixin):
|
|
103
|
+
"""Assemble quality data from the various quality metrics."""
|
|
104
|
+
|
|
105
|
+
@property
|
|
106
|
+
def polcal_label_list(self) -> list[str] | None:
|
|
107
|
+
"""Return the list of labels to look for when building polcal metrics.
|
|
108
|
+
|
|
109
|
+
If no labels are specified then no polcal metrics will be built.
|
|
110
|
+
"""
|
|
111
|
+
return None
|
|
112
|
+
|
|
113
|
+
def run(self):
|
|
114
|
+
"""Run method for the task."""
|
|
115
|
+
with self.apm_processing_step("Assembling quality data"):
|
|
116
|
+
quality_data = self.quality_assemble_data(polcal_label_list=self.polcal_label_list)
|
|
117
|
+
|
|
118
|
+
with self.apm_writing_step(
|
|
119
|
+
f"Saving quality data with {len(quality_data)} metrics to the file system"
|
|
120
|
+
):
|
|
121
|
+
self.write(
|
|
122
|
+
quality_data,
|
|
123
|
+
tags=Tag.quality_data(),
|
|
124
|
+
encoder=quality_data_encoder,
|
|
125
|
+
relative_path=f"{self.constants.dataset_id}_quality_data.json",
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
|
|
129
|
+
class SubmitDatasetMetadata(L1OutputDataBase):
|
|
130
|
+
"""
|
|
131
|
+
Add quality data and receipt account to the metadata store.
|
|
132
|
+
|
|
133
|
+
Add the quality data to the Quality database.
|
|
134
|
+
Add a Dataset Receipt Account record to Processing Support for use by the Dataset Catalog Locker.
|
|
135
|
+
Adds the number of files created during the calibration processing to the Processing Support table
|
|
136
|
+
for use by the Dataset Catalog Locker.
|
|
137
|
+
"""
|
|
138
|
+
|
|
139
|
+
def run(self) -> None:
|
|
140
|
+
"""Run method for this task."""
|
|
141
|
+
with self.apm_writing_step(f"Storing quality data to metadata store"):
|
|
142
|
+
# each quality_data file is a list - this will combine the elements of multiple lists into a single list
|
|
143
|
+
quality_data = list(
|
|
144
|
+
chain.from_iterable(
|
|
145
|
+
self.read(tags=Tag.quality_data(), decoder=quality_data_decoder)
|
|
146
|
+
)
|
|
147
|
+
)
|
|
148
|
+
self.metadata_store_add_quality_data(
|
|
149
|
+
dataset_id=self.constants.dataset_id, quality_data=quality_data
|
|
150
|
+
)
|
|
151
|
+
with self.apm_processing_step("Count Expected Outputs"):
|
|
152
|
+
dataset_id = self.constants.dataset_id
|
|
153
|
+
expected_object_count = self.count(tags=Tag.output())
|
|
154
|
+
if self.dataset_has_quality_report:
|
|
155
|
+
expected_object_count += 1
|
|
156
|
+
logger.info(
|
|
157
|
+
f"Adding Dataset Receipt Account: "
|
|
158
|
+
f"{dataset_id=}, {expected_object_count=}, recipe_run_id={self.recipe_run_id}"
|
|
159
|
+
)
|
|
160
|
+
with self.apm_task_step(
|
|
161
|
+
f"Add Dataset Receipt Account: {dataset_id = }, {expected_object_count = }"
|
|
162
|
+
):
|
|
163
|
+
self.metadata_store_add_dataset_receipt_account(
|
|
164
|
+
dataset_id=dataset_id, expected_object_count=expected_object_count
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
|
|
97
168
|
class PublishCatalogAndQualityMessages(L1OutputDataBase, InterserviceBusMixin):
|
|
98
169
|
"""Task class for publishing Catalog and Quality Messages."""
|
|
99
170
|
|
|
@@ -162,7 +233,7 @@ class PublishCatalogAndQualityMessages(L1OutputDataBase, InterserviceBusMixin):
|
|
|
162
233
|
)
|
|
163
234
|
|
|
164
235
|
def run(self) -> None:
|
|
165
|
-
"""Run method for this
|
|
236
|
+
"""Run method for this task."""
|
|
166
237
|
with self.apm_task_step("Gather output data"):
|
|
167
238
|
frames = self.read(tags=self.output_frame_tags)
|
|
168
239
|
movies = self.read(tags=[Tag.output(), Tag.movie()])
|
|
@@ -179,51 +250,3 @@ class PublishCatalogAndQualityMessages(L1OutputDataBase, InterserviceBusMixin):
|
|
|
179
250
|
f"Publish messages: {frame_message_count = }, {object_message_count = }, {dataset_has_quality_report = }"
|
|
180
251
|
):
|
|
181
252
|
self.interservice_bus_publish(messages=messages)
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
class AddDatasetReceiptAccount(L1OutputDataBase):
|
|
185
|
-
"""
|
|
186
|
-
Add a Dataset Receipt Account record to Processing Support for use by the Dataset Catalog Locker.
|
|
187
|
-
|
|
188
|
-
Adds the number of files created during the calibration processing to the Processing Support table
|
|
189
|
-
for use by the Dataset Catalog Locker.
|
|
190
|
-
"""
|
|
191
|
-
|
|
192
|
-
def run(self) -> None:
|
|
193
|
-
"""Run method for this task."""
|
|
194
|
-
with self.apm_processing_step("Count Expected Outputs"):
|
|
195
|
-
dataset_id = self.constants.dataset_id
|
|
196
|
-
expected_object_count = self.count(tags=Tag.output())
|
|
197
|
-
if self.dataset_has_quality_report:
|
|
198
|
-
expected_object_count += 1
|
|
199
|
-
logger.info(
|
|
200
|
-
f"Adding Dataset Receipt Account: "
|
|
201
|
-
f"{dataset_id=}, {expected_object_count=}, recipe_run_id={self.recipe_run_id}"
|
|
202
|
-
)
|
|
203
|
-
with self.apm_task_step(
|
|
204
|
-
f"Add Dataset Receipt Account: {dataset_id = }, {expected_object_count = }"
|
|
205
|
-
):
|
|
206
|
-
self.metadata_store_add_dataset_receipt_account(
|
|
207
|
-
dataset_id=dataset_id, expected_object_count=expected_object_count
|
|
208
|
-
)
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
class SubmitQuality(L1OutputDataBase, QualityMixin):
|
|
212
|
-
"""Task class for submitting the quality report to the metadata store."""
|
|
213
|
-
|
|
214
|
-
@property
|
|
215
|
-
def polcal_label_list(self) -> list[str] | None:
|
|
216
|
-
"""Return the list of labels to look for when building polcal metrics.
|
|
217
|
-
|
|
218
|
-
If no labels are specified then no polcal metrics will be built.
|
|
219
|
-
"""
|
|
220
|
-
return None
|
|
221
|
-
|
|
222
|
-
def run(self):
|
|
223
|
-
"""Run method for the task."""
|
|
224
|
-
with self.apm_processing_step("Building quality report"):
|
|
225
|
-
report = self.quality_build_report(polcal_label_list=self.polcal_label_list)
|
|
226
|
-
with self.apm_task_step(f"Submitting quality report: report section count = {len(report)}"):
|
|
227
|
-
self.metadata_store_add_quality_report(
|
|
228
|
-
dataset_id=self.constants.dataset_id, quality_report=report
|
|
229
|
-
)
|
|
@@ -5,6 +5,7 @@ from functools import cached_property
|
|
|
5
5
|
|
|
6
6
|
from dkist_processing_common._util.config import service_configuration
|
|
7
7
|
from dkist_processing_common._util.graphql import GraphQLClient
|
|
8
|
+
from dkist_processing_common.codecs.quality import QualityDataEncoder
|
|
8
9
|
from dkist_processing_common.models.graphql import DatasetCatalogReceiptAccountMutation
|
|
9
10
|
from dkist_processing_common.models.graphql import DatasetCatalogReceiptAccountResponse
|
|
10
11
|
from dkist_processing_common.models.graphql import InputDatasetPartResponse
|
|
@@ -21,7 +22,6 @@ from dkist_processing_common.models.graphql import RecipeRunResponse
|
|
|
21
22
|
from dkist_processing_common.models.graphql import RecipeRunStatusMutation
|
|
22
23
|
from dkist_processing_common.models.graphql import RecipeRunStatusQuery
|
|
23
24
|
from dkist_processing_common.models.graphql import RecipeRunStatusResponse
|
|
24
|
-
from dkist_processing_common.models.quality_json_encoders import QualityReportEncoder
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
logger = logging.getLogger(__name__)
|
|
@@ -78,10 +78,10 @@ class MetadataStoreMixin:
|
|
|
78
78
|
mutation_response_cls=RecipeRunProvenanceResponse,
|
|
79
79
|
)
|
|
80
80
|
|
|
81
|
-
def
|
|
82
|
-
"""Add the quality
|
|
83
|
-
|
|
84
|
-
params = QualityReportMutation(datasetId=dataset_id, qualityReport=
|
|
81
|
+
def metadata_store_add_quality_data(self, dataset_id: str, quality_data: list[dict]):
|
|
82
|
+
"""Add the quality data to the metadata-store."""
|
|
83
|
+
quality_data_json = json.dumps(quality_data, cls=QualityDataEncoder)
|
|
84
|
+
params = QualityReportMutation(datasetId=dataset_id, qualityReport=quality_data_json)
|
|
85
85
|
self.metadata_store_client.execute_gql_mutation(
|
|
86
86
|
mutation_base="createQualityReport",
|
|
87
87
|
mutation_parameters=params,
|
|
@@ -4,7 +4,7 @@ from typing import Iterable
|
|
|
4
4
|
import numpy as np
|
|
5
5
|
|
|
6
6
|
from dkist_processing_common.codecs.json import json_encoder
|
|
7
|
-
from dkist_processing_common.
|
|
7
|
+
from dkist_processing_common.codecs.quality import QualityValueEncoder
|
|
8
8
|
from dkist_processing_common.models.tags import Tag
|
|
9
9
|
from dkist_processing_common.tasks.mixin.quality._metrics import _PolcalQualityMixin
|
|
10
10
|
from dkist_processing_common.tasks.mixin.quality._metrics import _SimplePlotQualityMixin
|
|
@@ -17,8 +17,8 @@ class QualityMixin(
|
|
|
17
17
|
):
|
|
18
18
|
"""Mixin class supporting the generation of the quality reports."""
|
|
19
19
|
|
|
20
|
-
def
|
|
21
|
-
"""
|
|
20
|
+
def quality_assemble_data(self, polcal_label_list: list[str] | None = None) -> list[dict]:
|
|
21
|
+
"""Assemble the quality data by checking for the existence of each metric."""
|
|
22
22
|
report = []
|
|
23
23
|
report += self.quality_task_independent_metrics()
|
|
24
24
|
report += self.quality_task_dependent_metrics()
|
|
@@ -84,7 +84,9 @@ class QualityL0Metrics(WorkflowTaskBase, QualityMixin, ABC):
|
|
|
84
84
|
# We grab the task name
|
|
85
85
|
tags = self.tags(path)
|
|
86
86
|
task_type = [
|
|
87
|
-
t.replace(f"{StemName.task.value}_", "")
|
|
87
|
+
t.replace(f"{StemName.task.value}_", "")
|
|
88
|
+
for t in tags
|
|
89
|
+
if t.startswith("TASK")
|
|
88
90
|
][0]
|
|
89
91
|
|
|
90
92
|
if (
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import logging
|
|
3
3
|
from datetime import datetime
|
|
4
4
|
from importlib import resources
|
|
5
|
+
from itertools import chain
|
|
5
6
|
from pathlib import Path
|
|
6
7
|
from typing import Generator
|
|
7
8
|
from uuid import uuid4
|
|
@@ -10,13 +11,14 @@ from dkist_processing_common.codecs.asdf import asdf_encoder
|
|
|
10
11
|
from dkist_processing_common.codecs.fits import fits_access_decoder
|
|
11
12
|
from dkist_processing_common.codecs.json import json_encoder
|
|
12
13
|
from dkist_processing_common.codecs.path import path_decoder
|
|
14
|
+
from dkist_processing_common.codecs.quality import quality_data_decoder
|
|
13
15
|
from dkist_processing_common.models.fits_access import FitsAccessBase
|
|
14
16
|
from dkist_processing_common.models.tags import Tag
|
|
15
17
|
from dkist_processing_common.tasks.output_data_base import OutputDataBase
|
|
16
18
|
|
|
17
19
|
logger = logging.getLogger(__name__)
|
|
18
20
|
|
|
19
|
-
__all__ = ["CreateTrialDatasetInventory", "CreateTrialAsdf"]
|
|
21
|
+
__all__ = ["CreateTrialDatasetInventory", "CreateTrialAsdf", "CreateTrialQualityReport"]
|
|
20
22
|
|
|
21
23
|
|
|
22
24
|
# Capture condition of dkist-processing-common[inventory] install
|
|
@@ -39,6 +41,16 @@ try:
|
|
|
39
41
|
except ModuleNotFoundError:
|
|
40
42
|
pass
|
|
41
43
|
|
|
44
|
+
# Verify dkist-quality is installed
|
|
45
|
+
QUALITY_EXTRA_INSTALLED = False
|
|
46
|
+
try:
|
|
47
|
+
from dkist_quality.report import format_report
|
|
48
|
+
from dkist_quality.report import ReportFormattingException
|
|
49
|
+
|
|
50
|
+
QUALITY_EXTRA_INSTALLED = True
|
|
51
|
+
except ModuleNotFoundError:
|
|
52
|
+
pass
|
|
53
|
+
|
|
42
54
|
|
|
43
55
|
class CreateTrialDatasetInventory(OutputDataBase):
|
|
44
56
|
"""
|
|
@@ -143,3 +155,44 @@ class CreateTrialAsdf(OutputDataBase):
|
|
|
143
155
|
),
|
|
144
156
|
custom_schema=schema_path.as_posix(),
|
|
145
157
|
)
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
class CreateTrialQualityReport(OutputDataBase):
|
|
161
|
+
"""
|
|
162
|
+
Task for use in Trial workflows to generate the quality report for the dataset.
|
|
163
|
+
|
|
164
|
+
Warning: This task requires the dkist-quality package.
|
|
165
|
+
"""
|
|
166
|
+
|
|
167
|
+
def pre_run(self) -> None:
|
|
168
|
+
"""Require the dkist-quality package be installed."""
|
|
169
|
+
if not QUALITY_EXTRA_INSTALLED:
|
|
170
|
+
raise ModuleNotFoundError(
|
|
171
|
+
f"{self.__class__.__name__} Task requires the dkist-quality package "
|
|
172
|
+
f"(e.g. via a 'quality' pip_extra on dkist_processing_core.Workflow().add_node())"
|
|
173
|
+
f" but the required dependencies were not found."
|
|
174
|
+
)
|
|
175
|
+
|
|
176
|
+
def run(self) -> None:
|
|
177
|
+
"""Generate the quality report for the dataset."""
|
|
178
|
+
self.create_trial_quality_report()
|
|
179
|
+
|
|
180
|
+
def create_trial_quality_report(self) -> None:
|
|
181
|
+
"""Generate a trial quality report in pdf format and save to the file system for future upload."""
|
|
182
|
+
with self.apm_processing_step(f"Building the trial quality report"):
|
|
183
|
+
# each quality_data file is a list - this will combine the elements of multiple lists into a single list
|
|
184
|
+
quality_data = list(
|
|
185
|
+
chain.from_iterable(
|
|
186
|
+
self.read(tags=Tag.quality_data(), decoder=quality_data_decoder)
|
|
187
|
+
)
|
|
188
|
+
)
|
|
189
|
+
quality_report = format_report(
|
|
190
|
+
report_data=quality_data, dataset_id=self.constants.dataset_id
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
with self.apm_writing_step(f"Saving the trial quality report to the file system"):
|
|
194
|
+
self.write(
|
|
195
|
+
quality_report,
|
|
196
|
+
tags=[Tag.output(), Tag.quality_report()],
|
|
197
|
+
relative_path=f"{self.constants.dataset_id}_quality_report.pdf",
|
|
198
|
+
)
|
|
@@ -93,6 +93,20 @@ class TransferTrialDataBase(TransferDataBase, GlobusMixin, ABC):
|
|
|
93
93
|
"trial_transfer_output_asdf", True
|
|
94
94
|
)
|
|
95
95
|
|
|
96
|
+
@property
|
|
97
|
+
def output_quality_data_switch(self) -> bool:
|
|
98
|
+
"""Switch to turn on/off the transfer of the quality data to the trial location."""
|
|
99
|
+
return self.metadata_store_recipe_run_configuration().get(
|
|
100
|
+
"trial_transfer_output_quality_data", True
|
|
101
|
+
)
|
|
102
|
+
|
|
103
|
+
@property
|
|
104
|
+
def output_quality_report_switch(self) -> bool:
|
|
105
|
+
"""Switch to turn on/off the transfer of the quality report to the trial location."""
|
|
106
|
+
return self.metadata_store_recipe_run_configuration().get(
|
|
107
|
+
"trial_transfer_output_quality_report", True
|
|
108
|
+
)
|
|
109
|
+
|
|
96
110
|
@property
|
|
97
111
|
def specific_frame_tag_lists(self) -> list:
|
|
98
112
|
"""Return list of tag lists that define specific files we want to transfer to the trial location."""
|
|
@@ -161,6 +175,19 @@ class TransferTrialDataBase(TransferDataBase, GlobusMixin, ABC):
|
|
|
161
175
|
)
|
|
162
176
|
return transfer_items
|
|
163
177
|
|
|
178
|
+
def build_output_quality_data_transfer_list(self) -> list[GlobusTransferItem]:
|
|
179
|
+
"""Build a transfer list containing all files tagged with OUTPUT and QUALITY_DATA."""
|
|
180
|
+
# quality data is not tagged as OUTPUT
|
|
181
|
+
transfer_items = self.build_transfer_list_from_tag_lists(tag_lists=[Tag.quality_data()])
|
|
182
|
+
return transfer_items
|
|
183
|
+
|
|
184
|
+
def build_output_quality_report_transfer_list(self) -> list[GlobusTransferItem]:
|
|
185
|
+
"""Build a transfer list containing all files tagged with OUTPUT and QUALITY_REPORT."""
|
|
186
|
+
transfer_items = self.build_transfer_list_from_tag_lists(
|
|
187
|
+
tag_lists=[Tag.output(), Tag.quality_report()]
|
|
188
|
+
)
|
|
189
|
+
return transfer_items
|
|
190
|
+
|
|
164
191
|
@property
|
|
165
192
|
def intermediate_task_names(self) -> list[str]:
|
|
166
193
|
"""List specifying which TASK types to build when selecting INTERMEDIATE frames."""
|