Skip to content

relion: ghostscript is a host-only dependency, so relion_postprocess hard-fails at the end of an otherwise successful run #68838

Description

@scttfrdmn

recipes/relion/meta.yaml lists ghostscript under requirements: host: but not under requirements: run::

  host:
    - libtiff
    - fftw
    - ghostscript      # <-- here
    - libpng
    ...
  run:
    - openmpi
    - llvm-openmp         # [osx]
    - libgomp             # [linux]
    - tbb-devel           # [x86_64]
    - pytorch
                         # <-- not here

ghostscript is a runtime tool dependency, not a library RELION links against — RELION shells out to the gs binary — so a host-only entry means gs is absent in the installed environment. Verified on relion=5.1.0 (build h4615e1f_0, linux-aarch64): gs is not on PATH.

This is not cosmetic. It turns a successful analysis into a non-zero exit.

The failure chain

relion_postprocess finishes its actual work, writes its output maps and postprocess.star, then assembles a PDF log via joinMultipleEPSIntoSinglePDF (src/CPlot2D.cpp:29, RELION 5.1.0):

std::string command = "gs -sDEVICE=pdfwrite -dNOPAUSE -dBATCH -dSAFER ... -sOutputFile=";
...
if (system(command.c_str()))
{
    std::cerr << " ERROR in executing: " << command << "\n";
    have_error_in_gs = true;
}
...
if (!have_at_least_one || have_error_in_gs)
{
    std::cerr << " + Will make an empty PDF-file in " << fn_pdf << "\n";
    touch(fn_pdf);          // <-- fatal when dirname(fn_pdf) does not exist
}

The fallback is meant to degrade gracefully — a missing gs should cost you the PDF and nothing else. But fn_pdf is dirname(--o)/logfile.pdf, and RELION's own documented usage passes a bare output prefix, so that directory does not exist. touch then throws and the process dies:

sh: 1: gs: not found
 ERROR in executing: gs -sDEVICE=pdfwrite -dNOPAUSE -dBATCH -dSAFER -dDEVICEWIDTHPOINTS=800 -dDEVICEHEIGHTPOINTS=800 -sOutputFile=pp/logfile.pdf @pp/logfile.pdf.lst > /dev/null
 + Will make an empty PDF-file in pp/logfile.pdf
 Filename::touch ERROR: Cannot open file: pp/logfile.pdf

Non-zero exit, with correct scientific output already on disk. In any pipeline that checks exit codes — which is all of them — this reads as a failed job.

Reproduction

docker run --rm -it quay.io/biocontainers/relion:5.1.0--h4615e1f_0 bash
# ... obtain two unfiltered half-maps + a mask (e.g. any RELION Refine3D output) ...
relion_postprocess --mask mask.mrc --i run_half1_class001_unfil.mrc \
  --o pp --angpix 0.968 --auto_bfac --autob_lowres 10
echo "exit=$?"     # non-zero
command -v gs      # nothing

The bare prefix --o pp is the trigger, and it is the form RELION's own tutorial and GUI use.

Workaround for anyone who lands here first: pass an absolute --o whose parent exists, e.g. --o /tmp/postprocess. The empty-PDF fallback then lands somewhere writable and the run exits 0. The two gs lines in the log are expected noise in that case, which matters if you grep logs for ERROR.

Fix

Add ghostscript to run: (keeping it in host: is harmless) and bump build: number. It's available for every platform this recipe targets — conda-forge ghostscript 10.07.1 has linux-64, linux-aarch64 (hfae3067_0), osx-64 and osx-arm64 builds, and the recipe declares additional-platforms: [linux-aarch64, osx-arm64], so nothing is left behind.

Worth a look at whether other RELION entry points hit the same path — joinMultipleEPSIntoSinglePDF is in the shared CPlot2D unit, so anything that emits a PDF log is exposed, not just relion_postprocess.

Happy to open the PR if that's easier than doing it inline.


Found while building a reproducible arm64 cryo-EM example (a relion_postprocess run reproducing an archived EMPIAR-10581 result byte-for-byte on Graviton4 — all 221 FSC shells identical, so the science in the image is fine; only the packaging bit us).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions