Skip to content

Commit

Permalink
Add slurm support
Browse files Browse the repository at this point in the history
  • Loading branch information
marcelzwiers committed Oct 27, 2023
1 parent 7d3a862 commit ee9b932
Show file tree
Hide file tree
Showing 4 changed files with 22 additions and 15 deletions.
13 changes: 9 additions & 4 deletions bidscoin/bidsapps/skullstrip.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
from bidscoin import bcoin, bids, lsdirs, trackusage


def skullstrip(bidsdir: str, pattern: str, subjects: list, masked: str, output: list, force: bool, args: str, cluster: bool):
def skullstrip(bidsdir: str, pattern: str, subjects: list, masked: str, output: list, force: bool, args: str, cluster: str):
"""
:param bidsdir: The bids-directory with the subject data
:param pattern: Globlike search pattern (relative to the subject/session folder) to select the images that need to be skullstripped, e.g. 'anat/*_T1w*'
Expand All @@ -25,7 +25,7 @@ def skullstrip(bidsdir: str, pattern: str, subjects: list, masked: str, output:
:param masked: Globlike search pattern (relative to the subject/session folder) to select additional images that need to be masked with the same mask, e.g. 'fmap/*_phasediff')
:param output: One or two output strings that determine where the skullstripped + additional masked images are saved. Each output string can be the name of a BIDS datatype folder, such as 'anat', or of the derivatives folder, i.e. 'derivatives' (default). If the output string is the same as the datatype then the original images are replaced by the skullstripped images
:param args: Additional arguments that are passed to synthstrip. See examples for usage
:param cluster: Use qsub to submit the skullstrip jobs to a high-performance compute (HPC) cluster
:param cluster: Use `torque` or `slurm` to submit the skullstrip jobs to a high-performance compute (HPC) cluster. Leave empty to run skullstrip on your local computer
:return:
"""

