Skip to content

Commit

Permalink
refactor: create classes for HPC options
Browse files Browse the repository at this point in the history
  • Loading branch information
kelly-sovacool committed Aug 19, 2024
1 parent edc8735 commit f5c9eb6
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 23 deletions.
44 changes: 44 additions & 0 deletions src/ccbr_tools/pipeline/hpc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
from .util import get_hpcname


class Cluster:
def __init__(self):
self.name = None
self.slurm_script = {"nxf": None, "smk": None}
self.modules = {"nxf": None, "smk": None}
self.singularity_sif_dir = None

def __bool__(self):
return bool(self.name)

__nonzero__ = __bool__


class Biowulf(Cluster):
def __init__(self):
super().__init__()
self.name = "biowulf"
self.slurm_script = {
"nxf": "slurm_nxf_biowulf.sh",
"smk": "slurm_smk_biowulf.sh",
}
self.modules = {
"nxf": "ccbrpipeliner nextflow",
"smk": "ccbrpipeliner snakemake/7 singularity",
}
self.singularity_sif_dir = "/data/CCBR_Pipeliner/SIFs"


class FRCE(Cluster):
def __init__(self):
super().__init__()
self.name = "frce"
self.slurm_script = {"nxf": "slurm_nxf_frce.sh", "smk": "slurm_smk_frce.sh"}
self.modules = {"nxf": "nextflow", "smk": "snakemake/7 singularity"}
self.singularity_sif_dir = "/mnt/projects/CCBR-Pipelines/SIFs"


def get_hpc(debug=False):
hpc_options = {"biowulf": Biowulf, "frce": FRCE}
hpc_name = get_hpcname() if not debug else debug
return hpc_options.get(hpc_name, Cluster)()
38 changes: 15 additions & 23 deletions src/ccbr_tools/pipeline/nextflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,31 +8,24 @@
Run a Nextflow workflow.
"""

from ..pkg_util import repo_base, msg_box, use_template
from ..pkg_util import msg_box, use_template
from ..shell import shell_run
from .util import get_hpcname
from .hpc import get_hpc


def run(
nextfile_path=None,
nextflow_args=None,
nextfile_path,
nextflow_args=[],
mode="local",
pipeline_name=None,
debug=False,
hpc_options={
"biowulf": {"profile": "biowulf", "slurm": "slurm_nxf_biowulf.sh"},
"fnlcr": {
"profile": "frce",
"slurm": "slurm_nxf_frce.sh",
},
},
):
"""
Run a Nextflow workflow
Args:
nextfile_path (str, optional): Path to the Nextflow file. Defaults to None.
nextflow_args (list, optional): Additional Nextflow arguments. Defaults to None.
nextfile_path (str, optional): Path to the Nextflow file.
nextflow_args (list, optional): Additional Nextflow arguments. Defaults to an empty list.
mode (str, optional): Execution mode. Defaults to "local".
hpc_options (dict, optional): HPC options. Defaults to {"biowulf": {"profile": "biowulf", "slurm": "assets/slurm_header_biowulf.sh"}, "fnlcr": {"profile": "frce", "slurm": "assets/slurm_header_frce.sh"}}.
Expand All @@ -44,7 +37,7 @@ def run(
"""
nextflow_command = ["nextflow", "run", nextfile_path]

hpc = get_hpcname()
hpc = get_hpc()
if mode == "slurm" and not hpc:
raise ValueError("mode is 'slurm' but no HPC environment was detected")
# add any additional Nextflow commands
Expand All @@ -65,7 +58,7 @@ def run(
if mode == "slurm":
profiles.add("slurm")
if hpc:
profiles.add(hpc_options[hpc]["profile"])
profiles.add(hpc.name)
if (
profiles
): # only add to the profiles if there are any. there are none when champagne is run on GitHub Actions.
Expand All @@ -79,23 +72,22 @@ def run(
if mode == "slurm":
slurm_filename = "submit_slurm.sh"
use_template(
hpc_options[hpc]["slurm"],
output_filepath="submit_slurm.sh",
hpc.slurm_script["nxf"],
output_filepath=slurm_filename,
PIPELINE=pipeline_name if pipeline_name else "CCBR_nxf",
RUN_COMMAND=nextflow_command,
)
with open(slurm_filename, "w") as sbatch_file:
with open(repo_base(hpc_options[hpc]["slurm"]), "r") as template:
sbatch_file.writelines(template.readlines())
sbatch_file.write(nextflow_command)
run_command = f"sbatch {slurm_filename}"
msg_box("Slurm batch job", errmsg=run_command)
elif mode == "local":
if hpc:
nextflow_command = f'bash -c "module load nextflow && {nextflow_command}"'
nextflow_command = (
f'bash -c "module load {hpc.modules} && {nextflow_command}"'
)
run_command = nextflow_command
else:
raise ValueError(f"mode {mode} not recognized")

# Run Nextflow
shell_run(run_command, capture_output=False)
if not debug:
shell_run(run_command, capture_output=False)
32 changes: 32 additions & 0 deletions tests/test_hpc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
from ccbr_tools.pipeline.hpc import get_hpc


def test_hpc_biowulf():
hpc = get_hpc(debug="biowulf")
assert all(
[
hpc,
hpc.name == "biowulf",
hpc.slurm_script
== {"nxf": "slurm_nxf_biowulf.sh", "smk": "slurm_smk_biowulf.sh"},
hpc.singularity_sif_dir == "/data/CCBR_Pipeliner/SIFs",
]
)


def test_hpc_frce():
hpc = get_hpc(debug="frce")
assert all(
[
hpc,
hpc.name == "frce",
hpc.slurm_script
== {"nxf": "slurm_nxf_frce.sh", "smk": "slurm_smk_frce.sh"},
hpc.singularity_sif_dir == "/mnt/projects/CCBR-Pipelines/SIFs",
]
)


def test_hpc_none():
hpc = get_hpc(debug="")
assert not any([hpc, hpc.name, *hpc.slurm_script.values(), hpc.singularity_sif_dir])
8 changes: 8 additions & 0 deletions tests/test_nextflow.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
from ccbr_tools.pipeline.nextflow import run
from ccbr_tools.shell import exec_in_context


def test_nextflow_basic():
assert "nextflow run CCBR/CHAMPAGNE" in exec_in_context(
run, "CCBR/CHAMPAGNE", debug=True
)

0 comments on commit f5c9eb6

Please sign in to comment.