Skip to content

Commit b44a765

Browse files
authored
Merge branch 'master' into add-pagination-cases-samples-pools
2 parents 2c7fa4d + eea3e7e commit b44a765

File tree

196 files changed

+1706
-1316
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

196 files changed

+1706
-1316
lines changed

.bumpversion.cfg

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[bumpversion]
2-
current_version = 64.5.8
2+
current_version = 64.5.29
33
commit = True
44
tag = True
55
tag_name = v{new_version}

Dockerfile

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,5 @@
11
FROM docker.io/library/python:3.11-slim-bullseye
22

3-
ENV GUNICORN_WORKERS=1
4-
ENV GUNICORN_THREADS=1
5-
ENV GUNICORN_BIND="0.0.0.0:8000"
6-
ENV GUNICORN_TIMEOUT=400
7-
8-
93
ENV CG_SQL_DATABASE_URI="sqlite:///:memory:"
104
ENV CG_SECRET_KEY="key"
115

@@ -29,7 +23,7 @@ ENV TRAILBLAZER_SERVICE_ACCOUNT_AUTH_FILE="auth_file"
2923

3024

3125
WORKDIR /home/src/app
32-
COPY pyproject.toml poetry.lock ./
26+
COPY pyproject.toml poetry.lock gunicorn.conf.py ./
3327

3428
RUN pip install --no-cache-dir poetry \
3529
&& poetry config virtualenvs.create false \
@@ -38,14 +32,5 @@ RUN pip install --no-cache-dir poetry \
3832
COPY cg ./cg
3933

4034
CMD gunicorn \
41-
--workers=$GUNICORN_WORKERS \
42-
--bind=$GUNICORN_BIND \
43-
--threads=$GUNICORN_THREADS \
44-
--timeout=$GUNICORN_TIMEOUT \
45-
--proxy-protocol \
46-
--forwarded-allow-ips="10.0.2.100,127.0.0.1" \
47-
--log-syslog \
48-
--access-logfile - \
49-
--error-logfile - \
50-
--log-level="debug" \
51-
cg.server.auto:app
35+
--config gunicorn.conf.py \
36+
cg.server.auto:app
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
"""add-nallo-to-analysis-options
2+
3+
Revision ID: 5552c02a4966
4+
Revises: 05ffb5e13d7b
5+
Create Date: 2024-12-02 11:35:31.725343
6+
7+
"""
8+
9+
from enum import StrEnum
10+
11+
from alembic import op
12+
import sqlalchemy as sa
13+
from sqlalchemy.dialects import mysql
14+
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
15+
16+
# revision identifiers, used by Alembic.
17+
revision = "5552c02a4966"
18+
down_revision = "05ffb5e13d7b"
19+
branch_labels = None
20+
depends_on = None
21+
22+
base_options = (
23+
"balsamic",
24+
"balsamic-pon",
25+
"balsamic-qc",
26+
"balsamic-umi",
27+
"demultiplex",
28+
"raw-data",
29+
"fluffy",
30+
"microsalt",
31+
"mip-dna",
32+
"mip-rna",
33+
"mutant",
34+
"raredisease",
35+
"rnafusion",
36+
"rsync",
37+
"spring",
38+
"taxprofiler",
39+
"tomte",
40+
"jasen",
41+
)
42+
43+
old_options = sorted(base_options)
44+
new_options = sorted(base_options + ("nallo",))
45+
46+
old_analysis_enum = mysql.ENUM(*old_options)
47+
new_analysis_enum = mysql.ENUM(*new_options)
48+
49+
50+
class Pipeline(StrEnum):
51+
BALSAMIC: str = "balsamic"
52+
BALSAMIC_PON: str = "balsamic-pon"
53+
BALSAMIC_QC: str = "balsamic-qc"
54+
BALSAMIC_UMI: str = "balsamic-umi"
55+
DEMULTIPLEX: str = "demultiplex"
56+
FLUFFY: str = "fluffy"
57+
JASEN: str = "jasen"
58+
MICROSALT: str = "microsalt"
59+
MIP_DNA: str = "mip-dna"
60+
MIP_RNA: str = "mip-rna"
61+
MUTANT: str = "mutant"
62+
NALLO: str = "nallo"
63+
RAREDISEASE: str = "raredisease"
64+
RAW_DATA: str = "raw-data"
65+
RNAFUSION: str = "rnafusion"
66+
RSYNC: str = "rsync"
67+
SPRING: str = "spring"
68+
TAXPROFILER: str = "taxprofiler"
69+
TOMTE: str = "tomte"
70+
71+
72+
class Base(DeclarativeBase):
73+
pass
74+
75+
76+
class Analysis(Base):
77+
__tablename__ = "analysis"
78+
id = sa.Column(sa.types.Integer, primary_key=True)
79+
workflow = sa.Column(sa.types.Enum(*list(Pipeline)))
80+
81+
82+
class Case(Base):
83+
__tablename__ = "case"
84+
id = sa.Column(sa.types.Integer, primary_key=True)
85+
data_analysis = sa.Column(sa.types.Enum(*list(Pipeline)))
86+
internal_id = sa.Column(sa.types.String)
87+
88+
89+
def upgrade():
90+
op.alter_column("case", "data_analysis", type_=new_analysis_enum)
91+
op.alter_column("analysis", "workflow", type_=new_analysis_enum)
92+
93+
94+
def downgrade():
95+
bind = op.get_bind()
96+
session = sa.orm.Session(bind=bind)
97+
for analysis in session.query(Analysis).filter(Analysis.workflow == "nallo"):
98+
print(f"Changing pipeline for Case {Case.internal_id} to raw-data")
99+
analysis.workflow = "raw-data"
100+
for case in session.query(Case).filter(Case.data_analysis == "nallo"):
101+
print(f"Changing data_analysis for Case {case.internal_id} to raw-data")
102+
case.data_analysis = "raw-data"
103+
op.alter_column("case", "data_analysis", type_=old_analysis_enum)
104+
op.alter_column("analysis", "workflow", type_=old_analysis_enum)
105+
session.commit()