Expand Down Expand Up @@ -112,8 +112,13 @@ def skullstrip(bidsdir: str, pattern: str, subjects: list, masked: str, output:
maskimg = bidsdir/'derivatives'/'skullstrip'/subid/sesid/srcimg.parent.name/f"{srcent}_{derent}_mask{ext}"
maskimg.parent.mkdir(parents=True, exist_ok=True)
command = f"mri_synthstrip -i {srcimg} -o {outputimg} -m {maskimg} {args}"
if cluster:
command = f"qsub -l walltime=0:05:00,mem=8gb -N skullstrip_{subid}_{sesid} <<EOF\n{command}\nEOF"
if cluster == 'torque':
command = f"qsub -l walltime=0:05:00,mem=8gb -N skullstrip_{subid}_{sesid} << EOF\n{command}\nEOF"
elif cluster == 'slurm':
command = f"sbatch --time=0:05:00 --mem=8G --job-name=skullstrip_{subid}_{sesid} << EOF\n{command}\nEOF"
elif cluster:
LOGGER.error(f"Invalid cluster manager `{cluster}`")
exit(1)
if bcoin.run_command(command):
continue

Expand Down
20 changes: 11 additions & 9 deletions bidscoin/bidsapps/slicereport.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ def parse_outputs(outputargs: list, name: str) -> tuple:
return outputs, slices


def slicer_append(inputimage: Path, outlineimage: Path, mainopts: str, outputopts: str, sliceroutput: str, montage: Path, cluster: bool):
def slicer_append(inputimage: Path, outlineimage: Path, mainopts: str, outputopts: str, sliceroutput: str, montage: Path, cluster: str):
"""Run slicer and pngappend (locally or on the cluster) to create a montage of the sliced images"""

# Create a workdir and the shell command
Expand All @@ -86,12 +86,14 @@ def slicer_append(inputimage: Path, outlineimage: Path, mainopts: str, outputopt
f"rm -r {workdir}"

# Wrap the command
if cluster:
if inputimage.stat().st_size > 50 * 1024**2:
mem = '8gb' # Ask for more resources if we have a large (e.g. 4D) input image
else:
mem = '1gb'
command = f"qsub -l walltime=0:02:00,mem={mem} -N slicereport -e {tempfile.gettempdir()} -o {tempfile.gettempdir()}<<EOF\n{command}\nEOF"
mem = '8' if inputimage.stat().st_size > 50 * 1024**2 else '1' # Ask for more resources if we have a large (e.g. 4D) input image
if cluster == 'torque':
command = f"qsub -l walltime=0:02:00,mem={mem}gb -N slicereport -e {tempfile.gettempdir()} -o {tempfile.gettempdir()} << EOF\n{command}\nEOF"
elif cluster == 'slurm':
command = f"sbatch --time=0:02:00 --mem={mem}G --job-name slicereport -o {tempfile.gettempdir()}/slurm-%j.out << EOF\n{command}\nEOF"
elif cluster:
LOGGER.error(f"Invalid cluster manager `{cluster}`")
exit(1)

# Run the command
LOGGER.bcdebug(f"Command: {command}")
Expand All @@ -102,7 +104,7 @@ def slicer_append(inputimage: Path, outlineimage: Path, mainopts: str, outputopt
sys.exit(process.returncode)


def slicereport(bidsdir: str, pattern: str, outlinepattern: str, outlineimage: str, subjects: list, reportdir: str, crossdirs: str, qccols: list, cluster: bool, options: list, outputs: list, suboptions: list, suboutputs: list):
def slicereport(bidsdir: str, pattern: str, outlinepattern: str, outlineimage: str, subjects: list, reportdir: str, crossdirs: str, qccols: list, cluster: str, options: list, outputs: list, suboptions: list, suboutputs: list):
"""
:param bidsdir: The bids-directory with the subject data
:param pattern: Globlike search pattern to select the images in bidsdir to be reported, e.g. 'anat/*_T1w*'
Expand All @@ -112,7 +114,7 @@ def slicereport(bidsdir: str, pattern: str, outlinepattern: str, outlineimage: s
:param reportdir: The folder where the report is saved
:param crossdirs: A (list of) folder(s) with cross-linked sub-reports
:param qccols: Column names for creating an accompanying tsv-file to store QC-rating scores
:param cluster: Use qsub to submit the slicer jobs to a high-performance compute (HPC) cluster
:param cluster: Use `torque` or `slurm` to submit the slicer jobs to a high-performance compute (HPC) cluster. Leave empty to run slicer on your local computer
:param options: Slicer main options
:param outputs: Slicer output options
:param suboptions: Slicer main options for creating the sub-reports (same as OPTIONS)
Expand Down
2 changes: 1 addition & 1 deletion bidscoin/cli/_skullstrip.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,6 @@ class CustomFormatter(argparse.ArgumentDefaultsHelpFormatter, argparse.RawDescri
parser.add_argument('-o','--output', help="One or two output strings that determine where the skullstripped + additional masked images are saved. Each output string can be the name of a BIDS datatype folder, such as 'anat', or of the derivatives folder, i.e. 'derivatives' (default). If the output string is the same as the datatype then the original images are replaced by the skullstripped images", nargs='+')
parser.add_argument('-f','--force', help="Process images, regardless whether images have already been skullstripped (i.e. if {'SkullStripped': True} in the json sidecar file)", action='store_true')
parser.add_argument('-a','--args', help="Additional arguments that are passed to synthstrip (NB: Use quotes and a leading space to prevent unintended argument parsing)", type=str, default='')
parser.add_argument('-c','--cluster', help='Use `qsub` to submit the skullstrip jobs to a high-performance compute (HPC) cluster. Can only be used if `--masked` is left empty', action='store_true')
parser.add_argument('-c','--cluster', help='Use `torque` or `slurm` to submit the skullstrip jobs to a high-performance compute (HPC) cluster. Can only be used if `--masked` is left empty', choices=['torque','slurm'])

return parser
2 changes: 1 addition & 1 deletion bidscoin/cli/_slicereport.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ def get_parser():
parser.add_argument('-r','--reportfolder', help="The folder where the report is saved (default: bidsfolder/derivatives/slicereport)")
parser.add_argument('-x','--xlinkfolder', help="A (list of) QC report folder(s) with cross-linkable sub-reports, e.g. bidsfolder/derivatives/mriqc", nargs='+')
parser.add_argument('-q','--qcscores', help="Column names for creating an accompanying tsv-file to store QC-rating scores (default: rating_overall)", default=['rating_overall'], nargs='+')
parser.add_argument('-c','--cluster', help='Use `qsub` to submit the slicer jobs to a high-performance compute (HPC) cluster', action='store_true')
parser.add_argument('-c','--cluster', help='Use `torque` or `slurm` to submit the skullstrip jobs to a high-performance compute (HPC) cluster', choices=['torque','slurm'])
parser.add_argument('--options', help='Main options of slicer (see below). (default: "s 1")', default=['s','1'], nargs='+')
parser.add_argument('--outputs', help='Output options of slicer (see below). (default: "x 0.4 x 0.5 x 0.6 y 0.4 y 0.5 y 0.6 z 0.4 z 0.5 z 0.6")', default=['x','0.4','x','0.5','x','0.6','y','0.4','y','0.5','y','0.6','z','0.4','z','0.5','z','0.6'], nargs='+')
parser.add_argument('--suboptions', help='Main options of slicer for creating the sub-reports (same as OPTIONS, see below). (default: OPTIONS)', nargs='+')
Expand Down

0 comments on commit ee9b932

Please sign in to comment.