Skip to main content

Nexus Snakemake utilities

Shared workflow infrastructure for Python 3.11+ on Linux/macOS, targeting Snakemake 8.14. Newer Snakemake versions are allowed but remain unverified. Install the PyPI release into the Python/Conda environment that runs Snakemake:

python -m pip install "nexus-snakemake-utils==0.2.0"

For an existing conda environment, installation also works without activation:

snakemake_env_dir="/absolute/path/to/snakemake_v8.14.0"
conda run --prefix "$snakemake_env_dir" python -m pip install \
  "nexus-snakemake-utils==0.2.0" "snakemake==8.14.0"
conda run --prefix "$snakemake_env_dir" python -m pip check

Include pip when creating the conda environment; install the conda packages first and the utils afterwards. The explicit Snakemake constraint in this example retains the tested version; the utils package itself allows Snakemake >=8.14.

To install directly from the GitHub release tag instead:

python -m pip install 'nexus-snakemake-utils @ git+https://github.com/ETH-NEXUS/nexus_snakemake_utils.git@v0.2.0'

The package installs controller dependencies. Analysis tools and R dependencies must be supplied separately by your workflow.

Portability

Nexus/Leomed access and Slurm are not required. The supported environment is Linux/macOS with Python 3.11+ and Snakemake 8.14 as the tested target. Packaging requires snakemake>=8.14 without an upper bound; this permits Snakemake 9 but does not establish compatibility. Validation of newer versions is deferred. Core utilities and benchmark reports work with the local executor. Slurm accounting is queried only for Slurm runs; missing accounting tools or records produce warnings without failing the workflow. Container usage registration skips runtimes without the proxy interface.

The optional container proxy uses Unix file locking and requires a real Singularity/Apptainer runtime for container execution. Its singularity launcher is installed with this package and must find the real runtime later on PATH or through SNAKEMAKE_REAL_SINGULARITY. Set an image directory with --image-dir or LEOMED_SNAKEMAKE_IMAGE_DIR when using its image-cache commands. The variable name does not require Leomed storage; mirror mappings are optional. Keep cluster paths, accounts and binds in site profiles, and publish a local profile too.

Reporting libraries are installed as package dependencies even if reporting is unused. Analysis tools and report-rendering software remain workflow dependencies.

Workflow interface

import nexus_snakemake_utils as utils
# Top level of the Snakefile: runs during parsing, including dry runs.
# Preserve an explicit container workflow label, otherwise use the repository
# name; then log time, user, host, Git revision/checkout state and Snakemake version.
utils.initialize(repository_dir)

onstart:
    utils.register_container_usage(workflow)
onsuccess:
    utils.write_resource_report(workflow)
onerror:
    utils.write_resource_report(workflow, partial=True)

initialize preserves an explicit SNAKEMAKE_CONTAINER_WORKFLOW label and otherwise sets it to the repository name, then calls log_run_info. It does not register container usage, execute jobs, or write resource reports. Keep it at the top level of the Snakefile so logging also runs for dry runs. Parsing-time messages are buffered until Snakemake opens its execution log, so provenance appears once in both the terminal and .snakemake/log/. Dry runs retain terminal output without creating an execution log.

Select optional inputs or targets with optional(val, on, dpath=None):

rule all:
    input:
        utils.optional(rules.report.output.html, config, dpath="optional/report"),

This returns val unchanged when the flag is truthy, otherwise []. Omit dpath to pass a flag directly, for example utils.optional(targets, enabled). Config paths use dpath syntax; missing or ambiguous paths raise errors. Define flags explicitly in the base configuration (for example optional: {report: false}) and enable them through overlays. Values are evaluated before calling the helper; use lazy input functions when resolving a value itself requires optional files.

Derive a directory from a resolved output without a lambda:

params:
    outdir=utils.dirname("events", index=0),  # output.events[0]

dirname("quant") selects a single named output; dirname() uses output[0]. It preserves os.path.dirname semantics, including "" for a bare filename.

Plain lookup(...) runs while loading rules unless its query/path needs wildcards. Use lazylookup in input or params so unused rules do not require their settings:

params:
    extra=utils.lazylookup(dpath="rule_specific/tool/extra", within=config),