cg/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
__title__ = "cg"
2-
__version__ = "64.5.8"
2+
__version__ = "64.5.29"

cg/apps/demultiplex/demultiplex_api.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
from cg.apps.tb import TrailblazerAPI
1313
from cg.constants.constants import FileFormat, Workflow
1414
from cg.constants.demultiplexing import DemultiplexingDirsAndFiles
15-
from cg.constants.priority import SlurmQos
16-
from cg.constants.tb import AnalysisTypes
15+
from cg.constants.priority import SlurmQos, TrailblazerPriority
16+
from cg.constants.tb import AnalysisType
1717
from cg.exc import HousekeeperFileMissingError
1818
from cg.io.controller import WriteFile
1919
from cg.models.demultiplex.sbatch import SbatchCommand, SbatchError
@@ -49,6 +49,11 @@ def slurm_quality_of_service(self) -> Literal[SlurmQos.HIGH, SlurmQos.LOW]:
4949
"""Return SLURM quality of service."""
5050
return SlurmQos.LOW if self.environment == "stage" else SlurmQos.HIGH
5151

52+
@property
53+
def trailblazer_priority(self) -> Literal[TrailblazerPriority.HIGH, TrailblazerPriority.LOW]:
54+
"""Return Trailblazer quality of service."""
55+
return TrailblazerPriority.LOW if self.environment == "stage" else TrailblazerPriority.HIGH
56+
5257
def set_dry_run(self, dry_run: bool) -> None:
5358
"""Set dry run."""
5459
LOG.debug(f"DemultiplexingAPI: Set dry run to {dry_run}")
@@ -210,10 +215,10 @@ def add_to_trailblazer(
210215
)
211216
tb_api.add_pending_analysis(
212217
case_id=sequencing_run.id,
213-
analysis_type=AnalysisTypes.OTHER,
218+
analysis_type=AnalysisType.OTHER,
214219
config_path=sequencing_run.trailblazer_config_path.as_posix(),
215220
out_dir=sequencing_run.trailblazer_config_path.parent.as_posix(),
216-
slurm_quality_of_service=self.slurm_quality_of_service,
221+
priority=self.trailblazer_priority,
217222
email=self.mail,
218223
workflow=Workflow.DEMULTIPLEX,
219224
)

cg/apps/demultiplex/sample_sheet/api.py

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
import logging
22
from pathlib import Path
33

4-
import click
4+
import rich_click as click
55

66
from cg.apps.demultiplex.sample_sheet.read_sample_sheet import get_samples_from_content
77
from cg.apps.demultiplex.sample_sheet.sample_models import IlluminaSampleIndexSetting
88
from cg.apps.demultiplex.sample_sheet.sample_sheet_creator import SampleSheetCreator
99
from cg.apps.demultiplex.sample_sheet.sample_sheet_validator import SampleSheetValidator
1010
from cg.apps.demultiplex.sample_sheet.utils import (
11-
delete_sample_sheet_from_housekeeper,
1211
add_and_include_sample_sheet_path_to_housekeeper,
12+
delete_sample_sheet_from_housekeeper,
1313
)
1414
from cg.apps.housekeeper.hk import HousekeeperAPI
1515
from cg.apps.lims import LimsAPI
@@ -160,6 +160,20 @@ def _use_sample_sheet_from_housekeeper(
160160
"would have copied it to sequencing run directory"
161161
)
162162
return
163+
164+
try:
165+
if sample_sheet_path.samefile(run_directory_data.sample_sheet_path):
166+
LOG.info(
167+
"Sample sheet from Housekeeper is the same as the sequencing directory sample sheet"
168+
)
169+
return
170+
except FileNotFoundError:
171+
LOG.info(
172+
f"Sample sheet or target path does not exist. "
173+
f"Housekeeper sample sheet path: {sample_sheet_path}, "
174+
f"Target sample sheet path: {run_directory_data.sample_sheet_path}"
175+
)
176+
163177
LOG.info("Sample sheet from Housekeeper is valid. Copying it to sequencing run directory")
164178
link_or_overwrite_file(src=sample_sheet_path, dst=run_directory_data.sample_sheet_path)
165179

