diff --git a/modules/nf-core/vuegen/Dockerfile b/modules/nf-core/vuegen/Dockerfile new file mode 100644 index 000000000000..5caf60567ae3 --- /dev/null +++ b/modules/nf-core/vuegen/Dockerfile @@ -0,0 +1,52 @@ +# Set the base image to the official Python 3.12 slim debian trixie image +FROM python:3.12-slim-trixie + + +# Disable manual feedback for apt-get, update package list, install security updates, +# and install packages (procps, and system dependencies for tinytex and kaleido). +# Then clean up the package list and remove the cache. +RUN export DEBIAN_FRONTEND=noninteractive && \ + apt-get update && \ + apt-get -y upgrade && \ + apt-get install -y --no-install-recommends \ + procps=2:4.0.4-9 \ + wget=1.25.0-2 \ + perl=5.40.1-6 \ + # #2.84.4-3~deb13u1 + libglib2.0-0t64=2.84.4-3~deb13u1 \ + libgdk-pixbuf-2.0-0=2.42.12+dfsg-4 \ + libfontconfig1=2.15.0-2.3 \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +# Install vuegen Python package +RUN pip install --no-cache-dir -U vuegen==0.5.1 + +# Create and switch to non-root user for security reasons +RUN useradd --create-home appuser +USER appuser + +# Set the working directory +WORKDIR /home/appuser + +# Install TinyTeX for pdf reports +SHELL ["/bin/bash", "-o", "pipefail", "-c"] +RUN perl -mFile::Find /dev/null && \ + wget -qO- "https://yihui.org/tinytex/install-bin-unix.sh" | sh && \ + ~/.TinyTeX/bin/*/tlmgr \ + install \ + koma-script \ + caption \ + luaotfload + +# Set permissions for the appuser home directory +RUN chmod -R 777 /home/appuser + +# Set environment variables for Quarto, dataframe_image, and TinyTeX. Also, get tracebacks from C crashes +ENV XDG_RUNTIME_DIR=/tmp \ + XDG_CACHE_HOME=/tmp/quarto_cache_home \ + XDG_DATA_HOME=/tmp/quarto_data_home \ + PATH="${PATH}:/home/appuser/bin" \ + TEXMFVAR=/tmp/texmf-var \ + TEXMFHOME=/tmp/texmf-home \ + PYTHONFAULTHANDLER=1 diff --git a/modules/nf-core/vuegen/README.md b/modules/nf-core/vuegen/README.md new file mode 100644 index 000000000000..ce103444a43d --- /dev/null +++ b/modules/nf-core/vuegen/README.md @@ -0,0 +1,22 @@ +# VueGen Module + +## Dockerimage + +The dockerimage is needed as both quarto and the TinyTeX distribution are installed +inside the container to make vuegen work properly. At runtime especially apptainer +does not support installing packages on the fly to read-only directories. + +```bash +#!/bin/bash +set -euo pipefail + +ORG="quay.io/nf-core" +VERSION="v0.5.1" + +# 1. Build & push the base image (nextflow version) +docker buildx build \ + --platform linux/amd64,linux/arm64 \ + --push \ + -t ${ORG}/vuegen:${VERSION} \ + -f Dockerfile . +``` diff --git a/modules/nf-core/vuegen/environment.yml b/modules/nf-core/vuegen/environment.yml index 8eab2a170585..6dee2d2d963d 100644 --- a/modules/nf-core/vuegen/environment.yml +++ b/modules/nf-core/vuegen/environment.yml @@ -4,5 +4,5 @@ channels: - bioconda - conda-forge dependencies: - - bioconda::vuegen=0.3.2 - - python=3.11 + - python=3.12 + - vuegen=0.5.1 diff --git a/modules/nf-core/vuegen/main.nf b/modules/nf-core/vuegen/main.nf index ddc333fe5859..409ba207c46c 100644 --- a/modules/nf-core/vuegen/main.nf +++ b/modules/nf-core/vuegen/main.nf @@ -1,23 +1,23 @@ process VUEGEN { label 'process_single' conda "${moduleDir}/environment.yml" - container "dtu_biosustain_dsp/vuegen:v0.3.2-nextflow" + container "nf-core/vuegen:0.5.1" input: - val input_type - path input_path - val report_type + val input_type + path input_path + val report_type output: - path "*report", emit: output_folder - path "versions.yml", emit: versions + path "*report", emit: output_folder + path "versions.yml", emit: versions when: - task.ext.when == null || task.ext.when + task.ext.when == null || task.ext.when script: - def args = task.ext.args ?: '' - """ + def args = task.ext.args ?: '' + """ # Validate quarto_check flag if using a conda environment if [[ "${task.conda}" != "null" ]]; then QUARTO_CHECK_FLAG="--quarto_checks" @@ -27,28 +27,28 @@ process VUEGEN { # Execute VueGen based on the input type if [ "${input_type}" == "config" ]; then - echo "Running VueGen with config file: $input_path" - vuegen --config $input_path --report_type $report_type \$QUARTO_CHECK_FLAG $args + echo "Running VueGen with config file: ${input_path}" + vuegen --config ${input_path} --report_type ${report_type} \$QUARTO_CHECK_FLAG ${args} elif [ "${input_type}" == "directory" ]; then - echo "Running VueGen with directory: $input_path" - vuegen --directory $input_path --report_type $report_type \$QUARTO_CHECK_FLAG $args + echo "Running VueGen with directory: ${input_path}" + vuegen --directory ${input_path} --report_type ${report_type} \$QUARTO_CHECK_FLAG ${args} fi cat <<-END_VERSIONS > versions.yml "${task.process}": - vuegen: \$( vuegen --version | sed -e "s/vuegen //g" ) + vuegen: \$( python -c "import vuegen; print(vuegen.__version__)" ) END_VERSIONS """ stub: - """ + """ echo "STUB MODE: Creating a generic report directory" mkdir -p report touch report/report.txt cat <<-END_VERSIONS > versions.yml "${task.process}": - vuegen: \$( vuegen --version | sed -e "s/vuegen //g" ) + vuegen: \$( python -c "import vuegen; print(vuegen.__version__)" ) END_VERSIONS """ } diff --git a/modules/nf-core/vuegen/tests/main.nf.test b/modules/nf-core/vuegen/tests/main.nf.test index b11ba33f9ac3..40f7c7938f28 100644 --- a/modules/nf-core/vuegen/tests/main.nf.test +++ b/modules/nf-core/vuegen/tests/main.nf.test @@ -49,7 +49,7 @@ nextflow_process { "Static_Plots.py": path(process.out.output_folder[0] + "/sections/Plots/Static_Plots.py") .readLines()[0..3].sort().join('\n').md5() ], - versions: process.out.versions + versions: path(process.out.versions[0]).yaml, ]).match() } ) @@ -80,7 +80,7 @@ nextflow_process { "quarto_report.qmd": path(process.out.output_folder[0] + "/quarto_report.qmd") .readLines()[0..3].join('\n').md5() ], - versions: process.out.versions + versions: path(process.out.versions[0]).yaml ]).match() } ) @@ -111,7 +111,7 @@ nextflow_process { "quarto_report.qmd": path(process.out.output_folder[0] + "/quarto_report.qmd") .readLines()[0..3].sort().join('\n').md5() ], - versions: process.out.versions + versions: path(process.out.versions[0]).yaml, ]).match() } ) @@ -138,7 +138,7 @@ nextflow_process { assert snapshot( process.out.output_folder.collect { file(it).getName() } + process.out.output_files.collect { file(it).getName() }, - versions: process.out.versions + versions: path(process.out.versions[0]).yaml, ).match() } ) diff --git a/modules/nf-core/vuegen/tests/main.nf.test.snap b/modules/nf-core/vuegen/tests/main.nf.test.snap index ba5f6682404c..ea03a715d364 100644 --- a/modules/nf-core/vuegen/tests/main.nf.test.snap +++ b/modules/nf-core/vuegen/tests/main.nf.test.snap @@ -2,9 +2,11 @@ "vuegen - directory (HTML report) -stub": { "content": [ { - "versions": [ - "versions.yml:md5,c3e7ebc433dcacf3d15e1113fd44f5ec" - ] + "versions": { + "VUEGEN": { + "vuegen": "0.5.1" + } + } }, [ "report" @@ -12,9 +14,9 @@ ], "meta": { "nf-test": "0.9.2", - "nextflow": "24.10.5" + "nextflow": "24.10.6" }, - "timestamp": "2025-04-22T09:34:45.900956" + "timestamp": "2025-10-20T13:25:42.669804" }, "vuegen - directory (HTML report)": { "content": [ @@ -24,16 +26,18 @@ "quarto_report.html": "0129d189059f27b3d2ff6f328cd18ef9", "quarto_report.qmd": "e60a379de892055748e4597f9d8c656c" }, - "versions": [ - "versions.yml:md5,c3e7ebc433dcacf3d15e1113fd44f5ec" - ] + "versions": { + "VUEGEN": { + "vuegen": "0.5.1" + } + } } ], "meta": { "nf-test": "0.9.2", - "nextflow": "24.10.5" + "nextflow": "24.10.6" }, - "timestamp": "2025-04-22T09:04:23.56469" + "timestamp": "2025-10-20T13:24:59.558083" }, "vuegen - directory (PDF report)": { "content": [ @@ -43,37 +47,41 @@ "quarto_report.pdf": true, "quarto_report.qmd": "c447088ca2a435acf926ec5e95c51265" }, - "versions": [ - "versions.yml:md5,c3e7ebc433dcacf3d15e1113fd44f5ec" - ] + "versions": { + "VUEGEN": { + "vuegen": "0.5.1" + } + } } ], "meta": { "nf-test": "0.9.2", - "nextflow": "24.10.5" + "nextflow": "24.10.6" }, - "timestamp": "2025-04-22T09:05:54.139709" + "timestamp": "2025-10-20T13:25:37.140787" }, "vuegen - directory (Streamlit report)": { "content": [ { "output_folder": true, "output_files": { - "Homepage.py": "Homepage.py:md5,483a41696c225663772d68ff2d664493", - "report_manager.py": "report_manager.py:md5,ed15eefa722b7a2f08cca016c0c8e28d", - "All_Formats.py": "e2a56e761eb537da8f9809cbc0b63a9d", - "Interactive_Plots.py": "3198216240ef9b86d5b1ed722bd9b31c", - "Static_Plots.py": "931fd04e2e49cb14d169747b6d5bbd1e" + "Homepage.py": "Homepage.py:md5,a46395bbdfb127463d51d8f601f2ad83", + "report_manager.py": "report_manager.py:md5,a683071ba8bc6e371c8617ef9c3fb84e", + "All_Formats.py": "1f61acc3ca34f6ff941c109d93570815", + "Interactive_Plots.py": "4857dc511178812e93c2037c8bbe04f4", + "Static_Plots.py": "ae9c2e46ae9a9e0e5e98fcce87cd7f80" }, - "versions": [ - "versions.yml:md5,c3e7ebc433dcacf3d15e1113fd44f5ec" - ] + "versions": { + "VUEGEN": { + "vuegen": "0.5.1" + } + } } ], "meta": { "nf-test": "0.9.2", - "nextflow": "24.10.5" + "nextflow": "24.10.6" }, - "timestamp": "2025-04-22T09:03:48.375488" + "timestamp": "2025-10-20T13:19:47.56244" } } \ No newline at end of file