cg 76.0.0__py3-none-any.whl → 83.14.0__py3-none-any.whl
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.
- cg/__init__.py +1 -1
- cg/apps/housekeeper/hk.py +18 -1
- cg/apps/tb/api.py +42 -5
- cg/cli/transfer.py +13 -2
- cg/cli/upload/mutacc.py +16 -3
- cg/cli/upload/scout.py +2 -2
- cg/cli/upload/utils.py +10 -1
- cg/cli/workflow/balsamic/base.py +86 -172
- cg/cli/workflow/balsamic/options.py +3 -48
- cg/cli/workflow/balsamic/umi.py +210 -15
- cg/cli/workflow/microsalt/base.py +4 -2
- cg/cli/workflow/mip_dna/base.py +1 -1
- cg/cli/workflow/nallo/base.py +73 -23
- cg/cli/workflow/nf_analysis.py +5 -207
- cg/cli/workflow/raredisease/base.py +41 -54
- cg/cli/workflow/rnafusion/base.py +38 -8
- cg/cli/workflow/taxprofiler/base.py +31 -18
- cg/cli/workflow/tomte/base.py +83 -10
- cg/constants/constants.py +25 -30
- cg/constants/devices.py +6 -1
- cg/constants/gene_panel.py +3 -1
- cg/constants/housekeeper_tags.py +28 -28
- cg/constants/lims.py +4 -0
- cg/constants/nf_analysis.py +0 -1
- cg/constants/observations.py +21 -5
- cg/constants/orderforms.py +3 -3
- cg/constants/pacbio.py +1 -0
- cg/constants/priority.py +1 -1
- cg/constants/report.py +1 -0
- cg/constants/scout.py +12 -9
- cg/constants/sequencing.py +2 -2
- cg/constants/tb.py +5 -5
- cg/exc.py +27 -5
- cg/meta/compress/compress.py +7 -2
- cg/meta/delivery_report/balsamic.py +3 -1
- cg/meta/delivery_report/delivery_report_api.py +4 -3
- cg/meta/delivery_report/nallo.py +11 -11
- cg/meta/delivery_report/raredisease.py +7 -3
- cg/meta/delivery_report/templates/macros/data_analysis/qc_metrics/balsamic_qc_metrics.html +1 -0
- cg/meta/delivery_report/templates/macros/ticket_system.html +1 -1
- cg/meta/observations/balsamic_observations_api.py +110 -14
- cg/meta/observations/mip_dna_observations_api.py +1 -1
- cg/meta/observations/nallo_observations_api.py +1 -1
- cg/meta/observations/observations_api.py +23 -32
- cg/meta/observations/raredisease_observations_api.py +1 -1
- cg/meta/tar/tar.py +5 -2
- cg/meta/transfer/lims.py +32 -3
- cg/meta/upload/balsamic/balsamic.py +1 -8
- cg/meta/upload/coverage.py +5 -5
- cg/meta/upload/raredisease/raredisease.py +3 -0
- cg/meta/upload/scout/hk_tags.py +1 -0
- cg/meta/upload/scout/nallo_config_builder.py +31 -7
- cg/meta/workflow/balsamic.py +70 -36
- cg/meta/workflow/fastq.py +8 -0
- cg/meta/workflow/microsalt/quality_controller/models.py +0 -2
- cg/meta/workflow/microsalt/quality_controller/quality_controller.py +8 -16
- cg/meta/workflow/microsalt/quality_controller/result_logger.py +3 -6
- cg/meta/workflow/microsalt/quality_controller/utils.py +2 -45
- cg/meta/workflow/nallo.py +21 -99
- cg/meta/workflow/nf_analysis.py +12 -263
- cg/meta/workflow/raredisease.py +3 -112
- cg/meta/workflow/rnafusion.py +2 -34
- cg/meta/workflow/taxprofiler.py +2 -38
- cg/meta/workflow/tomte.py +2 -42
- cg/models/balsamic/config.py +0 -24
- cg/models/balsamic/metrics.py +5 -3
- cg/models/cg_config.py +39 -16
- cg/models/deliverables/metric_deliverables.py +1 -1
- cg/models/delivery_report/metadata.py +2 -1
- cg/models/nallo/nallo.py +14 -64
- cg/models/nf_analysis.py +1 -41
- cg/models/raredisease/raredisease.py +1 -63
- cg/models/rnafusion/rnafusion.py +0 -26
- cg/models/scout/scout_load_config.py +5 -2
- cg/models/taxprofiler/taxprofiler.py +0 -42
- cg/models/tomte/tomte.py +0 -69
- cg/resources/nallo_bundle_filenames.yaml +292 -22
- cg/resources/raredisease_bundle_filenames.yaml +11 -1
- cg/resources/taxprofiler_bundle_filenames.yaml +20 -0
- cg/server/admin.py +106 -25
- cg/server/app.py +15 -4
- cg/server/endpoints/sequencing_run/dtos.py +21 -3
- cg/server/endpoints/sequencing_run/pacbio_sequencing_run.py +29 -10
- cg/server/endpoints/sequencing_run/pacbio_smrt_cell_metrics.py +20 -0
- cg/services/analysis_starter/{service.py → analysis_starter.py} +11 -9
- cg/services/analysis_starter/configurator/abstract_model.py +8 -0
- cg/services/analysis_starter/configurator/configurator.py +1 -1
- cg/services/analysis_starter/configurator/extensions/nallo.py +27 -0
- cg/services/analysis_starter/configurator/extensions/{abstract.py → pipeline_extension.py} +1 -1
- cg/services/analysis_starter/configurator/extensions/raredisease.py +3 -1
- cg/services/analysis_starter/configurator/extensions/tomte_extension.py +28 -0
- cg/services/analysis_starter/configurator/file_creators/balsamic_config.py +240 -0
- cg/services/analysis_starter/configurator/file_creators/gene_panel.py +10 -5
- cg/services/analysis_starter/configurator/file_creators/nextflow/params_file/abstract.py +2 -1
- cg/services/analysis_starter/configurator/file_creators/nextflow/params_file/models.py +40 -1
- cg/services/analysis_starter/configurator/file_creators/nextflow/params_file/nallo.py +37 -0
- cg/services/analysis_starter/configurator/file_creators/nextflow/params_file/raredisease.py +8 -5
- cg/services/analysis_starter/configurator/file_creators/nextflow/params_file/tomte_params_file_creator.py +64 -0
- cg/services/analysis_starter/configurator/file_creators/nextflow/sample_sheet/creator.py +1 -1
- cg/services/analysis_starter/configurator/file_creators/nextflow/sample_sheet/nallo_sample_sheet_creator.py +65 -0
- cg/services/analysis_starter/configurator/file_creators/nextflow/sample_sheet/protocol.py +12 -0
- cg/services/analysis_starter/configurator/file_creators/nextflow/sample_sheet/{raredisease.py → raredisease_sample_sheet_creator.py} +2 -2
- cg/services/analysis_starter/configurator/file_creators/nextflow/sample_sheet/{rnafusion.py → rnafusion_sample_sheet_creator.py} +2 -2
- cg/services/analysis_starter/configurator/file_creators/nextflow/sample_sheet/{taxprofiler.py → taxprofiler_sample_sheet_creator.py} +2 -2
- cg/services/analysis_starter/configurator/file_creators/nextflow/sample_sheet/tomte_sample_sheet_creator.py +36 -0
- cg/services/analysis_starter/configurator/implementations/balsamic.py +68 -0
- cg/services/analysis_starter/configurator/implementations/nextflow.py +22 -5
- cg/services/analysis_starter/configurator/models/balsamic.py +152 -0
- cg/services/analysis_starter/configurator/models/mip_dna.py +6 -8
- cg/services/analysis_starter/configurator/models/nextflow.py +9 -0
- cg/services/analysis_starter/constants.py +2 -0
- cg/services/analysis_starter/factories/configurator_factory.py +131 -51
- cg/services/analysis_starter/factories/starter_factory.py +36 -7
- cg/services/analysis_starter/input_fetcher/implementations/bam_fetcher.py +57 -0
- cg/services/analysis_starter/input_fetcher/implementations/fastq_fetcher.py +3 -3
- cg/services/analysis_starter/submitters/seqera_platform/{client.py → seqera_platform_client.py} +19 -3
- cg/services/analysis_starter/submitters/seqera_platform/seqera_platform_submitter.py +73 -0
- cg/services/analysis_starter/submitters/submitter.py +1 -1
- cg/services/analysis_starter/submitters/subprocess/submitter.py +2 -1
- cg/services/analysis_starter/tracker/implementations/balsamic.py +22 -0
- cg/services/analysis_starter/tracker/implementations/microsalt.py +4 -4
- cg/services/analysis_starter/tracker/implementations/mip_dna.py +4 -1
- cg/services/analysis_starter/tracker/implementations/{nextflow.py → nextflow_tracker.py} +6 -4
- cg/services/analysis_starter/tracker/tracker.py +19 -15
- cg/services/deliver_files/factory.py +1 -1
- cg/services/delivery_message/messages/__init__.py +24 -14
- cg/services/delivery_message/messages/{microsalt_mwr_message.py → microsalt_message.py} +1 -1
- cg/services/delivery_message/utils.py +4 -40
- cg/services/illumina/backup/backup_service.py +29 -7
- cg/services/orders/validation/constants.py +3 -0
- cg/services/orders/validation/index_sequences.py +558 -0
- cg/services/orders/validation/order_types/microsalt/models/sample.py +2 -3
- cg/services/run_devices/pacbio/data_storage_service/pacbio_store_service.py +39 -18
- cg/services/run_devices/pacbio/data_transfer_service/data_transfer_service.py +8 -2
- cg/services/run_devices/pacbio/data_transfer_service/dto.py +9 -3
- cg/services/run_devices/pacbio/data_transfer_service/utils.py +14 -7
- cg/services/run_devices/pacbio/metrics_parser/models.py +1 -0
- cg/services/run_devices/pacbio/sequencing_runs_service.py +35 -7
- cg/services/sequencing_qc_service/quality_checks/checks.py +18 -16
- cg/services/sequencing_qc_service/quality_checks/utils.py +82 -18
- cg/services/sequencing_qc_service/sequencing_qc_service.py +12 -10
- cg/store/crud/create.py +73 -42
- cg/store/crud/read.py +73 -7
- cg/store/crud/update.py +14 -3
- cg/store/models.py +98 -35
- cg/store/store.py +8 -1
- {cg-76.0.0.dist-info → cg-83.14.0.dist-info}/METADATA +1 -1
- {cg-76.0.0.dist-info → cg-83.14.0.dist-info}/RECORD +150 -138
- cg/services/analysis_starter/submitters/seqera_platform/submitter.py +0 -39
- cg/services/delivery_message/messages/microsalt_mwx_message.py +0 -18
- {cg-76.0.0.dist-info → cg-83.14.0.dist-info}/WHEEL +0 -0
- {cg-76.0.0.dist-info → cg-83.14.0.dist-info}/entry_points.txt +0 -0
|
@@ -5,28 +5,25 @@ from typing import cast
|
|
|
5
5
|
|
|
6
6
|
import rich_click as click
|
|
7
7
|
|
|
8
|
-
from cg.cli.utils import CLICK_CONTEXT_SETTINGS
|
|
8
|
+
from cg.cli.utils import CLICK_CONTEXT_SETTINGS
|
|
9
9
|
from cg.cli.workflow.commands import ARGUMENT_CASE_ID, resolve_compression
|
|
10
10
|
from cg.cli.workflow.nf_analysis import (
|
|
11
|
-
|
|
11
|
+
OPTION_RESUME,
|
|
12
|
+
OPTION_REVISION,
|
|
12
13
|
metrics_deliver,
|
|
13
14
|
report_deliver,
|
|
14
|
-
run,
|
|
15
|
-
start,
|
|
16
|
-
start_available,
|
|
17
15
|
store,
|
|
18
16
|
store_available,
|
|
19
17
|
store_housekeeper,
|
|
20
18
|
)
|
|
21
|
-
from cg.constants.cli_options import DRY_RUN
|
|
22
19
|
from cg.constants.constants import MetaApis, Workflow
|
|
23
20
|
from cg.meta.workflow.analysis import AnalysisAPI
|
|
24
21
|
from cg.meta.workflow.raredisease import RarediseaseAnalysisAPI
|
|
25
22
|
from cg.models.cg_config import CGConfig
|
|
23
|
+
from cg.services.analysis_starter.analysis_starter import AnalysisStarter
|
|
26
24
|
from cg.services.analysis_starter.configurator.implementations.nextflow import NextflowConfigurator
|
|
27
25
|
from cg.services.analysis_starter.factories.configurator_factory import ConfiguratorFactory
|
|
28
26
|
from cg.services.analysis_starter.factories.starter_factory import AnalysisStarterFactory
|
|
29
|
-
from cg.services.analysis_starter.service import AnalysisStarter
|
|
30
27
|
|
|
31
28
|
LOG = logging.getLogger(__name__)
|
|
32
29
|
|
|
@@ -41,11 +38,7 @@ def raredisease(context: click.Context) -> None:
|
|
|
41
38
|
|
|
42
39
|
raredisease.add_command(metrics_deliver)
|
|
43
40
|
raredisease.add_command(resolve_compression)
|
|
44
|
-
raredisease.add_command(config_case)
|
|
45
41
|
raredisease.add_command(report_deliver)
|
|
46
|
-
raredisease.add_command(run)
|
|
47
|
-
raredisease.add_command(start)
|
|
48
|
-
raredisease.add_command(start_available)
|
|
49
42
|
raredisease.add_command(store)
|
|
50
43
|
raredisease.add_command(store_available)
|
|
51
44
|
raredisease.add_command(store_housekeeper)
|
|
@@ -54,40 +47,68 @@ raredisease.add_command(store_housekeeper)
|
|
|
54
47
|
@raredisease.command()
|
|
55
48
|
@ARGUMENT_CASE_ID
|
|
56
49
|
@click.pass_obj
|
|
57
|
-
def
|
|
58
|
-
"""
|
|
50
|
+
def config_case(cg_config: CGConfig, case_id: str):
|
|
51
|
+
"""
|
|
52
|
+
Configure a raredisease case so that it is ready to be run.
|
|
53
|
+
|
|
54
|
+
\b
|
|
55
|
+
Creates the following files in the case run directory:
|
|
56
|
+
- CASE_ID_params_file.yaml
|
|
57
|
+
- CASE_ID_nextflow_config.json
|
|
58
|
+
- CASE_ID_samplesheet.csv
|
|
59
|
+
"""
|
|
59
60
|
factory = ConfiguratorFactory(cg_config)
|
|
60
61
|
configurator = cast(NextflowConfigurator, factory.get_configurator(Workflow.RAREDISEASE))
|
|
61
62
|
configurator.configure(case_id=case_id)
|
|
62
63
|
|
|
63
64
|
|
|
64
65
|
@raredisease.command()
|
|
66
|
+
@OPTION_REVISION
|
|
67
|
+
@OPTION_RESUME
|
|
65
68
|
@ARGUMENT_CASE_ID
|
|
66
69
|
@click.pass_obj
|
|
67
|
-
def
|
|
68
|
-
"""
|
|
70
|
+
def run(cg_config: CGConfig, case_id: str, resume: bool, revision: str | None):
|
|
71
|
+
"""
|
|
72
|
+
Run a preconfigured raredisease case.
|
|
73
|
+
|
|
74
|
+
\b
|
|
75
|
+
Assumes that the following files exist in the case run directory:
|
|
76
|
+
- CASE_ID_params_file.yaml
|
|
77
|
+
- CASE_ID_nextflow_config.json
|
|
78
|
+
- CASE_ID_samplesheet.csv
|
|
79
|
+
"""
|
|
69
80
|
factory = AnalysisStarterFactory(cg_config)
|
|
70
81
|
analysis_starter: AnalysisStarter = factory.get_analysis_starter_for_workflow(
|
|
71
82
|
Workflow.RAREDISEASE
|
|
72
83
|
)
|
|
73
|
-
analysis_starter.run(case_id=case_id)
|
|
84
|
+
analysis_starter.run(case_id=case_id, resume=resume, revision=revision)
|
|
74
85
|
|
|
75
86
|
|
|
76
87
|
@raredisease.command()
|
|
88
|
+
@OPTION_REVISION
|
|
77
89
|
@ARGUMENT_CASE_ID
|
|
78
90
|
@click.pass_obj
|
|
79
|
-
def
|
|
80
|
-
"""
|
|
91
|
+
def start(cg_config: CGConfig, case_id: str, revision: str | None):
|
|
92
|
+
"""
|
|
93
|
+
Start a raredisease case.
|
|
94
|
+
|
|
95
|
+
\b
|
|
96
|
+
Configures the case and writes the following files:
|
|
97
|
+
- CASE_ID_params_file.yaml
|
|
98
|
+
- CASE_ID_nextflow_config.json
|
|
99
|
+
- CASE_ID_samplesheet.csv
|
|
100
|
+
and submits the job to the Seqera Platform.
|
|
101
|
+
"""
|
|
81
102
|
factory = AnalysisStarterFactory(cg_config)
|
|
82
103
|
analysis_starter: AnalysisStarter = factory.get_analysis_starter_for_workflow(
|
|
83
104
|
Workflow.RAREDISEASE
|
|
84
105
|
)
|
|
85
|
-
analysis_starter.start(case_id=case_id)
|
|
106
|
+
analysis_starter.start(case_id=case_id, revision=revision)
|
|
86
107
|
|
|
87
108
|
|
|
88
109
|
@raredisease.command()
|
|
89
110
|
@click.pass_obj
|
|
90
|
-
def
|
|
111
|
+
def start_available(cg_config: CGConfig) -> None:
|
|
91
112
|
"""Starts all available raredisease cases."""
|
|
92
113
|
LOG.info("Starting raredisease workflow for all available cases.")
|
|
93
114
|
analysis_starter = AnalysisStarterFactory(cg_config).get_analysis_starter_for_workflow(
|
|
@@ -96,37 +117,3 @@ def dev_start_available(cg_config: CGConfig) -> None:
|
|
|
96
117
|
succeeded: bool = analysis_starter.start_available()
|
|
97
118
|
if not succeeded:
|
|
98
119
|
raise click.Abort
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
@raredisease.command("panel")
|
|
102
|
-
@DRY_RUN
|
|
103
|
-
@ARGUMENT_CASE_ID
|
|
104
|
-
@click.pass_obj
|
|
105
|
-
def panel(context: CGConfig, case_id: str, dry_run: bool) -> None:
|
|
106
|
-
"""Write aggregated gene panel file exported from Scout."""
|
|
107
|
-
|
|
108
|
-
analysis_api: RarediseaseAnalysisAPI = context.meta_apis["analysis_api"]
|
|
109
|
-
analysis_api.status_db.verify_case_exists(case_internal_id=case_id)
|
|
110
|
-
|
|
111
|
-
bed_lines: list[str] = analysis_api.get_gene_panel(case_id=case_id)
|
|
112
|
-
if dry_run:
|
|
113
|
-
echo_lines(lines=bed_lines)
|
|
114
|
-
return
|
|
115
|
-
analysis_api.write_panel(case_id=case_id, content=bed_lines)
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
@raredisease.command("managed-variants")
|
|
119
|
-
@DRY_RUN
|
|
120
|
-
@ARGUMENT_CASE_ID
|
|
121
|
-
@click.pass_obj
|
|
122
|
-
def managed_variants(context: CGConfig, case_id: str, dry_run: bool) -> None:
|
|
123
|
-
"""Write managed variants file exported from Scout."""
|
|
124
|
-
|
|
125
|
-
analysis_api: RarediseaseAnalysisAPI = context.meta_apis["analysis_api"]
|
|
126
|
-
analysis_api.status_db.verify_case_exists(case_internal_id=case_id)
|
|
127
|
-
|
|
128
|
-
vcf_lines: list[str] = analysis_api.get_managed_variants(case_id=case_id)
|
|
129
|
-
if dry_run:
|
|
130
|
-
echo_lines(lines=vcf_lines)
|
|
131
|
-
return
|
|
132
|
-
analysis_api.write_managed_variants(case_id=case_id, content=vcf_lines)
|
|
@@ -8,6 +8,8 @@ import rich_click as click
|
|
|
8
8
|
from cg.cli.utils import CLICK_CONTEXT_SETTINGS
|
|
9
9
|
from cg.cli.workflow.commands import ARGUMENT_CASE_ID, resolve_compression
|
|
10
10
|
from cg.cli.workflow.nf_analysis import (
|
|
11
|
+
OPTION_RESUME,
|
|
12
|
+
OPTION_REVISION,
|
|
11
13
|
metrics_deliver,
|
|
12
14
|
report_deliver,
|
|
13
15
|
store,
|
|
@@ -18,10 +20,10 @@ from cg.constants.constants import MetaApis, Workflow
|
|
|
18
20
|
from cg.meta.workflow.analysis import AnalysisAPI
|
|
19
21
|
from cg.meta.workflow.rnafusion import RnafusionAnalysisAPI
|
|
20
22
|
from cg.models.cg_config import CGConfig
|
|
23
|
+
from cg.services.analysis_starter.analysis_starter import AnalysisStarter
|
|
21
24
|
from cg.services.analysis_starter.configurator.implementations.nextflow import NextflowConfigurator
|
|
22
25
|
from cg.services.analysis_starter.factories.configurator_factory import ConfiguratorFactory
|
|
23
26
|
from cg.services.analysis_starter.factories.starter_factory import AnalysisStarterFactory
|
|
24
|
-
from cg.services.analysis_starter.service import AnalysisStarter
|
|
25
27
|
|
|
26
28
|
LOG = logging.getLogger(__name__)
|
|
27
29
|
|
|
@@ -46,35 +48,63 @@ rnafusion.add_command(store_available)
|
|
|
46
48
|
@ARGUMENT_CASE_ID
|
|
47
49
|
@click.pass_obj
|
|
48
50
|
def config_case(cg_config: CGConfig, case_id: str):
|
|
49
|
-
"""
|
|
51
|
+
"""
|
|
52
|
+
Configure an RNAFUSION case so that it is ready to be run.
|
|
53
|
+
|
|
54
|
+
\b
|
|
55
|
+
Creates the following files in the case run directory:
|
|
56
|
+
- CASE_ID_params_file.yaml
|
|
57
|
+
- CASE_ID_nextflow_config.json
|
|
58
|
+
- CASE_ID_samplesheet.csv
|
|
59
|
+
"""
|
|
50
60
|
factory = ConfiguratorFactory(cg_config)
|
|
51
61
|
configurator = cast(NextflowConfigurator, factory.get_configurator(Workflow.RNAFUSION))
|
|
52
62
|
configurator.configure(case_id=case_id)
|
|
53
63
|
|
|
54
64
|
|
|
55
65
|
@rnafusion.command()
|
|
66
|
+
@OPTION_REVISION
|
|
67
|
+
@OPTION_RESUME
|
|
56
68
|
@ARGUMENT_CASE_ID
|
|
57
69
|
@click.pass_obj
|
|
58
|
-
def run(cg_config: CGConfig, case_id: str):
|
|
59
|
-
"""
|
|
70
|
+
def run(cg_config: CGConfig, case_id: str, resume: bool, revision: str | None):
|
|
71
|
+
"""
|
|
72
|
+
Run a preconfigured RNAFUSION case.
|
|
73
|
+
|
|
74
|
+
\b
|
|
75
|
+
Assumes that the following files exist in the case run directory:
|
|
76
|
+
- CASE_ID_params_file.yaml
|
|
77
|
+
- CASE_ID_nextflow_config.json
|
|
78
|
+
- CASE_ID_samplesheet.csv
|
|
79
|
+
"""
|
|
60
80
|
factory = AnalysisStarterFactory(cg_config)
|
|
61
81
|
analysis_starter: AnalysisStarter = factory.get_analysis_starter_for_workflow(
|
|
62
82
|
Workflow.RNAFUSION
|
|
63
83
|
)
|
|
64
|
-
analysis_starter.run(case_id=case_id)
|
|
84
|
+
analysis_starter.run(case_id=case_id, resume=resume, revision=revision)
|
|
65
85
|
|
|
66
86
|
|
|
67
87
|
@rnafusion.command()
|
|
88
|
+
@OPTION_REVISION
|
|
68
89
|
@ARGUMENT_CASE_ID
|
|
69
90
|
@click.pass_obj
|
|
70
|
-
def start(cg_config: CGConfig, case_id: str):
|
|
71
|
-
"""
|
|
91
|
+
def start(cg_config: CGConfig, case_id: str, revision: str | None):
|
|
92
|
+
"""
|
|
93
|
+
Start an RNAFUSION case. Configures the case if needed.
|
|
94
|
+
|
|
95
|
+
\b
|
|
96
|
+
Configures the case and writes the following files:
|
|
97
|
+
- CASE_ID_params_file.yaml
|
|
98
|
+
- CASE_ID_nextflow_config.json
|
|
99
|
+
- CASE_ID_samplesheet.csv
|
|
100
|
+
and submits the job to the Seqera Platform.
|
|
101
|
+
"""
|
|
72
102
|
LOG.info(f"Starting RNAFUSION workflow for case {case_id}.")
|
|
73
103
|
factory = AnalysisStarterFactory(cg_config)
|
|
74
104
|
analysis_starter: AnalysisStarter = factory.get_analysis_starter_for_workflow(
|
|
75
105
|
Workflow.RNAFUSION
|
|
76
106
|
)
|
|
77
|
-
analysis_starter.start(case_id=case_id)
|
|
107
|
+
analysis_starter.start(case_id=case_id, revision=revision)
|
|
78
108
|
|
|
79
109
|
|
|
80
110
|
@rnafusion.command()
|
|
@@ -8,6 +8,8 @@ import rich_click as click
|
|
|
8
8
|
from cg.cli.utils import CLICK_CONTEXT_SETTINGS
|
|
9
9
|
from cg.cli.workflow.commands import ARGUMENT_CASE_ID, resolve_compression
|
|
10
10
|
from cg.cli.workflow.nf_analysis import (
|
|
11
|
+
OPTION_RESUME,
|
|
12
|
+
OPTION_REVISION,
|
|
11
13
|
metrics_deliver,
|
|
12
14
|
report_deliver,
|
|
13
15
|
store,
|
|
@@ -18,10 +20,10 @@ from cg.constants.constants import MetaApis, Workflow
|
|
|
18
20
|
from cg.meta.workflow.analysis import AnalysisAPI
|
|
19
21
|
from cg.meta.workflow.taxprofiler import TaxprofilerAnalysisAPI
|
|
20
22
|
from cg.models.cg_config import CGConfig
|
|
23
|
+
from cg.services.analysis_starter.analysis_starter import AnalysisStarter
|
|
21
24
|
from cg.services.analysis_starter.configurator.implementations.nextflow import NextflowConfigurator
|
|
22
25
|
from cg.services.analysis_starter.factories.configurator_factory import ConfiguratorFactory
|
|
23
26
|
from cg.services.analysis_starter.factories.starter_factory import AnalysisStarterFactory
|
|
24
|
-
from cg.services.analysis_starter.service import AnalysisStarter
|
|
25
27
|
|
|
26
28
|
LOG = logging.getLogger(__name__)
|
|
27
29
|
|
|
@@ -35,21 +37,25 @@ def taxprofiler(context: click.Context) -> None:
|
|
|
35
37
|
|
|
36
38
|
|
|
37
39
|
@taxprofiler.command()
|
|
40
|
+
@OPTION_REVISION
|
|
38
41
|
@ARGUMENT_CASE_ID
|
|
39
42
|
@click.pass_obj
|
|
40
|
-
def start(cg_config: CGConfig, case_id: str) -> None:
|
|
41
|
-
"""
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
43
|
+
def start(cg_config: CGConfig, case_id: str, revision: str | None) -> None:
|
|
44
|
+
"""
|
|
45
|
+
Start a Taxprofiler case.
|
|
46
|
+
|
|
47
|
+
\b
|
|
48
|
+
Configures the case and writes the following files:
|
|
49
|
+
- CASE_ID_params_file.yaml
|
|
50
|
+
- CASE_ID_nextflow_config.json
|
|
51
|
+
- CASE_ID_samplesheet.csv
|
|
46
52
|
and submits the job to the Seqera Platform.
|
|
47
53
|
"""
|
|
48
54
|
factory = AnalysisStarterFactory(cg_config)
|
|
49
55
|
analysis_starter: AnalysisStarter = factory.get_analysis_starter_for_workflow(
|
|
50
56
|
Workflow.TAXPROFILER
|
|
51
57
|
)
|
|
52
|
-
analysis_starter.start(case_id=case_id)
|
|
58
|
+
analysis_starter.start(case_id=case_id, revision=revision)
|
|
53
59
|
|
|
54
60
|
|
|
55
61
|
@taxprofiler.command()
|
|
@@ -67,30 +73,37 @@ def start_available(cg_config: CGConfig) -> None:
|
|
|
67
73
|
|
|
68
74
|
|
|
69
75
|
@taxprofiler.command()
|
|
76
|
+
@OPTION_REVISION
|
|
77
|
+
@OPTION_RESUME
|
|
70
78
|
@ARGUMENT_CASE_ID
|
|
71
79
|
@click.pass_obj
|
|
72
|
-
def run(cg_config: CGConfig, case_id: str) -> None:
|
|
73
|
-
"""
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
80
|
+
def run(cg_config: CGConfig, case_id: str, resume: bool, revision: str | None) -> None:
|
|
81
|
+
"""
|
|
82
|
+
Run a preconfigured Taxprofiler case.
|
|
83
|
+
|
|
84
|
+
\b
|
|
85
|
+
Assumes that the following files are in the case run directory:
|
|
86
|
+
- CASE_ID_params_file.yaml
|
|
87
|
+
- CASE_ID_nextflow_config.json
|
|
77
88
|
- CASE_ID_samplesheet.csv
|
|
78
89
|
"""
|
|
79
90
|
factory = AnalysisStarterFactory(cg_config)
|
|
80
91
|
analysis_starter: AnalysisStarter = factory.get_analysis_starter_for_workflow(
|
|
81
92
|
Workflow.TAXPROFILER
|
|
82
93
|
)
|
|
83
|
-
analysis_starter.run(case_id=case_id)
|
|
94
|
+
analysis_starter.run(case_id=case_id, resume=resume, revision=revision)
|
|
84
95
|
|
|
85
96
|
|
|
86
97
|
@taxprofiler.command()
|
|
87
98
|
@ARGUMENT_CASE_ID
|
|
88
99
|
@click.pass_obj
|
|
89
100
|
def config_case(cg_config: CGConfig, case_id: str) -> None:
|
|
90
|
-
"""Configure a Taxprofiler case so that it is ready to be run.
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
101
|
+
"""Configure a Taxprofiler case so that it is ready to be run.
|
|
102
|
+
|
|
103
|
+
\b
|
|
104
|
+
Creates the following files in the case run directory:
|
|
105
|
+
- CASE_ID_params_file.yaml
|
|
106
|
+
- CASE_ID_nextflow_config.json
|
|
94
107
|
- CASE_ID_samplesheet.csv
|
|
95
108
|
"""
|
|
96
109
|
factory = ConfiguratorFactory(cg_config)
|
cg/cli/workflow/tomte/base.py
CHANGED
|
@@ -1,25 +1,29 @@
|
|
|
1
1
|
"""CLI support to create config and/or start Tomte."""
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
|
+
from typing import cast
|
|
4
5
|
|
|
5
6
|
import rich_click as click
|
|
6
7
|
|
|
7
8
|
from cg.cli.utils import CLICK_CONTEXT_SETTINGS
|
|
8
|
-
from cg.cli.workflow.commands import resolve_compression
|
|
9
|
+
from cg.cli.workflow.commands import ARGUMENT_CASE_ID, resolve_compression
|
|
9
10
|
from cg.cli.workflow.nf_analysis import (
|
|
10
|
-
|
|
11
|
+
OPTION_RESUME,
|
|
12
|
+
OPTION_REVISION,
|
|
11
13
|
metrics_deliver,
|
|
12
14
|
report_deliver,
|
|
13
|
-
run,
|
|
14
|
-
start,
|
|
15
|
-
start_available,
|
|
16
15
|
store,
|
|
17
16
|
store_available,
|
|
18
17
|
store_housekeeper,
|
|
19
18
|
)
|
|
20
|
-
from cg.constants.constants import MetaApis
|
|
19
|
+
from cg.constants.constants import MetaApis, Workflow
|
|
21
20
|
from cg.meta.workflow.analysis import AnalysisAPI
|
|
22
21
|
from cg.meta.workflow.tomte import TomteAnalysisAPI
|
|
22
|
+
from cg.models.cg_config import CGConfig
|
|
23
|
+
from cg.services.analysis_starter.analysis_starter import AnalysisStarter
|
|
24
|
+
from cg.services.analysis_starter.configurator.implementations.nextflow import NextflowConfigurator
|
|
25
|
+
from cg.services.analysis_starter.factories.configurator_factory import ConfiguratorFactory
|
|
26
|
+
from cg.services.analysis_starter.factories.starter_factory import AnalysisStarterFactory
|
|
23
27
|
|
|
24
28
|
LOG = logging.getLogger(__name__)
|
|
25
29
|
|
|
@@ -33,12 +37,81 @@ def tomte(context: click.Context) -> None:
|
|
|
33
37
|
|
|
34
38
|
|
|
35
39
|
tomte.add_command(resolve_compression)
|
|
36
|
-
tomte.add_command(config_case)
|
|
37
|
-
tomte.add_command(run)
|
|
38
|
-
tomte.add_command(start)
|
|
39
|
-
tomte.add_command(start_available)
|
|
40
40
|
tomte.add_command(metrics_deliver)
|
|
41
41
|
tomte.add_command(report_deliver)
|
|
42
42
|
tomte.add_command(store_housekeeper)
|
|
43
43
|
tomte.add_command(store)
|
|
44
44
|
tomte.add_command(store_available)
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@tomte.command("config-case")
|
|
48
|
+
@ARGUMENT_CASE_ID
|
|
49
|
+
@click.pass_obj
|
|
50
|
+
def config_case(cg_config: CGConfig, case_id: str):
|
|
51
|
+
"""
|
|
52
|
+
Configure a Tomte case so that it is ready to be run.
|
|
53
|
+
|
|
54
|
+
\b
|
|
55
|
+
Creates the following files in the case run directory:
|
|
56
|
+
- CASE_ID_params_file.yaml
|
|
57
|
+
- CASE_ID_nextflow_config.json
|
|
58
|
+
- CASE_ID_samplesheet.csv
|
|
59
|
+
- gene_panels.bed
|
|
60
|
+
"""
|
|
61
|
+
factory = ConfiguratorFactory(cg_config)
|
|
62
|
+
configurator = cast(NextflowConfigurator, factory.get_configurator(Workflow.TOMTE))
|
|
63
|
+
configurator.configure(case_id=case_id)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
@tomte.command("run")
|
|
67
|
+
@OPTION_REVISION
|
|
68
|
+
@OPTION_RESUME
|
|
69
|
+
@ARGUMENT_CASE_ID
|
|
70
|
+
@click.pass_obj
|
|
71
|
+
def run(cg_config: CGConfig, case_id: str, resume: bool, revision: str | None) -> None:
|
|
72
|
+
"""
|
|
73
|
+
Run a preconfigured Tomte case.
|
|
74
|
+
|
|
75
|
+
\b
|
|
76
|
+
Assumes that the following files exist in the case run directory:
|
|
77
|
+
- CASE_ID_params_file.yaml
|
|
78
|
+
- CASE_ID_nextflow_config.json
|
|
79
|
+
- CASE_ID_samplesheet.csv
|
|
80
|
+
- gene_panels.bed
|
|
81
|
+
"""
|
|
82
|
+
factory = AnalysisStarterFactory(cg_config)
|
|
83
|
+
analysis_starter: AnalysisStarter = factory.get_analysis_starter_for_workflow(Workflow.TOMTE)
|
|
84
|
+
analysis_starter.run(case_id=case_id, resume=resume, revision=revision)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
@tomte.command("start")
|
|
88
|
+
@OPTION_REVISION
|
|
89
|
+
@ARGUMENT_CASE_ID
|
|
90
|
+
@click.pass_obj
|
|
91
|
+
def start(cg_config: CGConfig, case_id: str, revision: str | None):
|
|
92
|
+
"""
|
|
93
|
+
Start a Tomte case.
|
|
94
|
+
|
|
95
|
+
\b
|
|
96
|
+
Configures the case and writes the following files:
|
|
97
|
+
- CASE_ID_params_file.yaml
|
|
98
|
+
- CASE_ID_nextflow_config.json
|
|
99
|
+
- CASE_ID_samplesheet.csv
|
|
100
|
+
- gene_panels.bed
|
|
101
|
+
and submits the job to the Seqera Platform.
|
|
102
|
+
"""
|
|
103
|
+
factory = AnalysisStarterFactory(cg_config)
|
|
104
|
+
analysis_starter: AnalysisStarter = factory.get_analysis_starter_for_workflow(Workflow.TOMTE)
|
|
105
|
+
analysis_starter.start(case_id=case_id, revision=revision)
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
@tomte.command("start-available")
|
|
109
|
+
@click.pass_obj
|
|
110
|
+
def start_available(cg_config: CGConfig):
|
|
111
|
+
"""Starts all available Tomte cases."""
|
|
112
|
+
LOG.info("Starting Tomte workflow for all available cases.")
|
|
113
|
+
factory = AnalysisStarterFactory(cg_config)
|
|
114
|
+
analysis_starter: AnalysisStarter = factory.get_analysis_starter_for_workflow(Workflow.TOMTE)
|
|
115
|
+
succeeded: bool = analysis_starter.start_available()
|
|
116
|
+
if not succeeded:
|
|
117
|
+
raise click.Abort
|
cg/constants/constants.py
CHANGED
|
@@ -60,20 +60,23 @@ DEFAULT_CAPTURE_KIT = "twistexomecomprehensive_10.2_hg19_design.bed"
|
|
|
60
60
|
|
|
61
61
|
|
|
62
62
|
class CustomerId(StrEnum):
|
|
63
|
-
CG_INTERNAL_CUSTOMER
|
|
64
|
-
CUST001
|
|
65
|
-
CUST002
|
|
66
|
-
CUST003
|
|
67
|
-
CUST004
|
|
68
|
-
CUST032
|
|
69
|
-
CUST042
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
63
|
+
CG_INTERNAL_CUSTOMER = "cust000"
|
|
64
|
+
CUST001 = "cust001"
|
|
65
|
+
CUST002 = "cust002"
|
|
66
|
+
CUST003 = "cust003"
|
|
67
|
+
CUST004 = "cust004"
|
|
68
|
+
CUST032 = "cust032"
|
|
69
|
+
CUST042 = "cust042"
|
|
70
|
+
CUST087 = "cust087"
|
|
71
|
+
CUST110 = "cust110"
|
|
72
|
+
CUST127 = "cust127"
|
|
73
|
+
CUST132 = "cust132"
|
|
74
|
+
CUST143 = "cust143"
|
|
75
|
+
CUST147 = "cust147"
|
|
76
|
+
CUST175 = "cust175"
|
|
77
|
+
CUST185 = "cust185"
|
|
78
|
+
CUST201 = "cust201"
|
|
79
|
+
CUST999 = "cust999"
|
|
77
80
|
|
|
78
81
|
|
|
79
82
|
class SequencingRunDataAvailability(StrEnum):
|
|
@@ -97,9 +100,9 @@ class CancerAnalysisType(StrEnum):
|
|
|
97
100
|
|
|
98
101
|
|
|
99
102
|
class SexOptions(StrEnum):
|
|
100
|
-
MALE
|
|
101
|
-
FEMALE
|
|
102
|
-
UNKNOWN
|
|
103
|
+
MALE = "male"
|
|
104
|
+
FEMALE = "female"
|
|
105
|
+
UNKNOWN = "unknown"
|
|
103
106
|
|
|
104
107
|
|
|
105
108
|
SARS_COV_REGEX = "^[0-9]{2}CS[0-9]{6}$"
|
|
@@ -153,12 +156,12 @@ class FileFormat(StrEnum):
|
|
|
153
156
|
|
|
154
157
|
|
|
155
158
|
class GenomeVersion(StrEnum):
|
|
156
|
-
GRCh37
|
|
157
|
-
GRCh38
|
|
158
|
-
T2T_CHM13
|
|
159
|
+
GRCh37 = "GRCh37"
|
|
160
|
+
GRCh38 = "GRCh38"
|
|
161
|
+
T2T_CHM13 = "T2T-CHM13v2.0"
|
|
159
162
|
CANFAM3 = auto()
|
|
160
|
-
HG19
|
|
161
|
-
HG38
|
|
163
|
+
HG19 = "hg19"
|
|
164
|
+
HG38 = "hg38"
|
|
162
165
|
|
|
163
166
|
|
|
164
167
|
class SampleType(StrEnum):
|
|
@@ -235,7 +238,6 @@ class APIMethods(StrEnum):
|
|
|
235
238
|
|
|
236
239
|
class MicrosaltQC:
|
|
237
240
|
AVERAGE_COVERAGE_THRESHOLD: int = 10
|
|
238
|
-
MWX_THRESHOLD_SAMPLES_PASSING: float = 0.9
|
|
239
241
|
COVERAGE_10X_THRESHOLD: float = 0.75
|
|
240
242
|
DUPLICATION_RATE_THRESHOLD: float = 0.8
|
|
241
243
|
INSERT_SIZE_THRESHOLD: int = 100
|
|
@@ -245,13 +247,6 @@ class MicrosaltQC:
|
|
|
245
247
|
TARGET_READS_FAIL_THRESHOLD: float = 0.7
|
|
246
248
|
|
|
247
249
|
|
|
248
|
-
class MicrosaltAppTags(StrEnum):
|
|
249
|
-
MWRNXTR003: str = "MWRNXTR003"
|
|
250
|
-
MWXNXTR003: str = "MWXNXTR003"
|
|
251
|
-
VWGNXTR001: str = "VWGNXTR001"
|
|
252
|
-
PREP_CATEGORY: str = "mic"
|
|
253
|
-
|
|
254
|
-
|
|
255
250
|
class MutantQC:
|
|
256
251
|
EXTERNAL_NEGATIVE_CONTROL_READS_THRESHOLD: int = 100000
|
|
257
252
|
INTERNAL_NEGATIVE_CONTROL_READS_THRESHOLD: int = 2000
|
cg/constants/devices.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"""Enums for run_devices."""
|
|
2
2
|
|
|
3
|
-
from enum import Enum, auto
|
|
3
|
+
from enum import Enum, StrEnum, auto
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
class DeviceType(Enum):
|
|
@@ -8,3 +8,8 @@ class DeviceType(Enum):
|
|
|
8
8
|
BIONANO = auto()
|
|
9
9
|
OXFORD_NANOPORE = auto()
|
|
10
10
|
PACBIO = auto()
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class RevioNames(StrEnum):
|
|
14
|
+
BETTY = "Betty"
|
|
15
|
+
WILMA = "Wilma"
|
cg/constants/gene_panel.py
CHANGED
|
@@ -20,6 +20,7 @@ class GenePanelMasterList(StrEnum):
|
|
|
20
20
|
CH = "CH"
|
|
21
21
|
CHILDHYPOTONIA = "CHILDHYPOTONIA"
|
|
22
22
|
CTD = "CTD"
|
|
23
|
+
COMPD = "COMPD"
|
|
23
24
|
DIAB = "DIAB"
|
|
24
25
|
ENDO = "ENDO"
|
|
25
26
|
EP = "EP"
|
|
@@ -35,6 +36,7 @@ class GenePanelMasterList(StrEnum):
|
|
|
35
36
|
MTDNA = "mtDNA"
|
|
36
37
|
NBS_M = "NBS-M"
|
|
37
38
|
NEURODEG = "NEURODEG"
|
|
39
|
+
NOONAN = "NOONAN"
|
|
38
40
|
NMD = "NMD"
|
|
39
41
|
OMIM_AUTO = "OMIM-AUTO"
|
|
40
42
|
OPTIC = "OPTIC"
|
|
@@ -47,7 +49,7 @@ class GenePanelMasterList(StrEnum):
|
|
|
47
49
|
SOVM = "SOVM"
|
|
48
50
|
STROKE = "STROKE"
|
|
49
51
|
AID = "AID"
|
|
50
|
-
|
|
52
|
+
IHC = "IHC"
|
|
51
53
|
VEO_IBD = "VEO-IBD"
|
|
52
54
|
KIDNEY = "Kidney"
|
|
53
55
|
CAKUT = "CAKUT"
|
cg/constants/housekeeper_tags.py
CHANGED
|
@@ -57,34 +57,34 @@ class HermesFileTag(StrEnum):
|
|
|
57
57
|
class AnalysisTag(StrEnum):
|
|
58
58
|
"""Tags for analysis files."""
|
|
59
59
|
|
|
60
|
-
ARRIBA
|
|
61
|
-
ARRIBA_VISUALIZATION
|
|
62
|
-
BED
|
|
63
|
-
BIGWIG
|
|
64
|
-
CLINICAL
|
|
65
|
-
COVERAGE
|
|
66
|
-
FRASER
|
|
67
|
-
FUSION
|
|
68
|
-
FUSIONCATCHER
|
|
69
|
-
FUSIONCATCHER_SUMMARY
|
|
70
|
-
FUSIONINSPECTOR
|
|
71
|
-
FUSIONINSPECTOR_HTML
|
|
72
|
-
FUSIONREPORT
|
|
73
|
-
GENE_COUNTS
|
|
74
|
-
JUNCTION
|
|
75
|
-
MULTIQC_HTML
|
|
76
|
-
OUTRIDER
|
|
77
|
-
REPEATS
|
|
78
|
-
RESEARCH
|
|
79
|
-
RNA
|
|
80
|
-
SMN_CALLING
|
|
81
|
-
STARFUSION
|
|
82
|
-
VCF_FUSION
|
|
83
|
-
VCF_SNV
|
|
84
|
-
VCF_SNV_CLINICAL
|
|
85
|
-
VCF_STR
|
|
86
|
-
VCF_SV_CLINICAL
|
|
87
|
-
VCF_SV
|
|
60
|
+
ARRIBA = "arriba"
|
|
61
|
+
ARRIBA_VISUALIZATION = "arriba-visualisation"
|
|
62
|
+
BED = "bed"
|
|
63
|
+
BIGWIG = "bigwig"
|
|
64
|
+
CLINICAL = "clinical"
|
|
65
|
+
COVERAGE = "coverage"
|
|
66
|
+
FRASER = "fraser"
|
|
67
|
+
FUSION = "fusion"
|
|
68
|
+
FUSIONCATCHER = "fusioncatcher"
|
|
69
|
+
FUSIONCATCHER_SUMMARY = "fusioncatcher-summary"
|
|
70
|
+
FUSIONINSPECTOR = "fusioninspector"
|
|
71
|
+
FUSIONINSPECTOR_HTML = "fusioninspector-html"
|
|
72
|
+
FUSIONREPORT = "fusionreport"
|
|
73
|
+
GENE_COUNTS = "gene-counts"
|
|
74
|
+
JUNCTION = "junction"
|
|
75
|
+
MULTIQC_HTML = "multiqc-html"
|
|
76
|
+
OUTRIDER = "outrider"
|
|
77
|
+
REPEATS = "repeats"
|
|
78
|
+
RESEARCH = "research"
|
|
79
|
+
RNA = "rna"
|
|
80
|
+
SMN_CALLING = "smn-calling"
|
|
81
|
+
STARFUSION = "star-fusion"
|
|
82
|
+
VCF_FUSION = "vcf-fusion"
|
|
83
|
+
VCF_SNV = "vcf-snv"
|
|
84
|
+
VCF_SNV_CLINICAL = "vcf-snv-clinical"
|
|
85
|
+
VCF_STR = "vcf-str"
|
|
86
|
+
VCF_SV_CLINICAL = "vcf-sv-clinical"
|
|
87
|
+
VCF_SV = "vcf-sv"
|
|
88
88
|
|
|
89
89
|
|
|
90
90
|
class HkMipAnalysisTag:
|
cg/constants/lims.py
CHANGED
|
@@ -145,6 +145,10 @@ MASTER_STEPS_UDFS = {
|
|
|
145
145
|
"atlas_document": "Sequencing Method",
|
|
146
146
|
"atlas_version": "Atlas Version",
|
|
147
147
|
},
|
|
148
|
+
"Set Up Sequencing Run (Revio) v2": {
|
|
149
|
+
"atlas_document": "Sequencing Method",
|
|
150
|
+
"atlas_version": "Atlas Version",
|
|
151
|
+
},
|
|
148
152
|
},
|
|
149
153
|
"delivery_method_step": {
|
|
150
154
|
"CG002 - Delivery": {
|