cg/apps/gens.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
import logging
44

5-
from cg.constants.constants import PrepCategory
5+
from cg.constants.sequencing import SeqLibraryPrepCategory
66
from cg.store.models import Case
77
from cg.utils import Process
88
from cg.utils.dict import get_list_from_dictionary
@@ -51,7 +51,8 @@ def load(
5151
def is_suitable_for_upload(case: Case) -> bool:
5252
"""Check if a cancer case supports Gens upload."""
5353
return all(
54-
sample.prep_category == PrepCategory.WHOLE_GENOME_SEQUENCING for sample in case.samples
54+
sample.prep_category == SeqLibraryPrepCategory.WHOLE_GENOME_SEQUENCING
55+
for sample in case.samples
5556
)
5657

5758
def __str__(self):

cg/apps/hermes/hermes_api.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@ class HermesApi:
1515
"""Class to communicate with hermes"""
1616

1717
def __init__(self, config: dict):
18-
self.process = Process(binary=config["hermes"]["binary_path"])
18+
self.process = Process(
19+
binary=config["hermes"]["binary_path"],
20+
)
21+
self.container_mount_volume = config["hermes"]["container_mount_volume"]
1922

2023
def convert_deliverables(
2124
self,
@@ -27,6 +30,10 @@ def convert_deliverables(
2730
"""Convert deliverables file in raw workflow format to CG format with Hermes."""
2831
LOG.info("Converting workflow deliverables to CG deliverables")
2932
convert_command = [
33+
"run",
34+
"--bind",
35+
self.container_mount_volume,
36+
"/home/proj/stage/singularity_containers/hermes_latest.sif",
3037
"convert",
3138
"deliverables",
3239
"--workflow",

cg/apps/orderform/excel_orderform_parser.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class ExcelOrderformParser(OrderformParser):
2525
SHEET_NAMES: list[str] = ["Orderform", "orderform", "order form", "Order Form"]
2626
VALID_ORDERFORMS: list[str] = [
2727
f"{Orderform.MIP_DNA}:{Orderform.get_current_orderform_version(Orderform.MIP_DNA)}", # Orderform MIP-DNA, Balsamic, sequencing only, MIP-RNA
28-
f"{Orderform.MICROSALT}:{Orderform.get_current_orderform_version(Orderform.MICROSALT)}", # Microbial WGS
28+
f"{Orderform.MICROSALT}:{Orderform.get_current_orderform_version(Orderform.MICROSALT)}", # Microbial WHOLE_GENOME_SEQUENCING
2929
f"{Orderform.RML}:{Orderform.get_current_orderform_version(Orderform.RML)}", # Orderform Ready made libraries (RML)
3030
f"{Orderform.METAGENOME}:{Orderform.get_current_orderform_version(Orderform.METAGENOME)}", # Microbial meta genomes
3131
f"{Orderform.SARS_COV_2}:{Orderform.get_current_orderform_version(Orderform.SARS_COV_2)}", # Orderform SARS-CoV-2

cg/apps/orderform/orderform_parser.py

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
from pydantic import BaseModel, ConfigDict, constr
66

7+
from cg.apps.orderform.utils import ORDER_TYPES_WITH_CASES
78
from cg.constants import DataDelivery
89
from cg.exc import OrderFormError
910
from cg.models.orders.order import OrderType
@@ -142,10 +143,11 @@ def expand_case(case_id: str, case_samples: list[OrderSample]) -> OrderCase:
142143

143144
def generate_orderform(self) -> Orderform:
144145
"""Generate an orderform"""
145-
cases_map: dict[str, list[OrderSample]] = self.group_cases()
146146
case_objs: list[OrderCase] = []
147-
for case_id in cases_map:
148-
case_objs.append(self.expand_case(case_id=case_id, case_samples=cases_map[case_id]))
147+
if self.project_type in ORDER_TYPES_WITH_CASES:
148+
cases_map: dict[str, list[OrderSample]] = self.group_cases()
149+
for case_id in cases_map:
150+
case_objs.append(self.expand_case(case_id=case_id, case_samples=cases_map[case_id]))
149151
return Orderform(
150152
comment=self.order_comment,
151153
samples=self.samples,

0 commit comments

Comments
 (0)