Skip to content

Commit 3dc55d5

Browse files
committed
Include Singularity and Containers classes into config setup, and update related components
1 parent b9ffb6a commit 3dc55d5

File tree

8 files changed

+113
-36
lines changed

8 files changed

+113
-36
lines changed

microSALT/cli.py

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,8 @@ def analyse(
211211
threshold=cfg.threshold,
212212
pubmlst=cfg.pubmlst,
213213
pasteur=cfg.pasteur,
214+
singularity=cfg.singularity,
215+
containers=cfg.containers,
214216
sampleinfo=sampleinfo,
215217
run_settings=run_settings,
216218
)
@@ -221,6 +223,8 @@ def analyse(
221223
threshold=cfg.threshold,
222224
pubmlst=cfg.pubmlst,
223225
pasteur=cfg.pasteur,
226+
singularity=cfg.singularity,
227+
containers=cfg.containers,
224228
sampleinfo=sampleinfo,
225229
force=force_update,
226230
)
@@ -318,6 +322,8 @@ def finish(ctx, sampleinfo_file, input, track, dry, email, skip_update, report,
318322
threshold=cfg.threshold,
319323
pubmlst=cfg.pubmlst,
320324
pasteur=cfg.pasteur,
325+
singularity=cfg.singularity,
326+
containers=cfg.containers,
321327
sampleinfo=sampleinfo,
322328
)
323329
try:
@@ -346,6 +352,8 @@ def finish(ctx, sampleinfo_file, input, track, dry, email, skip_update, report,
346352
config_path=cfg.config_path,
347353
pubmlst=cfg.pubmlst,
348354
pasteur=cfg.pasteur,
355+
singularity=cfg.singularity,
356+
containers=cfg.containers,
349357
sampleinfo=sampleinfo,
350358
input=input,
351359
)
@@ -376,7 +384,8 @@ def add(ctx, organism, force):
376384
cfg = ctx.obj["config"]
377385
referee = Referencer(
378386
log=logger, folders=cfg.folders, threshold=cfg.threshold,
379-
pubmlst=cfg.pubmlst, pasteur=cfg.pasteur, force=force,
387+
pubmlst=cfg.pubmlst, pasteur=cfg.pasteur,
388+
singularity=cfg.singularity, containers=cfg.containers, force=force,
380389
)
381390
try:
382391
referee.add_pubmlst(organism)
@@ -386,7 +395,8 @@ def add(ctx, organism, force):
386395
click.echo("INFO - Checking versions of all references..")
387396
referee = Referencer(
388397
log=logger, folders=cfg.folders, threshold=cfg.threshold,
389-
pubmlst=cfg.pubmlst, pasteur=cfg.pasteur, force=force,
398+
pubmlst=cfg.pubmlst, pasteur=cfg.pasteur,
399+
singularity=cfg.singularity, containers=cfg.containers, force=force,
390400
)
391401
referee.update_refs()
392402

@@ -399,6 +409,7 @@ def observe(ctx):
399409
refe = Referencer(
400410
log=logger, folders=cfg.folders, threshold=cfg.threshold,
401411
pubmlst=cfg.pubmlst, pasteur=cfg.pasteur,
412+
singularity=cfg.singularity, containers=cfg.containers,
402413
)
403414
click.echo("INFO - Currently stored organisms:")
404415
for org in sorted(refe.existing_organisms()):
@@ -500,6 +511,7 @@ def review(ctx, type, customer, skip_update, email, output):
500511
ext_refs = Referencer(
501512
log=logger, folders=cfg.folders, threshold=cfg.threshold,
502513
pubmlst=cfg.pubmlst, pasteur=cfg.pasteur,
514+
singularity=cfg.singularity, containers=cfg.containers,
503515
)
504516
if not skip_update:
505517
ext_refs.update_refs()
@@ -521,7 +533,8 @@ def update_refs(ctx, force_update: bool):
521533
cfg = ctx.obj["config"]
522534
ext_refs = Referencer(
523535
log=logger, folders=cfg.folders, threshold=cfg.threshold,
524-
pubmlst=cfg.pubmlst, pasteur=cfg.pasteur, force=force_update,
536+
pubmlst=cfg.pubmlst, pasteur=cfg.pasteur,
537+
singularity=cfg.singularity, containers=cfg.containers, force=force_update,
525538
)
526539
ext_refs.update_refs()
527540
done()
@@ -535,7 +548,8 @@ def update_from_static(ctx, force_update: bool):
535548
cfg = ctx.obj["config"]
536549
ext_refs = Referencer(
537550
log=logger, folders=cfg.folders, threshold=cfg.threshold,
538-
pubmlst=cfg.pubmlst, pasteur=cfg.pasteur, force=force_update,
551+
pubmlst=cfg.pubmlst, pasteur=cfg.pasteur,
552+
singularity=cfg.singularity, containers=cfg.containers, force=force_update,
539553
)
540554
ext_refs.fetch_external()
541555
done()
@@ -551,7 +565,8 @@ def update_organism(ctx, external: bool, force_update: bool, organism: str):
551565
cfg = ctx.obj["config"]
552566
ext_refs = Referencer(
553567
log=logger, folders=cfg.folders, threshold=cfg.threshold,
554-
pubmlst=cfg.pubmlst, pasteur=cfg.pasteur, force=force_update,
568+
pubmlst=cfg.pubmlst, pasteur=cfg.pasteur,
569+
singularity=cfg.singularity, containers=cfg.containers, force=force_update,
555570
)
556571
ext_refs.update_organism(external=external, organism=organism)
557572
done()
@@ -572,6 +587,7 @@ def overwrite(ctx, sample_name, force):
572587
ext_refs = Referencer(
573588
log=logger, folders=cfg.folders, threshold=cfg.threshold,
574589
pubmlst=cfg.pubmlst, pasteur=cfg.pasteur,
590+
singularity=cfg.singularity, containers=cfg.containers,
575591
)
576592
ext_refs.resync(type="overwrite", sample=sample_name, ignore=force)
577593
done()

