The workspace¶
A workspace is the directory scfoundry init prepares. It holds everything a run needs and
everything a run produces, so that a project can be moved, shared or deleted as one unit.
What init creates¶
my_project/
├── .scfoundry.json marker: scfoundry version, pipeline path, container runtime
├── nextflow.config container runtime, GPU pinning, paths — edit freely
├── data/model_weights/ checkpoints, filled by `scfoundry download`
├── cache/ container images, the container's HOME, Nextflow caches
├── results/ published outputs
└── runs/ one directory per launch (created on the first run)
nextflow.config is written from a template bundled with the package, with the container
runtime init detected switched on. It is yours: nothing overwrites it later (rerun
scfoundry init --force if you want a fresh copy).
How commands find the workspace¶
Every task command looks for a workspace in this order:
--workspace DIRon the command line;the
SCFOUNDRY_WORKSPACEenvironment variable;the current directory and its parents, stopping at the first one that contains
.scfoundry.json— the waygitfinds a repository.
So cd my_project (or any directory below it) is all it takes. scfoundry info prints
which workspace and configuration file are in effect.
Note
Several workspaces can share one copy of the weights and one image cache. Either pass
--weights-dir and --cache-dir on each command, or set model_weights_dir and
cache_dir in the workspace nextflow.config — see below.
nextflow.config¶
The file is annotated in full in the nextflow.config reference. The settings you are likely to touch:
Container runtime¶
Exactly one of the docker, singularity and apptainer blocks has enabled = true.
init sets it from what it finds; to change your mind:
scfoundry init --force --runtime docker .
or flip the enabled flags by hand. Do not delete the blocks — they carry the bind-mount
options each runtime needs.
GPU¶
gpu_id = null exposes every GPU on the machine. Pin one device per run with --gpu:
scfoundry embed --method scgpt --data demo/colon_1000.h5ad --gpu 0
or permanently, in the params block:
params {
gpu_id = 0
}
Tip
On a multi-GPU machine, pin a run to one device with --gpu 0. Without it, Docker gets
--gpus=all and Apptainer gets --nv with no CUDA_VISIBLE_DEVICES, so the job may land
on a card someone else is using. To make it permanent, set gpu_id in the workspace
nextflow.config.
Paths¶
Parameter |
Default |
What it controls |
|---|---|---|
|
|
Bind-mounted at |
|
|
Container images land in |
|
|
A stand-in |
The per-run equivalents are --weights-dir and --cache-dir; they take precedence over
the file.
Work directories and --resume¶
The template sets cleanup = true: Nextflow deletes a task’s work directory once the run
has succeeded. Work directories are large (every task stages its inputs), and the
outputs you want are already published under results/.
Note
Every launch gets its own run directory under runs/<task>/, and the workspace
nextflow.config sets cleanup = true, so the task work directory is deleted once the run
succeeds. After a failure it is kept: fix the cause, add --resume to the same command,
and Nextflow reuses every task that already completed. scfoundry runs lists the run
directories with their status; scfoundry runs --task <task> narrows the list.
Scheduler profiles¶
The template ends with a commented profiles { slurm { ... } } block. Uncomment it, adapt
the queue names, and every process is submitted as its own job when you add
--profile slurm to a command. Details on Running on an HPC cluster.
For one-off changes, keep a separate file and layer it on with --config extra.config
rather than editing the workspace file.
Runs¶
Every launch gets its own directory:
runs/embed/20260828-162920_scgpt_colon_1000/
├── params.json the parameters handed to Nextflow
├── command.sh the exact command, re-runnable
├── run.json task, method, input, timestamps, exit code, versions
├── nextflow.log the full Nextflow log
├── .nextflow/ Nextflow's cache database (what -resume uses)
└── work/ task work directories, removed on success
The name is <timestamp>_<method>_<input>; --run-name NAME chooses it yourself. Because
runs are isolated, several tasks can run in one workspace at the same time.
scfoundry runs --limit 5
started task method status exit run directory
2026-08-28T20:33:41 benchmark pca ok 0 runs/benchmark/20260828-203341_pca_pca
2026-08-28T20:23:44 benchmark scgpt ok 0 runs/benchmark/20260828-202344_scgpt_colon_1000
2026-08-28T20:10:12 finetune scgpt ok 0 runs/finetune/20260828-201012_scgpt_colon_50
2026-08-28T18:19:09 transfer scgpt ok 0 runs/transfer/20260828-181909_scgpt_liver_1shot_query
2026-08-28T16:29:20 embed scgpt ok 0 runs/embed/20260828-162920_scgpt_colon_1000
A failed run keeps its work/. Rerun the same command with --resume and Nextflow reuses
every task that already finished; --resume NAME targets a specific run directory.
--dry-run shows the parameter file and the Nextflow command without launching anything —
the quickest way to check what a set of options resolves to:
scfoundry embed --method scgpt --data demo/colon_1000.h5ad --gpu 0 --batch_size 32 --dry-run
[scfoundry] warning: forwarding unrecognised option(s) to Nextflow as parameters: --batch_size=32
[scfoundry] dry run -- workspace /home/you/my_project
[scfoundry] would create /home/you/my_project/runs/embed/20260828-225931_scgpt_colon_1000
params.json:
{
"task": "embed",
"method": "scgpt",
"data": "/home/you/my_project/demo/colon_1000.h5ad",
"emb_results_dir": "/home/you/my_project/results",
"gpu_id": "0",
"batch_size": 32
}
command (cwd = run directory; env SCFOUNDRY_WORKSPACE=/home/you/my_project NXF_SYNTAX_PARSER=v1):
/home/you/.conda/envs/nf-env/bin/nextflow -log nextflow.log run .../scfoundry/pipeline/main.nf -params-file params.json -work-dir work -ansi-log false
Results¶
Outputs are published under results/ by default; --outdir DIR redirects a run. The
layout is the same for every method — see the output reference.
See also
Command reference — every option shared by the task commands.
nextflow.config reference — the configuration file, line by line.