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.
Files changed (152) hide show
  1. cg/__init__.py +1 -1
  2. cg/apps/housekeeper/hk.py +18 -1
  3. cg/apps/tb/api.py +42 -5
  4. cg/cli/transfer.py +13 -2
  5. cg/cli/upload/mutacc.py +16 -3
  6. cg/cli/upload/scout.py +2 -2
  7. cg/cli/upload/utils.py +10 -1
  8. cg/cli/workflow/balsamic/base.py +86 -172
  9. cg/cli/workflow/balsamic/options.py +3 -48
  10. cg/cli/workflow/balsamic/umi.py +210 -15
  11. cg/cli/workflow/microsalt/base.py +4 -2
  12. cg/cli/workflow/mip_dna/base.py +1 -1
  13. cg/cli/workflow/nallo/base.py +73 -23
  14. cg/cli/workflow/nf_analysis.py +5 -207
  15. cg/cli/workflow/raredisease/base.py +41 -54
  16. cg/cli/workflow/rnafusion/base.py +38 -8
  17. cg/cli/workflow/taxprofiler/base.py +31 -18
  18. cg/cli/workflow/tomte/base.py +83 -10
  19. cg/constants/constants.py +25 -30
  20. cg/constants/devices.py +6 -1
  21. cg/constants/gene_panel.py +3 -1
  22. cg/constants/housekeeper_tags.py +28 -28
  23. cg/constants/lims.py +4 -0
  24. cg/constants/nf_analysis.py +0 -1
  25. cg/constants/observations.py +21 -5
  26. cg/constants/orderforms.py +3 -3
  27. cg/constants/pacbio.py +1 -0
  28. cg/constants/priority.py +1 -1
  29. cg/constants/report.py +1 -0
  30. cg/constants/scout.py +12 -9
  31. cg/constants/sequencing.py +2 -2
  32. cg/constants/tb.py +5 -5
  33. cg/exc.py +27 -5
  34. cg/meta/compress/compress.py +7 -2
  35. cg/meta/delivery_report/balsamic.py +3 -1
  36. cg/meta/delivery_report/delivery_report_api.py +4 -3
  37. cg/meta/delivery_report/nallo.py +11 -11
  38. cg/meta/delivery_report/raredisease.py +7 -3
  39. cg/meta/delivery_report/templates/macros/data_analysis/qc_metrics/balsamic_qc_metrics.html +1 -0
  40. cg/meta/delivery_report/templates/macros/ticket_system.html +1 -1
  41. cg/meta/observations/balsamic_observations_api.py +110 -14
  42. cg/meta/observations/mip_dna_observations_api.py +1 -1
  43. cg/meta/observations/nallo_observations_api.py +1 -1
  44. cg/meta/observations/observations_api.py +23 -32
  45. cg/meta/observations/raredisease_observations_api.py +1 -1
  46. cg/meta/tar/tar.py +5 -2
  47. cg/meta/transfer/lims.py +32 -3
  48. cg/meta/upload/balsamic/balsamic.py +1 -8
  49. cg/meta/upload/coverage.py +5 -5
  50. cg/meta/upload/raredisease/raredisease.py +3 -0
  51. cg/meta/upload/scout/hk_tags.py +1 -0
  52. cg/meta/upload/scout/nallo_config_builder.py +31 -7
  53. cg/meta/workflow/balsamic.py +70 -36
  54. cg/meta/workflow/fastq.py +8 -0
  55. cg/meta/workflow/microsalt/quality_controller/models.py +0 -2
  56. cg/meta/workflow/microsalt/quality_controller/quality_controller.py +8 -16
  57. cg/meta/workflow/microsalt/quality_controller/result_logger.py +3 -6
  58. cg/meta/workflow/microsalt/quality_controller/utils.py +2 -45
  59. cg/meta/workflow/nallo.py +21 -99
  60. cg/meta/workflow/nf_analysis.py +12 -263
  61. cg/meta/workflow/raredisease.py +3 -112
  62. cg/meta/workflow/rnafusion.py +2 -34
  63. cg/meta/workflow/taxprofiler.py +2 -38
  64. cg/meta/workflow/tomte.py +2 -42
  65. cg/models/balsamic/config.py +0 -24
  66. cg/models/balsamic/metrics.py +5 -3
  67. cg/models/cg_config.py +39 -16
  68. cg/models/deliverables/metric_deliverables.py +1 -1
  69. cg/models/delivery_report/metadata.py +2 -1
  70. cg/models/nallo/nallo.py +14 -64
  71. cg/models/nf_analysis.py +1 -41
  72. cg/models/raredisease/raredisease.py +1 -63
  73. cg/models/rnafusion/rnafusion.py +0 -26
  74. cg/models/scout/scout_load_config.py +5 -2
  75. cg/models/taxprofiler/taxprofiler.py +0 -42
  76. cg/models/tomte/tomte.py +0 -69
  77. cg/resources/nallo_bundle_filenames.yaml +292 -22
  78. cg/resources/raredisease_bundle_filenames.yaml +11 -1
  79. cg/resources/taxprofiler_bundle_filenames.yaml +20 -0
  80. cg/server/admin.py +106 -25
  81. cg/server/app.py +15 -4
  82. cg/server/endpoints/sequencing_run/dtos.py +21 -3
  83. cg/server/endpoints/sequencing_run/pacbio_sequencing_run.py +29 -10
  84. cg/server/endpoints/sequencing_run/pacbio_smrt_cell_metrics.py +20 -0
  85. cg/services/analysis_starter/{service.py → analysis_starter.py} +11 -9
  86. cg/services/analysis_starter/configurator/abstract_model.py +8 -0
  87. cg/services/analysis_starter/configurator/configurator.py +1 -1
  88. cg/services/analysis_starter/configurator/extensions/nallo.py +27 -0
  89. cg/services/analysis_starter/configurator/extensions/{abstract.py → pipeline_extension.py} +1 -1
  90. cg/services/analysis_starter/configurator/extensions/raredisease.py +3 -1
  91. cg/services/analysis_starter/configurator/extensions/tomte_extension.py +28 -0
  92. cg/services/analysis_starter/configurator/file_creators/balsamic_config.py +240 -0
  93. cg/services/analysis_starter/configurator/file_creators/gene_panel.py +10 -5
  94. cg/services/analysis_starter/configurator/file_creators/nextflow/params_file/abstract.py +2 -1
  95. cg/services/analysis_starter/configurator/file_creators/nextflow/params_file/models.py +40 -1
  96. cg/services/analysis_starter/configurator/file_creators/nextflow/params_file/nallo.py +37 -0
  97. cg/services/analysis_starter/configurator/file_creators/nextflow/params_file/raredisease.py +8 -5
  98. cg/services/analysis_starter/configurator/file_creators/nextflow/params_file/tomte_params_file_creator.py +64 -0
  99. cg/services/analysis_starter/configurator/file_creators/nextflow/sample_sheet/creator.py +1 -1
  100. cg/services/analysis_starter/configurator/file_creators/nextflow/sample_sheet/nallo_sample_sheet_creator.py +65 -0
  101. cg/services/analysis_starter/configurator/file_creators/nextflow/sample_sheet/protocol.py +12 -0
  102. cg/services/analysis_starter/configurator/file_creators/nextflow/sample_sheet/{raredisease.py → raredisease_sample_sheet_creator.py} +2 -2
  103. cg/services/analysis_starter/configurator/file_creators/nextflow/sample_sheet/{rnafusion.py → rnafusion_sample_sheet_creator.py} +2 -2
  104. cg/services/analysis_starter/configurator/file_creators/nextflow/sample_sheet/{taxprofiler.py → taxprofiler_sample_sheet_creator.py} +2 -2
  105. cg/services/analysis_starter/configurator/file_creators/nextflow/sample_sheet/tomte_sample_sheet_creator.py +36 -0
  106. cg/services/analysis_starter/configurator/implementations/balsamic.py +68 -0
  107. cg/services/analysis_starter/configurator/implementations/nextflow.py +22 -5
  108. cg/services/analysis_starter/configurator/models/balsamic.py +152 -0
  109. cg/services/analysis_starter/configurator/models/mip_dna.py +6 -8
  110. cg/services/analysis_starter/configurator/models/nextflow.py +9 -0
  111. cg/services/analysis_starter/constants.py +2 -0
  112. cg/services/analysis_starter/factories/configurator_factory.py +131 -51
  113. cg/services/analysis_starter/factories/starter_factory.py +36 -7
  114. cg/services/analysis_starter/input_fetcher/implementations/bam_fetcher.py +57 -0
  115. cg/services/analysis_starter/input_fetcher/implementations/fastq_fetcher.py +3 -3
  116. cg/services/analysis_starter/submitters/seqera_platform/{client.py → seqera_platform_client.py} +19 -3
  117. cg/services/analysis_starter/submitters/seqera_platform/seqera_platform_submitter.py +73 -0
  118. cg/services/analysis_starter/submitters/submitter.py +1 -1
  119. cg/services/analysis_starter/submitters/subprocess/submitter.py +2 -1
  120. cg/services/analysis_starter/tracker/implementations/balsamic.py +22 -0
  121. cg/services/analysis_starter/tracker/implementations/microsalt.py +4 -4
  122. cg/services/analysis_starter/tracker/implementations/mip_dna.py +4 -1
  123. cg/services/analysis_starter/tracker/implementations/{nextflow.py → nextflow_tracker.py} +6 -4
  124. cg/services/analysis_starter/tracker/tracker.py +19 -15
  125. cg/services/deliver_files/factory.py +1 -1
  126. cg/services/delivery_message/messages/__init__.py +24 -14
  127. cg/services/delivery_message/messages/{microsalt_mwr_message.py → microsalt_message.py} +1 -1
  128. cg/services/delivery_message/utils.py +4 -40
  129. cg/services/illumina/backup/backup_service.py +29 -7
  130. cg/services/orders/validation/constants.py +3 -0
  131. cg/services/orders/validation/index_sequences.py +558 -0
  132. cg/services/orders/validation/order_types/microsalt/models/sample.py +2 -3
  133. cg/services/run_devices/pacbio/data_storage_service/pacbio_store_service.py +39 -18
  134. cg/services/run_devices/pacbio/data_transfer_service/data_transfer_service.py +8 -2
  135. cg/services/run_devices/pacbio/data_transfer_service/dto.py +9 -3
  136. cg/services/run_devices/pacbio/data_transfer_service/utils.py +14 -7
  137. cg/services/run_devices/pacbio/metrics_parser/models.py +1 -0
  138. cg/services/run_devices/pacbio/sequencing_runs_service.py +35 -7
  139. cg/services/sequencing_qc_service/quality_checks/checks.py +18 -16
  140. cg/services/sequencing_qc_service/quality_checks/utils.py +82 -18
  141. cg/services/sequencing_qc_service/sequencing_qc_service.py +12 -10
  142. cg/store/crud/create.py +73 -42
  143. cg/store/crud/read.py +73 -7
  144. cg/store/crud/update.py +14 -3
  145. cg/store/models.py +98 -35
  146. cg/store/store.py +8 -1
  147. {cg-76.0.0.dist-info → cg-83.14.0.dist-info}/METADATA +1 -1
  148. {cg-76.0.0.dist-info → cg-83.14.0.dist-info}/RECORD +150 -138
  149. cg/services/analysis_starter/submitters/seqera_platform/submitter.py +0 -39
  150. cg/services/delivery_message/messages/microsalt_mwx_message.py +0 -18
  151. {cg-76.0.0.dist-info → cg-83.14.0.dist-info}/WHEEL +0 -0
  152. {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, echo_lines
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
- config_case,
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 dev_config_case(cg_config: CGConfig, case_id: str):
58
- """Configure a raredisease case so that it is ready to be run."""
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 dev_run(cg_config: CGConfig, case_id: str):
68
- """Run a preconfigured raredisease case."""
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 dev_start(cg_config: CGConfig, case_id: str):
80
- """Start a raredisease case. Configures the case if needed."""
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 dev_start_available(cg_config: CGConfig) -> None:
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
- """Configure an RNAFUSION case so that it is ready to be run."""
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
- """Run a preconfigured RNAFUSION case."""
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
- """Start an RNAFUSION case. Configures the case if needed."""
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
- """Start a Taxprofiler case. \n
42
- Configures the case and writes the following files: \n
43
- - CASE_ID_params_file.yaml \n
44
- - CASE_ID_nextflow_config.json \n
45
- - CASE_ID_samplesheet.csv \n
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
- """Run a preconfigured Taxprofiler case. \n
74
- Assumes that the following files are in the case run directory: \n
75
- - CASE_ID_params_file.yaml \n
76
- - CASE_ID_nextflow_config.json \n
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. \n
91
- Creates the following files in the case run directory:\n
92
- - CASE_ID_params_file.yaml \n
93
- - CASE_ID_nextflow_config.json \n
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)
@@ -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
- config_case,
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: str = "cust000"
64
- CUST001: str = "cust001"
65
- CUST002: str = "cust002"
66
- CUST003: str = "cust003"
67
- CUST004: str = "cust004"
68
- CUST032: str = "cust032"
69
- CUST042: str = "cust042"
70
- CUST110: str = "cust110"
71
- CUST127: str = "cust127"
72
- CUST132: str = "cust132"
73
- CUST143: str = "cust143"
74
- CUST147: str = "cust147"
75
- CUST201: str = "cust201"
76
- CUST999: str = "cust999"
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: str = "male"
101
- FEMALE: str = "female"
102
- UNKNOWN: str = "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: str = "GRCh37"
157
- GRCh38: str = "GRCh38"
158
- T2T_CHM13: str = "T2T-CHM13v2.0"
159
+ GRCh37 = "GRCh37"
160
+ GRCh38 = "GRCh38"
161
+ T2T_CHM13 = "T2T-CHM13v2.0"
159
162
  CANFAM3 = auto()