microSALT/config.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,22 @@ class PasteurCredentials(BIGSdbCredentials):
7676
pass
7777

7878

79+
class Singularity(BaseModel):
80+
binary: str = "/usr/bin/singularity"
81+
bind_paths: list[str] = []
82+
trimmomatic_adapters: str = "/opt/conda/share/trimmomatic/adapters/"
83+
84+
85+
class Containers(BaseModel):
86+
skesa: str = ""
87+
blast: str = ""
88+
bwa: str = ""
89+
samtools: str = ""
90+
picard: str = ""
91+
trimmomatic: str = ""
92+
quast: str = ""
93+
94+
7995
class MicroSALTConfig(BaseModel):
8096
slurm_header: SlurmHeader
8197
regex: Regex
@@ -84,6 +100,8 @@ class MicroSALTConfig(BaseModel):
84100
threshold: Threshold
85101
pubmlst: PubMLSTCredentials = PubMLSTCredentials()
86102
pasteur: PasteurCredentials = PasteurCredentials()
103+
singularity: Singularity = Singularity()
104+
containers: Containers = Containers()
87105
# Runtime fields set by the CLI, not from the JSON file
88106
dry: bool = False
89107
config_path: str = ""

microSALT/utils/job_creator.py

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@
1717
import yaml
1818

1919
from microSALT import __version__
20-
from microSALT.config import Folders, Threshold, SlurmHeader, Regex, PubMLSTCredentials, PasteurCredentials
20+
from microSALT.config import Folders, Threshold, SlurmHeader, Regex, PubMLSTCredentials, PasteurCredentials, Singularity, Containers
2121
from microSALT.store.db_manipulator import DB_Manipulator
2222
from microSALT.utils.referencer import Referencer
2323

2424

