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
cg/cli/workflow/balsamic/umi.py
CHANGED
|
@@ -1,25 +1,65 @@
|
|
|
1
1
|
"""CLI support to create config and/or start BALSAMIC """
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
|
+
import traceback
|
|
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.balsamic.base import
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
store_housekeeper,
|
|
17
|
-
)
|
|
18
|
-
from cg.cli.workflow.commands import link, resolve_compression
|
|
9
|
+
from cg.cli.workflow.balsamic.base import report_deliver, store, store_available, store_housekeeper
|
|
10
|
+
from cg.cli.workflow.balsamic.options import OPTION_PANEL_BED, OPTION_WORKFLOW_PROFILE
|
|
11
|
+
from cg.cli.workflow.commands import ARGUMENT_CASE_ID, link, resolve_compression
|
|
12
|
+
from cg.constants import EXIT_FAIL, EXIT_SUCCESS, Sex
|
|
13
|
+
from cg.constants.cli_options import DRY_RUN, LIMIT
|
|
14
|
+
from cg.constants.constants import GenomeVersion
|
|
15
|
+
from cg.constants.priority import SlurmQos
|
|
16
|
+
from cg.exc import AnalysisNotReadyError, CgError
|
|
19
17
|
from cg.meta.workflow.balsamic_umi import BalsamicUmiAnalysisAPI
|
|
18
|
+
from cg.models.cg_config import CGConfig
|
|
19
|
+
from cg.store.models import Case
|
|
20
20
|
|
|
21
21
|
LOG = logging.getLogger(__name__)
|
|
22
22
|
|
|
23
|
+
OPTION_GENDER = click.option(
|
|
24
|
+
"--gender",
|
|
25
|
+
type=click.Choice([Sex.FEMALE, Sex.MALE]),
|
|
26
|
+
required=False,
|
|
27
|
+
help="Case associated gender. Set this option to override the one selected by the customer in StatusDB.",
|
|
28
|
+
)
|
|
29
|
+
OPTION_GENOME_VERSION = click.option(
|
|
30
|
+
"--genome-version",
|
|
31
|
+
show_default=True,
|
|
32
|
+
default=GenomeVersion.HG19,
|
|
33
|
+
type=click.Choice([GenomeVersion.HG19, GenomeVersion.HG38, GenomeVersion.CANFAM3]),
|
|
34
|
+
help="Type and build version of the reference genome. Set this option to override the default.",
|
|
35
|
+
)
|
|
36
|
+
OPTION_QOS = click.option(
|
|
37
|
+
"-qos",
|
|
38
|
+
"--slurm-quality-of-service",
|
|
39
|
+
type=click.Choice([SlurmQos.LOW, SlurmQos.NORMAL, SlurmQos.HIGH, SlurmQos.EXPRESS]),
|
|
40
|
+
help="Job priority in SLURM. Setting this option will override the StatusDB case priority.",
|
|
41
|
+
)
|
|
42
|
+
OPTION_PON_CNN = click.option(
|
|
43
|
+
"--pon-cnn",
|
|
44
|
+
type=click.Path(exists=True),
|
|
45
|
+
required=False,
|
|
46
|
+
help="Panel of normal reference (.cnn) for CNVkit",
|
|
47
|
+
)
|
|
48
|
+
OPTION_OBSERVATIONS = click.option(
|
|
49
|
+
"--observations",
|
|
50
|
+
type=click.Path(exists=True),
|
|
51
|
+
multiple=True,
|
|
52
|
+
required=False,
|
|
53
|
+
help="VCF paths of clinical and/or cancer SNVs and SVs observations (WHOLE_GENOME_SEQUENCING analysis only). Set this option to "
|
|
54
|
+
"override the latest Loqusdb dump files.",
|
|
55
|
+
)
|
|
56
|
+
OPTION_CACHE_VERSION = click.option(
|
|
57
|
+
"--cache-version",
|
|
58
|
+
type=click.STRING,
|
|
59
|
+
required=False,
|
|
60
|
+
help="Cache version to be used for init or analysis. Use 'develop' or 'X.X.X'.",
|
|
61
|
+
)
|
|
62
|
+
|
|
23
63
|
|
|
24
64
|
@click.group(
|
|
25
65
|
"balsamic-umi",
|
|
@@ -36,13 +76,168 @@ def balsamic_umi(context: click.Context):
|
|
|
36
76
|
context.obj.meta_apis["analysis_api"] = BalsamicUmiAnalysisAPI(config=config)
|
|
37
77
|
|
|
38
78
|
|
|
79
|
+
@balsamic_umi.command("config-case")
|
|
80
|
+
@ARGUMENT_CASE_ID
|
|
81
|
+
@OPTION_GENDER
|
|
82
|
+
@OPTION_GENOME_VERSION
|
|
83
|
+
@OPTION_PANEL_BED
|
|
84
|
+
@OPTION_PON_CNN
|
|
85
|
+
@OPTION_OBSERVATIONS
|
|
86
|
+
@OPTION_CACHE_VERSION
|
|
87
|
+
@DRY_RUN
|
|
88
|
+
@click.pass_obj
|
|
89
|
+
def config_case(
|
|
90
|
+
context: CGConfig,
|
|
91
|
+
case_id: str,
|
|
92
|
+
gender: str,
|
|
93
|
+
genome_version: str,
|
|
94
|
+
panel_bed: str,
|
|
95
|
+
pon_cnn: click.Path,
|
|
96
|
+
observations: list[click.Path],
|
|
97
|
+
cache_version: str,
|
|
98
|
+
dry_run: bool,
|
|
99
|
+
):
|
|
100
|
+
"""Create config file for BALSAMIC UMI analysis for a given CASE_ID."""
|
|
101
|
+
|
|
102
|
+
analysis_api: BalsamicUmiAnalysisAPI = context.meta_apis["analysis_api"]
|
|
103
|
+
try:
|
|
104
|
+
LOG.info(f"Creating config file for {case_id}.")
|
|
105
|
+
analysis_api.status_db.verify_case_exists(case_internal_id=case_id)
|
|
106
|
+
analysis_api.config_case(
|
|
107
|
+
case_id=case_id,
|
|
108
|
+
gender=gender,
|
|
109
|
+
genome_version=genome_version,
|
|
110
|
+
panel_bed=panel_bed,
|
|
111
|
+
pon_cnn=pon_cnn,
|
|
112
|
+
observations=observations,
|
|
113
|
+
cache_version=cache_version,
|
|
114
|
+
dry_run=dry_run,
|
|
115
|
+
)
|
|
116
|
+
except CgError as error:
|
|
117
|
+
error_info = f"Error: {type(error).__name__}: {str(error)}\n{traceback.format_exc()}"
|
|
118
|
+
LOG.error(f"Could not create config: {error_info}")
|
|
119
|
+
raise click.Abort()
|
|
120
|
+
except Exception as error:
|
|
121
|
+
error_info = f"Error: {type(error).__name__}: {str(error)}\n{traceback.format_exc()}"
|
|
122
|
+
LOG.error(f"Could not create config: {error_info}")
|
|
123
|
+
raise click.Abort()
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
@balsamic_umi.command("run")
|
|
127
|
+
@ARGUMENT_CASE_ID
|
|
128
|
+
@OPTION_WORKFLOW_PROFILE
|
|
129
|
+
@DRY_RUN
|
|
130
|
+
@OPTION_QOS
|
|
131
|
+
@click.pass_obj
|
|
132
|
+
def run(
|
|
133
|
+
context: CGConfig,
|
|
134
|
+
case_id: str,
|
|
135
|
+
workflow_profile: click.Path,
|
|
136
|
+
slurm_quality_of_service: str,
|
|
137
|
+
dry_run: bool,
|
|
138
|
+
):
|
|
139
|
+
"""Run Balsamic UMI analysis for given CASE ID"""
|
|
140
|
+
analysis_api: BalsamicUmiAnalysisAPI = context.meta_apis["analysis_api"]
|
|
141
|
+
try:
|
|
142
|
+
analysis_api.status_db.verify_case_exists(case_internal_id=case_id)
|
|
143
|
+
analysis_api.verify_case_config_file_exists(case_id=case_id, dry_run=dry_run)
|
|
144
|
+
analysis_api.check_analysis_ongoing(case_id)
|
|
145
|
+
analysis_api.run_analysis(
|
|
146
|
+
case_id=case_id,
|
|
147
|
+
workflow_profile=workflow_profile,
|
|
148
|
+
slurm_quality_of_service=slurm_quality_of_service,
|
|
149
|
+
dry_run=dry_run,
|
|
150
|
+
)
|
|
151
|
+
if dry_run:
|
|
152
|
+
return
|
|
153
|
+
analysis_api.on_analysis_started(case_id)
|
|
154
|
+
except Exception as error:
|
|
155
|
+
error_info = f"Error: {type(error).__name__}: {str(error)}\n{traceback.format_exc()}"
|
|
156
|
+
LOG.error(f"Could not run analysis: {error_info}")
|
|
157
|
+
raise click.Abort()
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
@balsamic_umi.command("start")
|
|
161
|
+
@ARGUMENT_CASE_ID
|
|
162
|
+
@OPTION_GENDER
|
|
163
|
+
@OPTION_GENOME_VERSION
|
|
164
|
+
@OPTION_QOS
|
|
165
|
+
@DRY_RUN
|
|
166
|
+
@OPTION_PANEL_BED
|
|
167
|
+
@OPTION_PON_CNN
|
|
168
|
+
@OPTION_CACHE_VERSION
|
|
169
|
+
@OPTION_OBSERVATIONS
|
|
170
|
+
@OPTION_WORKFLOW_PROFILE
|
|
171
|
+
@click.pass_context
|
|
172
|
+
def start(
|
|
173
|
+
context: click.Context,
|
|
174
|
+
case_id: str,
|
|
175
|
+
gender: str,
|
|
176
|
+
genome_version: str,
|
|
177
|
+
cache_version: str,
|
|
178
|
+
panel_bed: str,
|
|
179
|
+
pon_cnn: str,
|
|
180
|
+
observations: list[click.Path],
|
|
181
|
+
slurm_quality_of_service: str,
|
|
182
|
+
workflow_profile: click.Path,
|
|
183
|
+
dry_run: bool,
|
|
184
|
+
):
|
|
185
|
+
"""Start full workflow for case ID."""
|
|
186
|
+
analysis_api: BalsamicUmiAnalysisAPI = context.obj.meta_apis["analysis_api"]
|
|
187
|
+
analysis_api.prepare_fastq_files(case_id=case_id, dry_run=dry_run)
|
|
188
|
+
LOG.info(f"Starting analysis for {case_id}")
|
|
189
|
+
context.invoke(link, case_id=case_id, dry_run=dry_run)
|
|
190
|
+
context.invoke(
|
|
191
|
+
config_case,
|
|
192
|
+
case_id=case_id,
|
|
193
|
+
gender=gender,
|
|
194
|
+
genome_version=genome_version,
|
|
195
|
+
cache_version=cache_version,
|
|
196
|
+
panel_bed=panel_bed,
|
|
197
|
+
pon_cnn=pon_cnn,
|
|
198
|
+
observations=observations,
|
|
199
|
+
dry_run=dry_run,
|
|
200
|
+
)
|
|
201
|
+
context.invoke(
|
|
202
|
+
run,
|
|
203
|
+
case_id=case_id,
|
|
204
|
+
workflow_profile=workflow_profile,
|
|
205
|
+
slurm_quality_of_service=slurm_quality_of_service,
|
|
206
|
+
dry_run=dry_run,
|
|
207
|
+
)
|
|
208
|
+
|
|
209
|
+
|
|
210
|
+
@balsamic_umi.command("start-available")
|
|
211
|
+
@DRY_RUN
|
|
212
|
+
@LIMIT
|
|
213
|
+
@click.pass_context
|
|
214
|
+
def start_available(context: click.Context, dry_run: bool = False, limit: int | None = None):
|
|
215
|
+
"""Start full workflow for all cases ready for analysis"""
|
|
216
|
+
|
|
217
|
+
analysis_api: BalsamicUmiAnalysisAPI = context.obj.meta_apis["analysis_api"]
|
|
218
|
+
|
|
219
|
+
cases: list[Case] = analysis_api.get_cases_to_analyze(limit=limit)
|
|
220
|
+
LOG.info(f"Starting {len(cases)} available Balsamic UMI cases")
|
|
221
|
+
|
|
222
|
+
exit_code: int = EXIT_SUCCESS
|
|
223
|
+
for case in cases:
|
|
224
|
+
try:
|
|
225
|
+
context.invoke(start, case_id=case.internal_id, dry_run=dry_run)
|
|
226
|
+
except AnalysisNotReadyError as error:
|
|
227
|
+
LOG.error(error)
|
|
228
|
+
except CgError as error:
|
|
229
|
+
LOG.error(error)
|
|
230
|
+
exit_code = EXIT_FAIL
|
|
231
|
+
except Exception as error:
|
|
232
|
+
LOG.error(f"Unspecified error occurred: {error}")
|
|
233
|
+
exit_code = EXIT_FAIL
|
|
234
|
+
if exit_code:
|
|
235
|
+
raise click.Abort
|
|
236
|
+
|
|
237
|
+
|
|
39
238
|
balsamic_umi.add_command(resolve_compression)
|
|
40
239
|
balsamic_umi.add_command(link)
|
|
41
|
-
balsamic_umi.add_command(config_case)
|
|
42
|
-
balsamic_umi.add_command(run)
|
|
43
240
|
balsamic_umi.add_command(report_deliver)
|
|
44
241
|
balsamic_umi.add_command(store_housekeeper)
|
|
45
|
-
balsamic_umi.add_command(start)
|
|
46
|
-
balsamic_umi.add_command(start_available)
|
|
47
242
|
balsamic_umi.add_command(store)
|
|
48
243
|
balsamic_umi.add_command(store_available)
|
|
@@ -12,12 +12,12 @@ from cg.constants.constants import Workflow
|
|
|
12
12
|
from cg.meta.workflow.analysis import AnalysisAPI
|
|
13
13
|
from cg.meta.workflow.microsalt import MicrosaltAnalysisAPI
|
|
14
14
|
from cg.models.cg_config import CGConfig
|
|
15
|
+
from cg.services.analysis_starter.analysis_starter import AnalysisStarter
|
|
15
16
|
from cg.services.analysis_starter.configurator.implementations.microsalt import (
|
|
16
17
|
MicrosaltConfigurator,
|
|
17
18
|
)
|
|
18
19
|
from cg.services.analysis_starter.factories.configurator_factory import ConfiguratorFactory
|
|
19
20
|
from cg.services.analysis_starter.factories.starter_factory import AnalysisStarterFactory
|
|
20
|
-
from cg.services.analysis_starter.service import AnalysisStarter
|
|
21
21
|
|
|
22
22
|
LOG = logging.getLogger(__name__)
|
|
23
23
|
|
|
@@ -41,7 +41,9 @@ microsalt.add_command(resolve_compression)
|
|
|
41
41
|
@ARGUMENT_CASE_ID
|
|
42
42
|
@click.pass_obj
|
|
43
43
|
def config_case(cg_config: CGConfig, case_id: str) -> None:
|
|
44
|
-
"""
|
|
44
|
+
"""
|
|
45
|
+
Configure a microSALT case so that it is ready to be run.
|
|
46
|
+
"""
|
|
45
47
|
factory = ConfiguratorFactory(cg_config)
|
|
46
48
|
configurator = cast(MicrosaltConfigurator, factory.get_configurator(Workflow.MICROSALT))
|
|
47
49
|
configurator.configure(case_id=case_id)
|
cg/cli/workflow/mip_dna/base.py
CHANGED
|
@@ -24,10 +24,10 @@ from cg.constants import Workflow
|
|
|
24
24
|
from cg.meta.workflow.analysis import AnalysisAPI
|
|
25
25
|
from cg.meta.workflow.mip_dna import MipDNAAnalysisAPI
|
|
26
26
|
from cg.models.cg_config import CGConfig
|
|
27
|
+
from cg.services.analysis_starter.analysis_starter import AnalysisStarter
|
|
27
28
|
from cg.services.analysis_starter.configurator.implementations.mip_dna import MIPDNAConfigurator
|
|
28
29
|
from cg.services.analysis_starter.factories.configurator_factory import ConfiguratorFactory
|
|
29
30
|
from cg.services.analysis_starter.factories.starter_factory import AnalysisStarterFactory
|
|
30
|
-
from cg.services.analysis_starter.service import AnalysisStarter
|
|
31
31
|
|
|
32
32
|
LOG = logging.getLogger(__name__)
|
|
33
33
|
|
cg/cli/workflow/nallo/base.py
CHANGED
|
@@ -1,28 +1,29 @@
|
|
|
1
1
|
"""CLI support to create config and/or start NALLO."""
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
|
+
from typing import cast
|
|
4
5
|
|
|
5
6
|
import rich_click as click
|
|
6
7
|
|
|
7
|
-
from cg.cli.utils import CLICK_CONTEXT_SETTINGS
|
|
8
|
+
from cg.cli.utils import CLICK_CONTEXT_SETTINGS
|
|
8
9
|
from cg.cli.workflow.commands import ARGUMENT_CASE_ID
|
|
9
|
-
from cg.constants.cli_options import DRY_RUN
|
|
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
|
-
|
|
22
|
-
from cg.constants.constants import MetaApis
|
|
19
|
+
from cg.constants.constants import MetaApis, Workflow
|
|
23
20
|
from cg.meta.workflow.analysis import AnalysisAPI
|
|
24
21
|
from cg.meta.workflow.nallo import NalloAnalysisAPI
|
|
25
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
|
|
26
27
|
|
|
27
28
|
LOG = logging.getLogger(__name__)
|
|
28
29
|
|
|
@@ -35,29 +36,78 @@ def nallo(context: click.Context) -> None:
|
|
|
35
36
|
context.obj.meta_apis[MetaApis.ANALYSIS_API] = NalloAnalysisAPI(config=context.obj)
|
|
36
37
|
|
|
37
38
|
|
|
38
|
-
nallo.add_command(config_case)
|
|
39
39
|
nallo.add_command(report_deliver)
|
|
40
|
-
nallo.add_command(run)
|
|
41
|
-
nallo.add_command(start)
|
|
42
|
-
nallo.add_command(start_available)
|
|
43
40
|
nallo.add_command(store)
|
|
44
41
|
nallo.add_command(store_available)
|
|
45
42
|
nallo.add_command(store_housekeeper)
|
|
46
43
|
nallo.add_command(metrics_deliver)
|
|
47
44
|
|
|
48
45
|
|
|
49
|
-
@nallo.command("
|
|
50
|
-
@DRY_RUN
|
|
46
|
+
@nallo.command("config-case")
|
|
51
47
|
@ARGUMENT_CASE_ID
|
|
52
48
|
@click.pass_obj
|
|
53
|
-
def
|
|
54
|
-
"""
|
|
49
|
+
def config_case(cg_config: CGConfig, case_id: str):
|
|
50
|
+
"""
|
|
51
|
+
Configure a Nallo case so that it is ready to be run.
|
|
52
|
+
|
|
53
|
+
\b
|
|
54
|
+
Creates the following files in the case run directory:
|
|
55
|
+
- CASE_ID_params_file.yaml
|
|
56
|
+
- CASE_ID_nextflow_config.json
|
|
57
|
+
- CASE_ID_samplesheet.csv
|
|
58
|
+
"""
|
|
59
|
+
factory = ConfiguratorFactory(cg_config)
|
|
60
|
+
configurator = cast(NextflowConfigurator, factory.get_configurator(Workflow.NALLO))
|
|
61
|
+
configurator.configure(case_id=case_id)
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
@nallo.command("run")
|
|
65
|
+
@OPTION_REVISION
|
|
66
|
+
@OPTION_RESUME
|
|
67
|
+
@ARGUMENT_CASE_ID
|
|
68
|
+
@click.pass_obj
|
|
69
|
+
def run(cg_config: CGConfig, case_id: str, resume: bool, revision: str | None) -> None:
|
|
70
|
+
"""
|
|
71
|
+
Run a preconfigured Nallo case.
|
|
72
|
+
|
|
73
|
+
\b
|
|
74
|
+
Assumes that the following files exist in the case run directory:
|
|
75
|
+
- CASE_ID_params_file.yaml
|
|
76
|
+
- CASE_ID_nextflow_config.json
|
|
77
|
+
- CASE_ID_samplesheet.csv
|
|
78
|
+
"""
|
|
79
|
+
factory = AnalysisStarterFactory(cg_config)
|
|
80
|
+
analysis_starter: AnalysisStarter = factory.get_analysis_starter_for_workflow(Workflow.NALLO)
|
|
81
|
+
analysis_starter.run(case_id=case_id, resume=resume, revision=revision)
|
|
55
82
|
|
|
56
|
-
analysis_api: NalloAnalysisAPI = context.meta_apis["analysis_api"]
|
|
57
|
-
analysis_api.status_db.verify_case_exists(case_internal_id=case_id)
|
|
58
83
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
84
|
+
@nallo.command("start")
|
|
85
|
+
@OPTION_REVISION
|
|
86
|
+
@ARGUMENT_CASE_ID
|
|
87
|
+
@click.pass_obj
|
|
88
|
+
def start(cg_config: CGConfig, case_id: str, revision: str | None):
|
|
89
|
+
"""
|
|
90
|
+
Start a Nallo case.
|
|
91
|
+
|
|
92
|
+
\b
|
|
93
|
+
Configures the case and writes the following files:
|
|
94
|
+
- CASE_ID_params_file.yaml
|
|
95
|
+
- CASE_ID_nextflow_config.json
|
|
96
|
+
- CASE_ID_samplesheet.csv
|
|
97
|
+
and submits the job to the Seqera Platform.
|
|
98
|
+
"""
|
|
99
|
+
factory = AnalysisStarterFactory(cg_config)
|
|
100
|
+
analysis_starter: AnalysisStarter = factory.get_analysis_starter_for_workflow(Workflow.NALLO)
|
|
101
|
+
analysis_starter.start(case_id=case_id, revision=revision)
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
@nallo.command("start-available")
|
|
105
|
+
@click.pass_obj
|
|
106
|
+
def start_available(cg_config: CGConfig):
|
|
107
|
+
"""Starts all available Nallo cases."""
|
|
108
|
+
LOG.info("Starting Nallo workflow for all available cases.")
|
|
109
|
+
factory = AnalysisStarterFactory(cg_config)
|
|
110
|
+
analysis_starter: AnalysisStarter = factory.get_analysis_starter_for_workflow(Workflow.NALLO)
|
|
111
|
+
succeeded: bool = analysis_starter.start_available()
|
|
112
|
+
if not succeeded:
|
|
113
|
+
raise click.Abort
|
cg/cli/workflow/nf_analysis.py
CHANGED
|
@@ -3,232 +3,30 @@
|
|
|
3
3
|
import logging
|
|
4
4
|
|
|
5
5
|
import rich_click as click
|
|
6
|
-
from pydantic import ValidationError
|
|
7
6
|
|
|
8
7
|
from cg.cli.workflow.commands import ARGUMENT_CASE_ID
|
|
9
8
|
from cg.cli.workflow.utils import validate_force_store_option
|
|
10
|
-
from cg.constants import EXIT_FAIL, EXIT_SUCCESS, Workflow
|
|
11
9
|
from cg.constants.cli_options import COMMENT, DRY_RUN, FORCE
|
|
12
10
|
from cg.constants.constants import MetaApis
|
|
13
|
-
from cg.exc import
|
|
11
|
+
from cg.exc import CgError, HousekeeperStoreError
|
|
14
12
|
from cg.meta.workflow.nf_analysis import NfAnalysisAPI
|
|
15
13
|
from cg.models.cg_config import CGConfig
|
|
16
|
-
from cg.store.models import Case
|
|
17
14
|
|
|
18
15
|
LOG = logging.getLogger(__name__)
|
|
19
16
|
|
|
20
|
-
|
|
21
|
-
"--work-dir",
|
|
22
|
-
type=click.Path(),
|
|
23
|
-
help="Directory where intermediate result files are stored",
|
|
24
|
-
)
|
|
17
|
+
|
|
25
18
|
OPTION_RESUME = click.option(
|
|
26
19
|
"--resume",
|
|
27
|
-
|
|
28
|
-
default=False,
|
|
29
|
-
show_default=True,
|
|
30
|
-
help="Execute the script using the cached results, useful to continue \
|
|
31
|
-
executions that was stopped by an error",
|
|
32
|
-
)
|
|
33
|
-
OPTION_PROFILE = click.option(
|
|
34
|
-
"--profile",
|
|
35
|
-
type=str,
|
|
20
|
+
default=True,
|
|
36
21
|
show_default=True,
|
|
37
|
-
help="
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
OPTION_CONFIG = click.option(
|
|
41
|
-
"--config",
|
|
42
|
-
type=click.Path(),
|
|
43
|
-
help="Nextflow config file path",
|
|
22
|
+
help="Execute the script using the cached results, useful to continue "
|
|
23
|
+
"executions that were stopped by an error",
|
|
44
24
|
)
|
|
45
|
-
|
|
46
|
-
OPTION_PARAMS_FILE = click.option(
|
|
47
|
-
"--params-file",
|
|
48
|
-
type=click.Path(),
|
|
49
|
-
help="Nextflow workflow-specific parameter file path",
|
|
50
|
-
)
|
|
51
|
-
|
|
52
|
-
OPTION_USE_NEXTFLOW = click.option(
|
|
53
|
-
"--use-nextflow",
|
|
54
|
-
type=bool,
|
|
55
|
-
is_flag=True,
|
|
56
|
-
default=False,
|
|
57
|
-
show_default=True,
|
|
58
|
-
help="Execute workflow using nextflow",
|
|
59
|
-
)
|
|
60
|
-
|
|
61
25
|
OPTION_REVISION = click.option(
|
|
62
26
|
"--revision",
|
|
63
27
|
type=str,
|
|
64
28
|
help="Revision of workflow to run (either a git branch, tag or commit SHA number)",
|
|
65
29
|
)
|
|
66
|
-
OPTION_COMPUTE_ENV = click.option(
|
|
67
|
-
"--compute-env",
|
|
68
|
-
type=str,
|
|
69
|
-
help="Compute environment name. If not specified the primary compute environment will be used.",
|
|
70
|
-
)
|
|
71
|
-
OPTION_TOWER_RUN_ID = click.option(
|
|
72
|
-
"--nf-tower-id",
|
|
73
|
-
type=str,
|
|
74
|
-
is_flag=False,
|
|
75
|
-
default=None,
|
|
76
|
-
help="NF-Tower ID of run to relaunch. If not provided the latest NF-Tower ID for a case will be used.",
|
|
77
|
-
)
|
|
78
|
-
OPTION_FROM_START = click.option(
|
|
79
|
-
"--from-start",
|
|
80
|
-
is_flag=True,
|
|
81
|
-
default=False,
|
|
82
|
-
show_default=True,
|
|
83
|
-
help="Start workflow from start without resuming execution",
|
|
84
|
-
)
|
|
85
|
-
OPTION_STUB = click.option(
|
|
86
|
-
"--stub-run",
|
|
87
|
-
is_flag=True,
|
|
88
|
-
default=False,
|
|
89
|
-
show_default=True,
|
|
90
|
-
help="Start a stub workflow",
|
|
91
|
-
)
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
@click.command("config-case")
|
|
95
|
-
@ARGUMENT_CASE_ID
|
|
96
|
-
@DRY_RUN
|
|
97
|
-
@click.pass_obj
|
|
98
|
-
def config_case(context: CGConfig, case_id: str, dry_run: bool) -> None:
|
|
99
|
-
"""Create config files required by a workflow for a case."""
|
|
100
|
-
analysis_api: NfAnalysisAPI = context.meta_apis[MetaApis.ANALYSIS_API]
|
|
101
|
-
try:
|
|
102
|
-
analysis_api.config_case(case_id=case_id, dry_run=dry_run)
|
|
103
|
-
except (CgError, ValidationError) as error:
|
|
104
|
-
LOG.error(f"Could not create config files for {case_id}: {error}")
|
|
105
|
-
raise click.Abort() from error
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
@click.command("run")
|
|
109
|
-
@ARGUMENT_CASE_ID
|
|
110
|
-
@OPTION_WORKDIR
|
|
111
|
-
@OPTION_FROM_START
|
|
112
|
-
@OPTION_PROFILE
|
|
113
|
-
@OPTION_CONFIG
|
|
114
|
-
@OPTION_PARAMS_FILE
|
|
115
|
-
@OPTION_REVISION
|
|
116
|
-
@OPTION_COMPUTE_ENV
|
|
117
|
-
@OPTION_USE_NEXTFLOW
|
|
118
|
-
@OPTION_TOWER_RUN_ID
|
|
119
|
-
@OPTION_STUB
|
|
120
|
-
@DRY_RUN
|
|
121
|
-
@click.pass_obj
|
|
122
|
-
def run(
|
|
123
|
-
context: CGConfig,
|
|
124
|
-
case_id: str,
|
|
125
|
-
work_dir: str,
|
|
126
|
-
from_start: bool,
|
|
127
|
-
profile: str,
|
|
128
|
-
config: str,
|
|
129
|
-
params_file: str,
|
|
130
|
-
revision: str,
|
|
131
|
-
compute_env: str,
|
|
132
|
-
use_nextflow: bool,
|
|
133
|
-
nf_tower_id: str | None,
|
|
134
|
-
stub_run: bool,
|
|
135
|
-
dry_run: bool,
|
|
136
|
-
) -> None:
|
|
137
|
-
"""Run analysis for a case."""
|
|
138
|
-
analysis_api: NfAnalysisAPI = context.meta_apis[MetaApis.ANALYSIS_API]
|
|
139
|
-
try:
|
|
140
|
-
analysis_api.run_nextflow_analysis(
|
|
141
|
-
case_id=case_id,
|
|
142
|
-
dry_run=dry_run,
|
|
143
|
-
work_dir=work_dir,
|
|
144
|
-
from_start=from_start,
|
|
145
|
-
profile=profile,
|
|
146
|
-
config=config,
|
|
147
|
-
params_file=params_file,
|
|
148
|
-
revision=revision,
|
|
149
|
-
compute_env=compute_env,
|
|
150
|
-
use_nextflow=use_nextflow,
|
|
151
|
-
nf_tower_id=nf_tower_id,
|
|
152
|
-
stub_run=stub_run,
|
|
153
|
-
)
|
|
154
|
-
except Exception as error:
|
|
155
|
-
LOG.error(f"Unspecified error occurred: {error}")
|
|
156
|
-
raise click.Abort() from error
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
@click.command("start")
|
|
160
|
-
@ARGUMENT_CASE_ID
|
|
161
|
-
@OPTION_WORKDIR
|
|
162
|
-
@OPTION_PROFILE
|
|
163
|
-
@OPTION_CONFIG
|
|
164
|
-
@OPTION_PARAMS_FILE
|
|
165
|
-
@OPTION_REVISION
|
|
166
|
-
@OPTION_COMPUTE_ENV
|
|
167
|
-
@OPTION_USE_NEXTFLOW
|
|
168
|
-
@OPTION_STUB
|
|
169
|
-
@DRY_RUN
|
|
170
|
-
@click.pass_obj
|
|
171
|
-
def start(
|
|
172
|
-
context: CGConfig,
|
|
173
|
-
case_id: str,
|
|
174
|
-
work_dir: str,
|
|
175
|
-
profile: str,
|
|
176
|
-
config: str,
|
|
177
|
-
params_file: str,
|
|
178
|
-
revision: str,
|
|
179
|
-
compute_env: str,
|
|
180
|
-
use_nextflow: bool,
|
|
181
|
-
stub_run: bool,
|
|
182
|
-
dry_run: bool,
|
|
183
|
-
) -> None:
|
|
184
|
-
"""Start workflow for a case."""
|
|
185
|
-
LOG.info(f"Starting analysis for {case_id}")
|
|
186
|
-
analysis_api: NfAnalysisAPI = context.meta_apis[MetaApis.ANALYSIS_API]
|
|
187
|
-
try:
|
|
188
|
-
analysis_api.status_db.verify_case_exists(case_internal_id=case_id)
|
|
189
|
-
case: Case = analysis_api.status_db.get_case_by_internal_id(case_id)
|
|
190
|
-
if case.data_analysis != Workflow.NALLO:
|
|
191
|
-
analysis_api.prepare_fastq_files(case_id=case_id, dry_run=dry_run)
|
|
192
|
-
analysis_api.config_case(case_id=case_id, dry_run=dry_run)
|
|
193
|
-
analysis_api.run_nextflow_analysis(
|
|
194
|
-
case_id=case_id,
|
|
195
|
-
dry_run=dry_run,
|
|
196
|
-
work_dir=work_dir,
|
|
197
|
-
from_start=True,
|
|
198
|
-
profile=profile,
|
|
199
|
-
config=config,
|
|
200
|
-
params_file=params_file,
|
|
201
|
-
revision=revision,
|
|
202
|
-
compute_env=compute_env,
|
|
203
|
-
use_nextflow=use_nextflow,
|
|
204
|
-
stub_run=stub_run,
|
|
205
|
-
)
|
|
206
|
-
except Exception as error:
|
|
207
|
-
LOG.error(f"Unexpected error occurred: {error}")
|
|
208
|
-
raise click.Abort from error
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
@click.command("start-available")
|
|
212
|
-
@DRY_RUN
|
|
213
|
-
@click.pass_context
|
|
214
|
-
def start_available(context: click.Context, dry_run: bool = False) -> None:
|
|
215
|
-
"""Start workflow for all cases ready for analysis."""
|
|
216
|
-
analysis_api: NfAnalysisAPI = context.obj.meta_apis[MetaApis.ANALYSIS_API]
|
|
217
|
-
|
|
218
|
-
cases: list[Case] = analysis_api.get_cases_to_analyze()
|
|
219
|
-
LOG.info(f"Starting {len(cases)} available {analysis_api.workflow} cases")
|
|
220
|
-
|
|
221
|
-
exit_code: int = EXIT_SUCCESS
|
|
222
|
-
for case in cases:
|
|
223
|
-
try:
|
|
224
|
-
context.invoke(start, case_id=case.internal_id, dry_run=dry_run)
|
|
225
|
-
except AnalysisNotReadyError as error:
|
|
226
|
-
LOG.error(error)
|
|
227
|
-
except Exception as error:
|
|
228
|
-
LOG.error(error)
|
|
229
|
-
exit_code = EXIT_FAIL
|
|
230
|
-
if exit_code:
|
|
231
|
-
raise click.Abort
|
|
232
30
|
|
|
233
31
|
|
|
234
32
|
@click.command("metrics-deliver")
|