160
- HG19: str = "hg19"
161
- HG38: str = "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"
@@ -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
- INHERITED_CANCER = "Inherited cancer"
52
+ IHC = "IHC"
51
53
  VEO_IBD = "VEO-IBD"
52
54
  KIDNEY = "Kidney"
53
55
  CAKUT = "CAKUT"
@@ -57,34 +57,34 @@ class HermesFileTag(StrEnum):
57
57
  class AnalysisTag(StrEnum):
58
58
  """Tags for analysis files."""
59
59
 
60
- ARRIBA: str = "arriba"
61
- ARRIBA_VISUALIZATION: str = "arriba-visualisation"
62
- BED: str = "bed"
63
- BIGWIG: str = "bigwig"
64
- CLINICAL: str = "clinical"
65
- COVERAGE: str = "coverage"
66
- FRASER: str = "fraser"
67
- FUSION: str = "fusion"
68
- FUSIONCATCHER: str = "fusioncatcher"
69
- FUSIONCATCHER_SUMMARY: str = "fusioncatcher-summary"
70
- FUSIONINSPECTOR: str = "fusioninspector"
71
- FUSIONINSPECTOR_HTML: str = "fusioninspector-html"
72
- FUSIONREPORT: str = "fusionreport"
73
- GENE_COUNTS: str = "gene-counts"
74
- JUNCTION: str = "junction"
75
- MULTIQC_HTML: str = "multiqc-html"
76
- OUTRIDER: str = "outrider"
77
- REPEATS: str = "repeats"
78
- RESEARCH: str = "research"
79
- RNA: str = "rna"
80
- SMN_CALLING: str = "smn-calling"
81
- STARFUSION: str = "star-fusion"
82
- VCF_FUSION: str = "vcf-fusion"
83
- VCF_SNV: str = "vcf-snv"
84
- VCF_SNV_CLINICAL: str = "vcf-snv-clinical"
85
- VCF_STR: str = "vcf-str"
86
- VCF_SV_CLINICAL: str = "vcf-sv-clinical"
87
- VCF_SV: str = "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": {