2525
class Job_Creator:
26-
def __init__(self, log, folders: Folders, slurm_header: SlurmHeader, regex: Regex, dry: bool, config_path: str, threshold: Threshold, pubmlst: PubMLSTCredentials, pasteur: PasteurCredentials, sampleinfo={}, run_settings={}):
26+
def __init__(self, log, folders: Folders, slurm_header: SlurmHeader, regex: Regex, dry: bool, config_path: str, threshold: Threshold, pubmlst: PubMLSTCredentials, pasteur: PasteurCredentials, singularity: Singularity, containers: Containers, sampleinfo={}, run_settings={}):
2727
self.folders = folders
2828
self.slurm_header = slurm_header
2929
self.regex = regex
@@ -32,6 +32,8 @@ def __init__(self, log, folders: Folders, slurm_header: SlurmHeader, regex: Rege
3232
self.threshold = threshold
3333
self.pubmlst = pubmlst
3434
self.pasteur = pasteur
35+
self.singularity = singularity
36+
self.containers = containers
3537
self.logger = log
3638
self.batchfile = "/tmp/batchfile.sbatch"
3739

@@ -85,7 +87,7 @@ def __init__(self, log, folders: Folders, slurm_header: SlurmHeader, regex: Rege
8587
self.finishdir = f"{folders.results}/{self.name}_{self.now}"
8688
self.db_pusher = DB_Manipulator(log=log, folders=folders, threshold=threshold)
8789
self.concat_files = dict()
88-
self.ref_resolver = Referencer(log=log, folders=folders, threshold=threshold, pubmlst=pubmlst, pasteur=pasteur)
90+
self.ref_resolver = Referencer(log=log, folders=folders, threshold=threshold, pubmlst=pubmlst, pasteur=pasteur, singularity=singularity, containers=containers)
8991

9092
def get_sbatch(self):
9193
"""Returns sbatchfile, slightly superflous"""
@@ -95,11 +97,11 @@ def get_headerargs(self):
9597
headerline = f"-A {self.slurm_header.project} -p {self.slurm_header.type} -n {self.slurm_header.threads} -t {self.slurm_header.time} -J {self.slurm_header.job_prefix}_{self.name} --qos {self.slurm_header.qos} --output {self.finishdir}/slurm_{self.name}.log"
9698
return headerline
9799

98-
def _singularity_exec(self, tool, command):
100+
def _singularity_exec(self, tool: str, command: str) -> str:
99101
"""Return command wrapped with singularity exec for the given tool container."""
100-
sif = self.config["containers"][tool]
101-
binary = self.config["singularity"]["binary"]
102-
bind_list = list(self.config["singularity"].get("bind_paths", []))
102+
sif = getattr(self.containers, tool)
103+
binary = self.singularity.binary
104+
bind_list = list(self.singularity.bind_paths)
103105
if self.finishdir and self.finishdir not in bind_list:
104106
bind_list.append(self.finishdir)
105107
bind = f"--bind {','.join(bind_list)}" if bind_list else ""
@@ -619,6 +621,8 @@ def project_job(self, single_sample=False):
619621
threshold=self.threshold,
620622
pubmlst=self.pubmlst,
621623
pasteur=self.pasteur,
624+
singularity=self.singularity,
625+
containers=self.containers,
622626
sampleinfo=local_sampleinfo,
623627
run_settings=sample_settings,
624628
)

microSALT/utils/referencer.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,21 @@
1212

1313
from Bio import Entrez
1414

15-
from microSALT.config import Folders, Threshold, PubMLSTCredentials, PasteurCredentials
15+
from microSALT.config import Folders, Threshold, PubMLSTCredentials, PasteurCredentials, Singularity, Containers
1616
from microSALT.store.db_manipulator import DB_Manipulator
1717
from microSALT.utils.pubmlst.client import BaseClient, get_client
1818
from microSALT.utils.pubmlst.exceptions import InvalidURLError, PubMLSTError
1919
from microSALT.utils.pubmlst.helpers import get_service_by_url
2020

2121

2222
class Referencer:
23-
def __init__(self, log, folders: Folders, threshold: Threshold, pubmlst: PubMLSTCredentials, pasteur: PasteurCredentials, sampleinfo={}, force=False):
23+
def __init__(self, log, folders: Folders, threshold: Threshold, pubmlst: PubMLSTCredentials, pasteur: PasteurCredentials, singularity: Singularity = None, containers: Containers = None, sampleinfo={}, force=False):
2424
self.folders = folders
2525
self.threshold = threshold
2626
self.pubmlst = pubmlst
2727
self.pasteur = pasteur
28+
self.singularity = singularity or Singularity()
29+
self.containers = containers or Containers()
2830
self.logger = log
2931
self.db_access = DB_Manipulator(log=log, folders=folders, threshold=threshold)
3032
self.updated = list()
@@ -55,11 +57,11 @@ def set_client(self, service: str, database: str = None):
5557
"""Set the client for PubMLST API interactions."""
5658
self.client: BaseClient = get_client(service, database, self.folders, self.pubmlst, self.pasteur)
5759

58-
def _singularity_exec(self, tool, command):
60+
def _singularity_exec(self, tool: str, command: str) -> str:
5961
"""Return command wrapped with singularity exec for the given tool container."""
60-
sif = self.config['containers'][tool]
61-
binary = self.config['singularity']['binary']
62-
bind_list = self.config['singularity'].get('bind_paths', [])
62+
sif = getattr(self.containers, tool)
63+
binary = self.singularity.binary
64+
bind_list = list(self.singularity.bind_paths)
6365
bind = f"--bind {','.join(bind_list)}" if bind_list else ""
6466
return f"{binary} exec {bind} {sif} {command}"
6567

microSALT/utils/scraper.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,15 @@
1010
import sys
1111
import time
1212

13-
from microSALT.config import Folders, Threshold, SlurmHeader, Regex, PubMLSTCredentials, PasteurCredentials
13+
from microSALT.config import Folders, Threshold, SlurmHeader, Regex, PubMLSTCredentials, PasteurCredentials, Singularity, Containers
1414
from microSALT.store.db_manipulator import DB_Manipulator
1515
from microSALT.utils.referencer import Referencer
1616
from microSALT.utils.job_creator import Job_Creator
1717

1818

1919
# TODO: Rewrite so samples use seperate objects
2020
class Scraper:
21-
def __init__(self, log, folders: Folders, threshold: Threshold, slurm_header: SlurmHeader, regex: Regex, dry: bool, config_path: str, pubmlst: PubMLSTCredentials, pasteur: PasteurCredentials, sampleinfo={}, input=""):
21+
def __init__(self, log, folders: Folders, threshold: Threshold, slurm_header: SlurmHeader, regex: Regex, dry: bool, config_path: str, pubmlst: PubMLSTCredentials, pasteur: PasteurCredentials, singularity: Singularity = None, containers: Containers = None, sampleinfo={}, input=""):
2222
self.folders = folders
2323
self.threshold = threshold
2424
self.slurm_header = slurm_header
@@ -27,10 +27,12 @@ def __init__(self, log, folders: Folders, threshold: Threshold, slurm_header: Sl
2727
self.config_path = config_path
2828
self.pubmlst = pubmlst
2929
self.pasteur = pasteur
30+
self.singularity = singularity or Singularity()
31+
self.containers = containers or Containers()
3032
self.logger = log
3133
self.db_pusher = DB_Manipulator(log=log, folders=folders, threshold=threshold)
32-
self.referencer = Referencer(log=log, folders=folders, threshold=threshold, pubmlst=pubmlst, pasteur=pasteur)
33-
self.job_fallback = Job_Creator(log=log, folders=folders, slurm_header=slurm_header, regex=regex, dry=dry, config_path=config_path, threshold=threshold, pubmlst=pubmlst, pasteur=pasteur, sampleinfo=sampleinfo)
34+
self.referencer = Referencer(log=log, folders=folders, threshold=threshold, pubmlst=pubmlst, pasteur=pasteur, singularity=self.singularity, containers=self.containers)
35+
self.job_fallback = Job_Creator(log=log, folders=folders, slurm_header=slurm_header, regex=regex, dry=dry, config_path=config_path, threshold=threshold, pubmlst=pubmlst, pasteur=pasteur, singularity=self.singularity, containers=self.containers, sampleinfo=sampleinfo)
3436
self.infolder = os.path.abspath(input)
3537
self.sampledir = ""
3638

tests/conftest.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@
55
from importlib.resources import files as resource_files
66

77
from microSALT.config import (
8+
Containers,
89
Database,
910
Folders,
1011
MicroSALTConfig,
1112
PasteurCredentials,
1213
PubMLSTCredentials,
1314
Regex,
15+
Singularity,
1416
SlurmHeader,
1517
Threshold,
1618
)
@@ -73,6 +75,8 @@ def config(tmp_path_factory: pytest.TempPathFactory) -> MicroSALTConfig:
7375
threshold=Threshold(),
7476
pubmlst=PubMLSTCredentials(),
7577
pasteur=PasteurCredentials(),
78+
singularity=Singularity(),
79+
containers=Containers(),
7680
)
7781
cfg.folders.expec = str(
7882
resource_files("microSALT").joinpath("unique_references", "ExPEC.fsa")

tests/utils/conftest.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,8 @@ def scraper(config: MicroSALTConfig, logger: logging.Logger, testdata: list[dict
121121
config_path=config.config_path,
122122
pubmlst=config.pubmlst,
123123
pasteur=config.pasteur,
124+
singularity=config.singularity,
125+
containers=config.containers,
124126
sampleinfo=testdata[0],
125127
)
126128

@@ -133,6 +135,8 @@ def init_references(config: MicroSALTConfig, logger: logging.Logger, testdata: l
133135
threshold=config.threshold,
134136
pubmlst=config.pubmlst,
135137
pasteur=config.pasteur,
138+
singularity=config.singularity,
139+
containers=config.containers,
136140
sampleinfo=testdata,
137141
)
138142
ref_obj.identify_new(testdata[0].get("CG_ID_project"), project=True)
@@ -170,6 +174,8 @@ def blast_scraper_context(
170174
config_path=config.config_path,
171175
pubmlst=config.pubmlst,
172176
pasteur=config.pasteur,
177+
singularity=config.singularity,
178+
containers=config.containers,
173179
sampleinfo=testdata[0],
174180
)
175181

0 commit comments

Comments
 (0)