It accepts Snakemake's lookup arguments, including defaults and wildcard paths. Missing required keys still fail when the job is evaluated, including during dry runs. transform=shlex.split can convert an option string after lookup. Arguments are still evaluated when calling the factory: pass within=config, not an eager lookup of an optional subsection. Use ordinary lookup for load-time setup, output paths and Python conditions; a callable itself is always truthy.

Pass a configuration branch to a script as JSON and extend it with other settings:

params:
    report_config=utils.json_dumps(
        within=config,
        base="rule_specific/de_analysis",
        tx2gene="resources/tx2gene",
        gene_info="resources/gene_info",
    ),

json_dumps returns a callable. It copies the base mapping, applies output-path → input-path mappings in keyword order, then serializes the result. Omit base to start with {}. Additional mappings override existing values; nested output paths use **{"references/tx2gene": "resources/tx2gene"}. Source paths support Snakemake wildcards. All lookups happen at job evaluation; missing paths and a non-mapping base raise errors. The original configuration is never modified.

Register system limits once in workflow/rules/misc.smk:

limits = utils.ResourceLimits(
    memory_mb=lookup(dpath="resources/max_mem_mb", within=config),
    runtime_minutes=lookup(dpath="resources/max_minutes", within=config),
)

Both limits must be positive integers. Each instance holds its own immutable limits. Use its callable factories in each rule's resources block:

resources:
    mem_mb=limits.memory_by_input(
        base_mem_mb=2000,
        mem_per_input_mb=2,
    ),
    runtime=limits.runtime_by_input(
        base_minutes=5,
        minutes_per_gib=1,
    ),

Keep system limits in configuration and use lookup without defaults so missing required settings fail clearly. These limits cap estimates made through the object; fixed resource requests in rules and scheduler limits are separate. The standalone utils.memory_by_input and utils.runtime_by_input factories remain available with an explicit maximum. The factory captures the coefficients and limit during parsing, then returns a function accepting wildcards and input. Snakemake evaluates that function when the job's inputs are available; missing inputs remain <TBD> during dry runs. Memory is ceil(base_mem_mb + mem_per_input_mb * input.size_mb); runtime is ceil(base_minutes + minutes_per_gib * input.size_mb / 1024), each capped at its maximum. Estimates apply to the whole job, not per thread.

Snakemake 8.14 resource functions receive no params or other resource values. Keep resource coefficients here or in workflow configuration, rather than introducing artificial scheduler resources. The lower-level dynamic_mem_mb and dynamic_runtime functions remain available for direct numeric estimates. Metadata loading and scientific validation stay in the workflow.

external_path(value, label, repository_dir) resolves a path against the current run directory and rejects the repository itself and its descendants, including paths that resolve into it through symlinks. It returns an absolute Path without requiring that the file exists. Pass the repository boundary explicitly:

sample_sheet = utils.external_path(
    config["sample_sheet"], "Sample sheet", repository_dir=repository_dir
)

Enable benchmark-extended: true in execution profiles to record job metadata and historical input sizes. The resource report uses those values when available, compares requested and measured resources, and exports measurements.tsv; ordinary benchmarks remain supported. nexus-resource-report --help describes standalone inspection of existing benchmark outputs. See resource reporting. The success and failure hooks retain existing outputs and accounting semantics; missing site services are reported as warnings.

Singularity image proxy

Installation exposes singularity in the environment. Ensure that environment's bin precedes the real runtime on PATH. Discovery skips this launcher; set SNAKEMAKE_REAL_SINGULARITY=/absolute/path/to/real/singularity when needed. Do not point it at the proxy. Native Apptainer can be supplied through this variable too.

export LEOMED_SNAKEMAKE_IMAGE_DIR=/path/to/shared/images
export SNAKEMAKE_CONTAINER_PROXY_CONFIG=/path/to/site/container-proxies.json
singularity list
singularity list '*samtools*'
singularity locate docker://python:3.14
singularity rm 'docker://python:3.14*'
singularity pull docker://python:3.14
singularity exec docker://python:3.14 python --version
singularity --image-dir /another/cache list

To persist the proxy configuration path for a Conda environment:

conda env config vars set --prefix /path/to/env \
  SNAKEMAKE_CONTAINER_PROXY_CONFIG=/path/to/site/container-proxies.json

Reactivate the environment afterward. Image pulls warn on stderr when the proxy configuration variable is unset or its JSON mapping is empty; direct pulls remain allowed. Version checks and other native commands stay quiet.

Use the same image directory variable in a Snakemake profile:

apptainer-prefix: "$LEOMED_SNAKEMAKE_IMAGE_DIR"

An explicit --image-dir before the command or among its leading options wins over the environment. Listing and URL resolution require a location; local image paths and unrelated native commands do not. Quote URL globs to prevent shell expansion. list prints downloaded URLs, paths and usage metadata as TSV, omitting missing files and showing unmapped .simg files with URL unknown. It does not modify the manifest. locate prints only an existing absolute path.

rm URL-GLOB removes cached images matching the same original URL patterns as list, using the same per-image locks as pulls. Quote patterns, for example singularity rm '*python*'. An explicit URL or pattern is required; no matches return an error. Inventory history is retained and deleted images are marked missing. As with list, '*' includes images whose URL is unknown. Remove shared images only when no jobs are using them. This command does not clean the runtime's separate layer cache. Other native commands, including cache, instance and help, continue to pass through unchanged; rm inside container commands is also unaffected.

exec, run and shell resolve the image operand only. URLs in runtime option values or in the container's arguments are preserved. Runtime help supplies option arity, supporting the installed runtime's flags. Local paths and instance:// references pass through unchanged. Missing URL images fail with an explicit pull command; execution never downloads implicitly. Usage denotes an execution attempt, not successful completion. Mutable tags reuse their existing image until an explicit forced pull.

Unnamed pulls write <md5(exact-original-url)>.simg under the selected directory. Explicit filenames and Snakemake's pull --name ... retain their original output location. Mirror rewriting never changes the hash. Keep URLs exactly consistent; registry aliases are not normalized. Use an explicit destination for sandbox pulls. The proxy records file-backed images in container_list.tsv, retaining the existing schema, per-image locks, atomic manifest updates and per-workflow usage timestamps.

Proxy mappings are an optional JSON object of source prefixes to replacements. Longest prefix wins. The generic docker:// mapping applies to Docker Hub while preserving explicit other registries. Without configured mappings, URLs pass through unchanged. Keep site addresses in site configuration, outside this package.

Native commands, including cache list, pass through. This workflow image store is separate from the runtime's layer cache. Existing --proxy-capabilities, --proxy-register, --proxy-real-runtime and --proxy-audit DIRECTORY interfaces remain supported. Audit refreshes presence information and discovers unmapped images; it does not recover their original URLs.

For contributing, validation and releases, see the separate developer guide.

Metadata

Release files for nexus-snakemake-utils 0.3.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for nexus-snakemake-utils 0.3.0
File Size Uploaded Provenance
nexus_snakemake_utils-0.3.0.tar.gz 29.7 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for nexus-snakemake-utils 0.3.0
File Interpreter ABI Platform
nexus_snakemake_utils-0.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 57.0 kB

Release files / nexus_snakemake_utils-0.3.0.tar.gz

Download URL nexus_snakemake_utils-0.3.0.tar.gz
Size 29.7 kB
Tags Source
SHA-256 checksum
How to use checksums
062be7ae3db63029bfa317adccac64bff9bacb05f8217b81612c8e4db440530c
BLAKE2b-256 checksum
How to use checksums
5959475d400b0e919793c3adf25d0b94dc54197a44ccf21548abe05d4e3bbd44
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.2

Release files / nexus_snakemake_utils-0.3.0-py3-none-any.whl

Download URL nexus_snakemake_utils-0.3.0-py3-none-any.whl
Size 27.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
0e3b81db00107206fb3e78a59287915963a8a97821155fc98d0b583e5d212211
BLAKE2b-256 checksum
How to use checksums
03fbeaf83f02884baf06e908344c3bea2b2417fc4cd67e0280d14e2e1e59e47a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.2

Security for nexus-snakemake-utils 0.3.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Release history Release notifications | RSS feed

This release

0.3.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page