diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index b290e090..d5df5e0b 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -1,20 +1,21 @@ { "name": "nfcore", - "image": "nfcore/gitpod:latest", - "remoteUser": "gitpod", - "runArgs": ["--privileged"], + "image": "nfcore/devcontainer:latest", - // Configure tool-specific properties. - "customizations": { - // Configure properties specific to VS Code. - "vscode": { - // Set *default* container specific settings.json values on container create. - "settings": { - "python.defaultInterpreterPath": "/opt/conda/bin/python" - }, + "remoteUser": "root", + "privileged": true, + "runArgs": ["--device=/dev/loop-control", "--device=/dev/loop0", "--device=/dev/loop1"], - // Add the IDs of extensions you want installed when the container is created. - "extensions": ["ms-python.python", "ms-python.vscode-pylance", "nf-core.nf-core-extensionpack"] - } + "remoteEnv": { + // Workspace path on the host for mounting with docker-outside-of-docker + "LOCAL_WORKSPACE_FOLDER": "${localWorkspaceFolder}" + }, + + "onCreateCommand": "./.devcontainer/setup.sh", + + "hostRequirements": { + "cpus": 4, + "memory": "16gb", + "storage": "32gb" } } diff --git a/.devcontainer/setup.sh b/.devcontainer/setup.sh new file mode 100755 index 00000000..07a54582 --- /dev/null +++ b/.devcontainer/setup.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash + +# Customise the terminal command prompt +echo "export PROMPT_DIRTRIM=2" >> $HOME/.bashrc +echo "export PS1='\[\e[3;36m\]\w ->\[\e[0m\\] '" >> $HOME/.bashrc +export PROMPT_DIRTRIM=2 +export PS1='\[\e[3;36m\]\w ->\[\e[0m\\] ' + +# Update Nextflow +nextflow self-update + +# Update welcome message +echo "Welcome to the nf-core/mhcquant devcontainer!" > /usr/local/etc/vscode-dev-containers/first-run-notice.txt diff --git a/.editorconfig b/.editorconfig deleted file mode 100644 index 20500856..00000000 --- a/.editorconfig +++ /dev/null @@ -1,43 +0,0 @@ -root = true - -[*] -charset = utf-8 -end_of_line = lf -insert_final_newline = true -trim_trailing_whitespace = true -indent_size = 4 -indent_style = space - -[*.{md,yml,yaml,html,css,scss,js}] -indent_size = 2 - -# These files are edited and tested upstream in nf-core/modules -[/modules/nf-core/**] -charset = unset -end_of_line = unset -insert_final_newline = unset -trim_trailing_whitespace = unset -indent_style = unset -[/subworkflows/nf-core/**] -charset = unset -end_of_line = unset -insert_final_newline = unset -trim_trailing_whitespace = unset -indent_style = unset - -[/assets/email*] -indent_size = unset - -[/assets/250120_unimod_tables.xml] -indent_style = unset -indent_size = unset -end_of_line = unset -trim_trailing_whitespace = unset - -# ignore python and markdown -[*.{py,md}] -indent_style = unset - -# ignore ro-crate metadata files -[**/ro-crate-metadata.json] -insert_final_newline = unset diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index fe6789a0..4eae7b24 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -78,7 +78,7 @@ If you wish to contribute a new step, please use the following coding standards: 5. Add any new parameters to `nextflow_schema.json` with help text (via the `nf-core pipelines schema build` tool). 6. Add sanity checks and validation for all relevant parameters. 7. Perform local tests to validate that the new code works as expected. -8. If applicable, add a new test command in `.github/workflow/ci.yml`. +8. If applicable, add a new test in the `tests` directory. 9. Update MultiQC config `assets/multiqc_config.yml` so relevant suffixes, file name clean up and module plots are in the appropriate order. If applicable, add a [MultiQC](https://https://multiqc.info/) module. 10. Add a description of the output files and if relevant any appropriate images from the MultiQC report to `docs/output.md`. diff --git a/.github/actions/get-shards/action.yml b/.github/actions/get-shards/action.yml new file mode 100644 index 00000000..34085279 --- /dev/null +++ b/.github/actions/get-shards/action.yml @@ -0,0 +1,69 @@ +name: "Get number of shards" +description: "Get the number of nf-test shards for the current CI job" +inputs: + max_shards: + description: "Maximum number of shards allowed" + required: true + paths: + description: "Component paths to test" + required: false + tags: + description: "Tags to pass as argument for nf-test --tag parameter" + required: false +outputs: + shard: + description: "Array of shard numbers" + value: ${{ steps.shards.outputs.shard }} + total_shards: + description: "Total number of shards" + value: ${{ steps.shards.outputs.total_shards }} +runs: + using: "composite" + steps: + - name: Install nf-test + uses: nf-core/setup-nf-test@v1 + with: + version: ${{ env.NFT_VER }} + - name: Get number of shards + id: shards + shell: bash + run: | + # Run nf-test with dynamic parameter + nftest_output=$(nf-test test \ + --profile +docker \ + $(if [ -n "${{ inputs.tags }}" ]; then echo "--tag ${{ inputs.tags }}"; fi) \ + --dry-run \ + --ci \ + --changed-since HEAD^) || { + echo "nf-test command failed with exit code $?" + echo "Full output: $nftest_output" + exit 1 + } + echo "nf-test dry-run output: $nftest_output" + + # Default values for shard and total_shards + shard="[]" + total_shards=0 + + # Check if there are related tests + if echo "$nftest_output" | grep -q 'No tests to execute'; then + echo "No related tests found." + else + # Extract the number of related tests + number_of_shards=$(echo "$nftest_output" | sed -n 's|.*Executed \([0-9]*\) tests.*|\1|p') + if [[ -n "$number_of_shards" && "$number_of_shards" -gt 0 ]]; then + shards_to_run=$(( $number_of_shards < ${{ inputs.max_shards }} ? $number_of_shards : ${{ inputs.max_shards }} )) + shard=$(seq 1 "$shards_to_run" | jq -R . | jq -c -s .) + total_shards="$shards_to_run" + else + echo "Unexpected output format. Falling back to default values." + fi + fi + + # Write to GitHub Actions outputs + echo "shard=$shard" >> $GITHUB_OUTPUT + echo "total_shards=$total_shards" >> $GITHUB_OUTPUT + + # Debugging output + echo "Final shard array: $shard" + echo "Total number of shards: $total_shards" diff --git a/.github/actions/nf-test/action.yml b/.github/actions/nf-test/action.yml new file mode 100644 index 00000000..3b9724c7 --- /dev/null +++ b/.github/actions/nf-test/action.yml @@ -0,0 +1,111 @@ +name: "nf-test Action" +description: "Runs nf-test with common setup steps" +inputs: + profile: + description: "Profile to use" + required: true + shard: + description: "Shard number for this CI job" + required: true + total_shards: + description: "Total number of test shards(NOT the total number of matrix jobs)" + required: true + paths: + description: "Test paths" + required: true + tags: + description: "Tags to pass as argument for nf-test --tag parameter" + required: false +runs: + using: "composite" + steps: + - name: Setup Nextflow + uses: nf-core/setup-nextflow@v2 + with: + version: "${{ env.NXF_VERSION }}" + + - name: Set up Python + uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6 + with: + python-version: "3.14" + + - name: Install nf-test + uses: nf-core/setup-nf-test@v1 + with: + version: "${{ env.NFT_VER }}" + install-pdiff: true + + - name: Setup apptainer + if: contains(inputs.profile, 'singularity') + uses: eWaterCycle/setup-apptainer@main + + - name: Set up Singularity + if: contains(inputs.profile, 'singularity') + shell: bash + run: | + mkdir -p $NXF_SINGULARITY_CACHEDIR + mkdir -p $NXF_SINGULARITY_LIBRARYDIR + + - name: Conda setup + if: contains(inputs.profile, 'conda') + uses: conda-incubator/setup-miniconda@505e6394dae86d6a5c7fbb6e3fb8938e3e863830 # v3 + with: + auto-update-conda: true + conda-solver: libmamba + channels: conda-forge + channel-priority: strict + conda-remove-defaults: true + + - name: Run nf-test + shell: bash + env: + NFT_WORKDIR: ${{ env.NFT_WORKDIR }} + run: | + nf-test test \ + --profile=+${{ inputs.profile }} \ + $(if [ -n "${{ inputs.tags }}" ]; then echo "--tag ${{ inputs.tags }}"; fi) \ + --ci \ + --changed-since HEAD^ \ + --verbose \ + --tap=test.tap \ + --shard ${{ inputs.shard }}/${{ inputs.total_shards }} + + # Save the absolute path of the test.tap file to the output + echo "tap_file_path=$(realpath test.tap)" >> $GITHUB_OUTPUT + + - name: Generate test summary + if: always() + shell: bash + run: | + # Add header if it doesn't exist (using a token file to track this) + if [ ! -f ".summary_header" ]; then + echo "# 🚀 nf-test results" >> $GITHUB_STEP_SUMMARY + echo "" >> $GITHUB_STEP_SUMMARY + echo "| Status | Test Name | Profile | Shard |" >> $GITHUB_STEP_SUMMARY + echo "|:------:|-----------|---------|-------|" >> $GITHUB_STEP_SUMMARY + touch .summary_header + fi + + if [ -f test.tap ]; then + while IFS= read -r line; do + if [[ $line =~ ^ok ]]; then + test_name="${line#ok }" + # Remove the test number from the beginning + test_name="${test_name#* }" + echo "| ✅ | ${test_name} | ${{ inputs.profile }} | ${{ inputs.shard }}/${{ inputs.total_shards }} |" >> $GITHUB_STEP_SUMMARY + elif [[ $line =~ ^not\ ok ]]; then + test_name="${line#not ok }" + # Remove the test number from the beginning + test_name="${test_name#* }" + echo "| ❌ | ${test_name} | ${{ inputs.profile }} | ${{ inputs.shard }}/${{ inputs.total_shards }} |" >> $GITHUB_STEP_SUMMARY + fi + done < test.tap + else + echo "| ⚠️ | No test results found | ${{ inputs.profile }} | ${{ inputs.shard }}/${{ inputs.total_shards }} |" >> $GITHUB_STEP_SUMMARY + fi + + - name: Clean up + if: always() + shell: bash + run: | + sudo rm -rf /home/ubuntu/tests/ diff --git a/.github/workflows/awsfulltest.yml b/.github/workflows/awsfulltest.yml index 318bc896..3ab7364a 100644 --- a/.github/workflows/awsfulltest.yml +++ b/.github/workflows/awsfulltest.yml @@ -14,7 +14,7 @@ jobs: run-platform: name: Run AWS full tests # run only if the PR is approved by at least 2 reviewers and against the master/main branch or manually triggered - if: github.repository == 'nf-core/mhcquant' && github.event.review.state == 'approved' && (github.event.pull_request.base.ref == 'master' || github.event.pull_request.base.ref == 'main') || github.event_name == 'workflow_dispatch' + if: github.repository == 'nf-core/mhcquant' && github.event.review.state == 'approved' && (github.event.pull_request.base.ref == 'master' || github.event.pull_request.base.ref == 'main') || github.event_name == 'workflow_dispatch' || github.event_name == 'release' runs-on: ubuntu-latest steps: - name: Set revision variable @@ -25,21 +25,21 @@ jobs: - name: Launch workflow via Seqera Platform uses: seqeralabs/action-tower-launch@v2 with: - workspace_id: ${{ secrets.TOWER_WORKSPACE_ID }} + workspace_id: ${{ vars.TOWER_WORKSPACE_ID }} access_token: ${{ secrets.TOWER_ACCESS_TOKEN }} - compute_env: ${{ secrets.TOWER_COMPUTE_ENV }} + compute_env: ${{ vars.TOWER_COMPUTE_ENV }} revision: ${{ steps.revision.outputs.revision }} - workdir: s3://${{ secrets.AWS_S3_BUCKET }}/work/mhcquant/work-${{ steps.revision.outputs.revision }} + workdir: s3://${{ vars.AWS_S3_BUCKET }}/work/mhcquant/work-${{ steps.revision.outputs.revision }} parameters: | { "hook_url": "${{ secrets.MEGATESTS_ALERTS_SLACK_HOOK_URL }}", - "outdir": "s3://${{ secrets.AWS_S3_BUCKET }}/mhcquant/results-${{ steps.revision.outputs.revision }}" + "outdir": "s3://${{ vars.AWS_S3_BUCKET }}/mhcquant/results-${{ steps.revision.outputs.revision }}" } profiles: test_full - - uses: actions/upload-artifact@v4 + - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: Seqera Platform debug log file path: | - seqera_platform_action_*.log - seqera_platform_action_*.json + tower_action_*.log + tower_action_*.json diff --git a/.github/workflows/awstest.yml b/.github/workflows/awstest.yml index 90a22ffa..d747d13c 100644 --- a/.github/workflows/awstest.yml +++ b/.github/workflows/awstest.yml @@ -14,20 +14,20 @@ jobs: - name: Launch workflow via Seqera Platform uses: seqeralabs/action-tower-launch@v2 with: - workspace_id: ${{ secrets.TOWER_WORKSPACE_ID }} + workspace_id: ${{ vars.TOWER_WORKSPACE_ID }} access_token: ${{ secrets.TOWER_ACCESS_TOKEN }} - compute_env: ${{ secrets.TOWER_COMPUTE_ENV }} + compute_env: ${{ vars.TOWER_COMPUTE_ENV }} revision: ${{ github.sha }} - workdir: s3://${{ secrets.AWS_S3_BUCKET }}/work/mhcquant/work-${{ github.sha }} + workdir: s3://${{ vars.AWS_S3_BUCKET }}/work/mhcquant/work-${{ github.sha }} parameters: | { - "outdir": "s3://${{ secrets.AWS_S3_BUCKET }}/mhcquant/results-test-${{ github.sha }}" + "outdir": "s3://${{ vars.AWS_S3_BUCKET }}/mhcquant/results-test-${{ github.sha }}" } profiles: test - - uses: actions/upload-artifact@v4 + - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: Seqera Platform debug log file path: | - seqera_platform_action_*.log - seqera_platform_action_*.json + tower_action_*.log + tower_action_*.json diff --git a/.github/workflows/changelog.py b/.github/workflows/changelog.py new file mode 100644 index 00000000..2f86a721 --- /dev/null +++ b/.github/workflows/changelog.py @@ -0,0 +1,231 @@ +#! /usr/bin/env python3 +""" +Taken from https://github.com/MultiQC/MultiQC/blob/main/.github/workflows/changelog.py and updated for nf-core + +To be called by a CI action. Assumes the following environment variables are set: +PR_TITLE, PR_NUMBER, GITHUB_WORKSPACE. + +Adds a line into the CHANGELOG.md: +* Looks for the section to add the line to, based on the PR title, e.g. `Template:`, `Modules:`. +* All other change will go under the "### General" section. +* If an entry for the PR is already added, it will not run. + +Other assumptions: +- CHANGELOG.md has a running section for an ongoing "dev" version +(i.e. titled "## nf-core vX.Ydev"). +""" + +import os +import re +import sys +from pathlib import Path + +REPO_URL = "https://github.com/nf-core/mhcquant" + +# Assumes the environment is set by the GitHub action. +pr_title = os.environ["PR_TITLE"] +pr_number = os.environ["PR_NUMBER"] +comment = os.environ.get("COMMENT", "") +workspace_path = Path(os.environ.get("GITHUB_WORKSPACE", "")) + +assert pr_title, pr_title +assert pr_number, pr_number + +# Trim the PR number added when GitHub squashes commits, e.g. "Template: Updated (#2026)" +pr_title = pr_title.removesuffix(f" (#{pr_number})") # type: ignore + +changelog_path = workspace_path / "CHANGELOG.md" + +if any( + line in pr_title.lower() + for line in [ + "skip changelog", + "skip change log", + "no changelog", + "no change log", + "bump version", + ] +): + print("Skipping changelog update") + sys.exit(0) + + +def _determine_change_type(pr_title) -> tuple[str, str]: + """ + Determine the type of the PR: Template, Download, Linting, Modules, Subworkflows, or General + Returns a tuple of the section name and the module info. + """ + sections = { + "Template": "### Template", + "Download": "### Download", + "Linting": "### Linting", + "Modules": "### Modules", + "Subworkflows": "### Subworkflows", + } + current_section_header = "### General" + current_section = "General" + + # Check if the PR in any of the sections. + for section, section_header in sections.items(): + # check if the PR title contains any of the section headers, with some loose matching, e.g. removing plural and suffixes + if re.sub(r"s$", "", section.lower().replace("ing", "")) in pr_title.lower(): + current_section_header = section_header + current_section = section + print(f"Detected section: {current_section}") + return current_section, current_section_header + + +# Determine the type of the PR +section, section_header = _determine_change_type(pr_title) + +# Remove section indicator from the PR title. +pr_title = re.sub(rf"{section}:[\s]*", "", pr_title, flags=re.IGNORECASE) + +# Prepare the change log entry. +pr_link = f"([#{pr_number}]({REPO_URL}/pull/{pr_number}))" + +# Handle manual changelog entries through comments. +if comment := comment.removeprefix("@nf-core-bot changelog").strip(): # type: ignore + print(f"Adding manual changelog entry: {comment}") + pr_title = comment +new_lines = [ + f"- {pr_title} {pr_link}\n", +] +print(f"Adding new lines into section '{section}':\n" + "".join(new_lines)) + +# Finally, updating the changelog. +# Read the current changelog lines. We will print them back as is, except for one new +# entry, corresponding to this new PR. +with changelog_path.open("r") as f: + orig_lines = f.readlines() +updated_lines: list[str] = [] + + +def _skip_existing_entry_for_this_pr(line: str, same_section: bool = True) -> str: + if line.strip().endswith(pr_link): + print(f"Found existing entry for this pull request #{pr_number}:") + existing_lines = [line] + if new_lines and new_lines == existing_lines and same_section: + print(f"Found existing identical entry for this pull request #{pr_number} in the same section:") + print("".join(existing_lines)) + sys.exit(0) # Just leaving the CHANGELOG intact + else: + print( + f"Found existing entry for this pull request #{pr_number}. It will be replaced and/or moved to proper section" + ) + print("".join(existing_lines)) + for _ in range(len(existing_lines)): + try: + line = orig_lines.pop(0) + except IndexError: + break + return line + + +# Find the next line in the change log that matches the pattern "# nf-core/mhcquant v.*dev" +# If it doesn't exist, exist with code 1 (let's assume that a new section is added +# manually or by CI when a release is pushed). +# Else, find the next line that matches the `section` variable, and insert a new line +# under it (we also assume that section headers are added already). +inside_version_dev = False +already_added_entry = False +while orig_lines: + line = orig_lines.pop(0) + + # If the line already contains a link to the PR, don't add it again. + line = _skip_existing_entry_for_this_pr(line, same_section=False) + + if ( + line.startswith("## ") and not line.strip() == "# nf-core/mhcquant: Changelog" + ): # Version header, e.g. "## v2.12dev" + print(f"Found version header: {line.strip()}") + updated_lines.append(line) + + # Parse version from the line `## v2.12dev` or + # `## [v2.11.1 - Magnesium Dragon Patch](https://github.com/nf-core/tools/releases/tag/2.11) - [2023-12-20]` ... + if not (m := re.match(r".*(v\d+\.\d+.\d*(dev)?).*", line)): + print(f"Cannot parse version from line {line.strip()}.", file=sys.stderr) + sys.exit(1) + version = m.group(1) + print(f"Found version: {version}") + + if not inside_version_dev: + if not version.endswith("dev"): + print( + "Can't find a 'dev' version section in the changelog. Make sure " + "it's created, and all the required sections, e.g. `### Template` are created under it .", + file=sys.stderr, + ) + sys.exit(1) + inside_version_dev = True + else: + if version.endswith("dev"): + print( + f"Found another 'dev' version section in the changelog, make" + f"sure to change it to a 'release' stable version tag. " + f"Line: {line.strip()}", + file=sys.stderr, + ) + sys.exit(1) + # We are past the dev version, so just add back the rest of the lines and break. + while orig_lines: + line = orig_lines.pop(0) + line = _skip_existing_entry_for_this_pr(line, same_section=False) + if line: + updated_lines.append(line) + break + continue + print(f"Found line: {line.strip()}") + print(f"inside_version_dev: {inside_version_dev}") + print(f"section_header: {section_header}") + if inside_version_dev and line.lower().startswith(section_header.lower()): # Section of interest header + print(f"Found section header: {line.strip()}") + if already_added_entry: + print( + f"Already added new lines into section {section}, is the section duplicated?", + file=sys.stderr, + ) + sys.exit(1) + updated_lines.append(line) + # Collecting lines until the next section. + section_lines: list[str] = [] + while True: + line = orig_lines.pop(0) + if line.startswith("#"): + print(f"Found the next section header: {line.strip()}") + # Found the next section header, so need to put all the lines we collected. + updated_lines.append("\n") + _updated_lines = [_l for _l in section_lines + new_lines if _l.strip()] + updated_lines.extend(_updated_lines) + updated_lines.append("\n") + if new_lines: + print(f"Updated {changelog_path} section '{section}' with lines:\n" + "".join(new_lines)) + else: + print(f"Removed existing entry from {changelog_path} section '{section}'") + already_added_entry = True + # Pushing back the next section header line + orig_lines.insert(0, line) + break + # If the line already contains a link to the PR, don't add it again. + line = _skip_existing_entry_for_this_pr(line, same_section=True) + section_lines.append(line) + + else: + updated_lines.append(line) + + +def collapse_newlines(lines: list[str]) -> list[str]: + updated = [] + for idx in range(len(lines)): + if idx != 0 and not lines[idx].strip() and not lines[idx - 1].strip(): + continue + updated.append(lines[idx]) + return updated + + +updated_lines = collapse_newlines(updated_lines) + + +# Finally, writing the updated lines back. +with changelog_path.open("w") as f: + f.writelines(updated_lines) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml deleted file mode 100644 index 442f9211..00000000 --- a/.github/workflows/ci.yml +++ /dev/null @@ -1,156 +0,0 @@ -name: nf-core CI -# This workflow runs the pipeline with the minimal test dataset to check that it completes without any syntax errors -on: - push: - branches: - - dev - - master - pull_request: - release: - types: [published] - workflow_dispatch: - -env: - NXF_ANSI_LOG: false - NXF_SINGULARITY_CACHEDIR: ${{ github.workspace }}/.singularity - NXF_SINGULARITY_LIBRARYDIR: ${{ github.workspace }}/.singularity - -concurrency: - group: "${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}" - cancel-in-progress: true - -jobs: - test: - name: "Run pipeline with test data (${{ matrix.NXF_VER }} | ${{ matrix.test_name }} | ${{ matrix.profile }})" - # Only run on push if this is the nf-core dev branch (merged PRs) - if: "${{ github.event_name != 'push' || (github.event_name == 'push' && github.repository == 'nf-core/mhcquant') }}" - runs-on: ubuntu-latest - strategy: - matrix: - NXF_VER: - - "24.04.2" - - "latest-everything" - profile: - - "conda" - - "docker" - - "singularity" - test_name: - - "test" - isMaster: - - ${{ github.base_ref == 'master' }} - # Exclude conda and singularity on dev - exclude: - - isMaster: false - profile: "conda" - - isMaster: false - profile: "singularity" - steps: - - name: Check out pipeline code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 - with: - fetch-depth: 0 - - - name: Set up Nextflow - uses: nf-core/setup-nextflow@v2 - with: - version: "${{ matrix.NXF_VER }}" - - - name: Set up Apptainer - if: matrix.profile == 'singularity' - uses: eWaterCycle/setup-apptainer@main - - - name: Set up Singularity - if: matrix.profile == 'singularity' - run: | - mkdir -p $NXF_SINGULARITY_CACHEDIR - mkdir -p $NXF_SINGULARITY_LIBRARYDIR - - - name: Set up Miniconda - if: matrix.profile == 'conda' - uses: conda-incubator/setup-miniconda@a4260408e20b96e80095f42ff7f1a15b27dd94ca # v3 - with: - miniconda-version: "latest" - auto-update-conda: true - conda-solver: libmamba - channels: conda-forge,bioconda - - - name: Set up Conda - if: matrix.profile == 'conda' - run: | - echo $(realpath $CONDA)/condabin >> $GITHUB_PATH - echo $(realpath python) >> $GITHUB_PATH - - - name: Clean up Disk space - uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be # v1.3.1 - - - name: "Run pipeline with test data ${{ matrix.NXF_VER }} | ${{ matrix.test_name }} | ${{ matrix.profile }}" - continue-on-error: ${{ matrix.NXF_VER == 'latest-everything' }} - run: | - nextflow run ${GITHUB_WORKSPACE} -profile test,docker --outdir ./results - - profile: - name: Run profile tests - if: ${{ github.event_name != 'push' || (github.event_name == 'push' && github.repository == 'nf-core/mhcquant') }} - runs-on: ubuntu-latest - env: - NXF_VER: ${{ matrix.nxf_ver }} - NXF_ANSI_LOG: false - strategy: - matrix: - include: - # Test pipeline minimum Nextflow version - - NXF_VER: "23.04.0" - NXF_EDGE: "" - # Test latest edge release of Nextflow - - NXF_VER: "" - NXF_EDGE: "1" - tests: ["test_mokapot", "test_percolator", "test_ionannotator", "test_speclib"] - steps: - - name: Check out pipeline code - uses: actions/checkout@v2 - - name: Install Nextflow - env: - NXF_VER: ${{ matrix.NXF_VER }} - # Uncomment only if the edge release is more recent than the latest stable release - # See https://github.com/nextflow-io/nextflow/issues/2467 - # NXF_EDGE: ${{ matrix.NXF_EDGE }} - run: | - wget -qO- get.nextflow.io | bash - sudo mv nextflow /usr/local/bin/ - - name: Run pipeline with profile ${{ matrix.tests }} - run: | - nextflow run ${GITHUB_WORKSPACE} -profile ${{ matrix.tests }},docker --spectrum_batch_size 5000 --outdir ./results - - # Define a second workflow only against main with additional tests: test_timstof and test_full - profile_main: - name: Run timsTOF profile tests - if: ${{ github.event_name == 'push' && github.ref == 'refs/heads/main' && github.repository == 'nf-core/mhcquant' }} - runs-on: ubuntu-latest - env: - NXF_VER: ${{ matrix.nxf_ver }} - NXF_ANSI_LOG: false - strategy: - matrix: - include: - # Test pipeline minimum Nextflow version - - NXF_VER: "23.04.0" - NXF_EDGE: "" - # Test latest edge release of Nextflow - - NXF_VER: "" - NXF_EDGE: "1" - tests: ["test_timstof"] - steps: - - name: Check out pipeline code - uses: actions/checkout@v2 - - name: Install Nextflow - env: - NXF_VER: ${{ matrix.NXF_VER }} - # Uncomment only if the edge release is more recent than the latest stable release - # See https://github.com/nextflow-io/nextflow/issues/2467 - # NXF_EDGE: ${{ matrix.NXF_EDGE }} - run: | - wget -qO- get.nextflow.io | bash - sudo mv nextflow /usr/local/bin/ - - name: Run pipeline with profile ${{ matrix.tests }} - run: | - nextflow run ${GITHUB_WORKSPACE} -profile ${{ matrix.tests }},docker --spectrum_batch_size 5000 --outdir ./results diff --git a/.github/workflows/clean-up.yml b/.github/workflows/clean-up.yml index 0b6b1f27..6adb0fff 100644 --- a/.github/workflows/clean-up.yml +++ b/.github/workflows/clean-up.yml @@ -10,7 +10,7 @@ jobs: issues: write pull-requests: write steps: - - uses: actions/stale@28ca1036281a5e5922ead5184a1bbf96e5fc984e # v9 + - uses: actions/stale@5f858e3efba33a5ca4407a664cc011ad407f2008 # v10 with: stale-issue-message: "This issue has been tagged as awaiting-changes or awaiting-feedback by an nf-core contributor. Remove stale label or add a comment otherwise this issue will be closed in 20 days." stale-pr-message: "This PR has been tagged as awaiting-changes or awaiting-feedback by an nf-core contributor. Remove stale label or add a comment if it is still useful." diff --git a/.github/workflows/download_pipeline.yml b/.github/workflows/download_pipeline.yml index ab06316e..6d94bcbf 100644 --- a/.github/workflows/download_pipeline.yml +++ b/.github/workflows/download_pipeline.yml @@ -12,14 +12,6 @@ on: required: true default: "dev" pull_request: - types: - - opened - - edited - - synchronize - branches: - - main - - master - pull_request_target: branches: - main - master @@ -52,9 +44,9 @@ jobs: - name: Disk space cleanup uses: jlumbroso/free-disk-space@54081f138730dfa15788a46383842cd2f914a1be # v1.3.1 - - uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5 + - uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6 with: - python-version: "3.12" + python-version: "3.14" architecture: "x64" - name: Setup Apptainer @@ -65,7 +57,7 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install git+https://github.com/nf-core/tools.git@dev + pip install git+https://github.com/nf-core/tools.git - name: Make a cache directory for the container images run: | @@ -120,6 +112,7 @@ jobs: echo "IMAGE_COUNT_AFTER=$image_count" >> "$GITHUB_OUTPUT" - name: Compare container image counts + id: count_comparison run: | if [ "${{ steps.count_initial.outputs.IMAGE_COUNT_INITIAL }}" -ne "${{ steps.count_afterwards.outputs.IMAGE_COUNT_AFTER }}" ]; then initial_count=${{ steps.count_initial.outputs.IMAGE_COUNT_INITIAL }} @@ -132,3 +125,10 @@ jobs: else echo "The pipeline can be downloaded successfully!" fi + + - name: Upload Nextflow logfile for debugging purposes + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + with: + name: nextflow_logfile.txt + path: .nextflow.log* + include-hidden-files: true diff --git a/.github/workflows/fix-linting.yml b/.github/workflows/fix_linting.yml similarity index 80% rename from .github/workflows/fix-linting.yml rename to .github/workflows/fix_linting.yml index 8bdf75c7..b67a297c 100644 --- a/.github/workflows/fix-linting.yml +++ b/.github/workflows/fix_linting.yml @@ -13,13 +13,13 @@ jobs: runs-on: ubuntu-latest steps: # Use the @nf-core-bot token to check out so we can push later - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5 with: token: ${{ secrets.nf_core_bot_auth_token }} # indication that the linting is being fixed - name: React on comment - uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4 + uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9 # v5 with: comment-id: ${{ github.event.comment.id }} reactions: eyes @@ -32,9 +32,9 @@ jobs: GITHUB_TOKEN: ${{ secrets.nf_core_bot_auth_token }} # Install and run pre-commit - - uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5 + - uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6 with: - python-version: "3.12" + python-version: "3.14" - name: Install pre-commit run: pip install pre-commit @@ -47,7 +47,7 @@ jobs: # indication that the linting has finished - name: react if linting finished succesfully if: steps.pre-commit.outcome == 'success' - uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4 + uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9 # v5 with: comment-id: ${{ github.event.comment.id }} reactions: "+1" @@ -67,21 +67,21 @@ jobs: - name: react if linting errors were fixed id: react-if-fixed if: steps.commit-and-push.outcome == 'success' - uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4 + uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9 # v5 with: comment-id: ${{ github.event.comment.id }} reactions: hooray - name: react if linting errors were not fixed if: steps.commit-and-push.outcome == 'failure' - uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4 + uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9 # v5 with: comment-id: ${{ github.event.comment.id }} reactions: confused - name: react if linting errors were not fixed if: steps.commit-and-push.outcome == 'failure' - uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4 + uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9 # v5 with: issue-number: ${{ github.event.issue.number }} body: | diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index dbd52d5a..30e66026 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -3,9 +3,6 @@ name: nf-core linting # It runs the `nf-core pipelines lint` and markdown lint tests to ensure # that the code meets the nf-core guidelines. on: - push: - branches: - - dev pull_request: release: types: [published] @@ -14,12 +11,12 @@ jobs: pre-commit: runs-on: ubuntu-latest steps: - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5 - - name: Set up Python 3.12 - uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5 + - name: Set up Python 3.14 + uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6 with: - python-version: "3.12" + python-version: "3.14" - name: Install pre-commit run: pip install pre-commit @@ -31,18 +28,18 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out pipeline code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5 - name: Install Nextflow uses: nf-core/setup-nextflow@v2 - - uses: actions/setup-python@0b93645e9fea7318ecaed2b359559ac225c90a2b # v5 + - uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6 with: - python-version: "3.12" + python-version: "3.14" architecture: "x64" - name: read .nf-core.yml - uses: pietrobolcato/action-read-yaml@1.1.0 + uses: pietrobolcato/action-read-yaml@9f13718d61111b69f30ab4ac683e67a56d254e1d # 1.1.0 id: read_yml with: config: ${{ github.workspace }}/.nf-core.yml @@ -74,7 +71,7 @@ jobs: - name: Upload linting log file artifact if: ${{ always() }} - uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 # v4 + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 with: name: linting-logs path: | diff --git a/.github/workflows/linting_comment.yml b/.github/workflows/linting_comment.yml index 95b6b6af..e6e9bc26 100644 --- a/.github/workflows/linting_comment.yml +++ b/.github/workflows/linting_comment.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Download lint results - uses: dawidd6/action-download-artifact@20319c5641d495c8a52e688b7dc5fada6c3a9fbc # v8 + uses: dawidd6/action-download-artifact@ac66b43f0e6a346234dd65d4d0c8fbb31cb316e5 # v11 with: workflow: linting.yml workflow_conclusion: completed @@ -21,7 +21,7 @@ jobs: run: echo "pr_number=$(cat linting-logs/PR_number.txt)" >> $GITHUB_OUTPUT - name: Post PR comment - uses: marocchino/sticky-pull-request-comment@331f8f5b4215f0445d3c07b4967662a32a2d3e31 # v2 + uses: marocchino/sticky-pull-request-comment@773744901bac0e8cbb5a0dc842800d45e9b2b405 # v2 with: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} number: ${{ steps.pr_number.outputs.pr_number }} diff --git a/.github/workflows/nf-test.yml b/.github/workflows/nf-test.yml new file mode 100644 index 00000000..cb4db1d2 --- /dev/null +++ b/.github/workflows/nf-test.yml @@ -0,0 +1,145 @@ +name: Run nf-test +on: + pull_request: + paths-ignore: + - "docs/**" + - "**/meta.yml" + - "**/*.md" + - "**/*.png" + - "**/*.svg" + release: + types: [published] + workflow_dispatch: + +# Cancel if a newer run is started +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + NFT_VER: "0.9.3" + NFT_WORKDIR: "~" + NXF_ANSI_LOG: false + NXF_SINGULARITY_CACHEDIR: ${{ github.workspace }}/.singularity + NXF_SINGULARITY_LIBRARYDIR: ${{ github.workspace }}/.singularity + +jobs: + nf-test-changes: + name: nf-test-changes + runs-on: # use self-hosted runners + - runs-on=${{ github.run_id }}-nf-test-changes + - runner=4cpu-linux-x64 + outputs: + shard: ${{ steps.set-shards.outputs.shard }} + total_shards: ${{ steps.set-shards.outputs.total_shards }} + steps: + - name: Clean Workspace # Purge the workspace in case it's running on a self-hosted runner + run: | + ls -la ./ + rm -rf ./* || true + rm -rf ./.??* || true + ls -la ./ + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5 + with: + fetch-depth: 0 + + - name: get number of shards + id: set-shards + uses: ./.github/actions/get-shards + env: + NFT_VER: ${{ env.NFT_VER }} + with: + max_shards: 7 + + - name: debug + run: | + echo ${{ steps.set-shards.outputs.shard }} + echo ${{ steps.set-shards.outputs.total_shards }} + + nf-test: + name: "${{ matrix.profile }} | ${{ matrix.NXF_VER }} | ${{ matrix.shard }}/${{ needs.nf-test-changes.outputs.total_shards }}" + needs: [nf-test-changes] + if: ${{ needs.nf-test-changes.outputs.total_shards != '0' }} + runs-on: # use self-hosted runners + - runs-on=${{ github.run_id }}-nf-test + - runner=4cpu-linux-x64 + strategy: + fail-fast: false + matrix: + shard: ${{ fromJson(needs.nf-test-changes.outputs.shard) }} + # Add conda to once conda lock file support is added + profile: [docker, singularity] + isMain: + - ${{ github.base_ref == 'master' || github.base_ref == 'main' }} + # Exclude conda and singularity on dev + exclude: + - isMain: false + profile: "conda" + - isMain: false + profile: "singularity" + NXF_VER: + - "25.04.0" + - "latest-everything" + env: + NXF_ANSI_LOG: false + TOTAL_SHARDS: ${{ needs.nf-test-changes.outputs.total_shards }} + + steps: + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5 + with: + fetch-depth: 0 + + - name: Run nf-test + id: run_nf_test + uses: ./.github/actions/nf-test + continue-on-error: ${{ matrix.NXF_VER == 'latest-everything' }} + env: + NFT_WORKDIR: ${{ env.NFT_WORKDIR }} + NXF_VERSION: ${{ matrix.NXF_VER }} + with: + profile: ${{ matrix.profile }} + shard: ${{ matrix.shard }} + total_shards: ${{ env.TOTAL_SHARDS }} + + - name: Report test status + if: ${{ always() }} + run: | + if [[ "${{ steps.run_nf_test.outcome }}" == "failure" ]]; then + echo "::error::Test with ${{ matrix.NXF_VER }} failed" + # Add to workflow summary + echo "## ❌ Test failed: ${{ matrix.profile }} | ${{ matrix.NXF_VER }} | Shard ${{ matrix.shard }}/${{ env.TOTAL_SHARDS }}" >> $GITHUB_STEP_SUMMARY + if [[ "${{ matrix.NXF_VER }}" == "latest-everything" ]]; then + echo "::warning::Test with latest-everything failed but will not cause workflow failure. Please check if the error is expected or if it needs fixing." + fi + if [[ "${{ matrix.NXF_VER }}" != "latest-everything" ]]; then + exit 1 + fi + fi + + confirm-pass: + needs: [nf-test] + if: always() + runs-on: # use self-hosted runners + - runs-on=${{ github.run_id }}-confirm-pass + - runner=2cpu-linux-x64 + steps: + - name: One or more tests failed (excluding latest-everything) + if: ${{ contains(needs.*.result, 'failure') }} + run: exit 1 + + - name: One or more tests cancelled + if: ${{ contains(needs.*.result, 'cancelled') }} + run: exit 1 + + - name: All tests ok + if: ${{ contains(needs.*.result, 'success') }} + run: exit 0 + + - name: debug-print + if: always() + run: | + echo "::group::DEBUG: `needs` Contents" + echo "DEBUG: toJSON(needs) = ${{ toJSON(needs) }}" + echo "DEBUG: toJSON(needs.*.result) = ${{ toJSON(needs.*.result) }}" + echo "::endgroup::" diff --git a/.github/workflows/release-announcements.yml b/.github/workflows/release-announcements.yml index 76a9e67e..431d3d44 100644 --- a/.github/workflows/release-announcements.yml +++ b/.github/workflows/release-announcements.yml @@ -14,6 +14,10 @@ jobs: run: | echo "topics=$(curl -s https://nf-co.re/pipelines.json | jq -r '.remote_workflows[] | select(.full_name == "${{ github.repository }}") | .topics[]' | awk '{print "#"$0}' | tr '\n' ' ')" | sed 's/-//g' >> $GITHUB_OUTPUT + - name: get description + id: get_description + run: | + echo "description=$(curl -s https://nf-co.re/pipelines.json | jq -r '.remote_workflows[] | select(.full_name == "${{ github.repository }}") | .description')" >> $GITHUB_OUTPUT - uses: rzr/fediverse-action@master with: access-token: ${{ secrets.MASTODON_ACCESS_TOKEN }} @@ -22,7 +26,7 @@ jobs: # https://docs.github.com/en/developers/webhooks-and-events/webhooks/webhook-events-and-payloads#release message: | Pipeline release! ${{ github.repository }} v${{ github.event.release.tag_name }} - ${{ github.event.release.name }}! - + ${{ steps.get_description.outputs.description }} Please see the changelog: ${{ github.event.release.html_url }} ${{ steps.get_topics.outputs.topics }} #nfcore #openscience #nextflow #bioinformatics @@ -30,7 +34,7 @@ jobs: bsky-post: runs-on: ubuntu-latest steps: - - uses: zentered/bluesky-post-action@80dbe0a7697de18c15ad22f4619919ceb5ccf597 # v0.1.0 + - uses: zentered/bluesky-post-action@6461056ea355ea43b977e149f7bf76aaa572e5e8 # v0.3.0 with: post: | Pipeline release! ${{ github.repository }} v${{ github.event.release.tag_name }} - ${{ github.event.release.name }}! diff --git a/.github/workflows/template_version_comment.yml b/.github/workflows/template-version-comment.yml similarity index 91% rename from .github/workflows/template_version_comment.yml rename to .github/workflows/template-version-comment.yml index 537529bc..c5988af9 100644 --- a/.github/workflows/template_version_comment.yml +++ b/.github/workflows/template-version-comment.yml @@ -9,12 +9,12 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out pipeline code - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5 with: ref: ${{ github.event.pull_request.head.sha }} - name: Read template version from .nf-core.yml - uses: nichmor/minimal-read-yaml@v0.0.2 + uses: nichmor/minimal-read-yaml@1f7205277e25e156e1f63815781db80a6d490b8f # v0.0.2 id: read_yml with: config: ${{ github.workspace }}/.nf-core.yml diff --git a/.github/workflows/update-snapshots.yml b/.github/workflows/update-snapshots.yml new file mode 100644 index 00000000..474d6f47 --- /dev/null +++ b/.github/workflows/update-snapshots.yml @@ -0,0 +1,102 @@ +name: Update nf-test snapshots from a comment +on: + issue_comment: + types: [created] +env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + # renovate: datasource=github-releases depName=askimed/nf-test versioning=semver + NFT_VER: "0.9.2" + NXF_ANSI_LOG: false + # renovate: datasource=github-releases depName=nextflow/nextflow versioning=semver + NXF_VER: "24.10.2" + +jobs: + update-snapshots: + # Only run if comment is on a PR with the main repo, and if it contains the magic keywords + if: > + contains(github.event.comment.html_url, '/pull/') && + contains(github.event.comment.body, '@nf-core-bot update snapshots') && + github.repository == 'nf-core/mhcquant' + runs-on: ubuntu-latest + steps: + # Use the @nf-core-bot token to check out so we can push later + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4 + with: + token: ${{ secrets.nf_core_bot_auth_token }} + + # indication that the command is running + - name: React on comment + uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4 + with: + comment-id: ${{ github.event.comment.id }} + reactions: eyes + + # Action runs on the issue comment, so we don't get the PR by default + # Use the gh cli to check out the PR + - name: Checkout Pull Request + run: gh pr checkout ${{ github.event.issue.number }} + env: + GITHUB_TOKEN: ${{ secrets.nf_core_bot_auth_token }} + + - uses: actions/setup-java@dded0888837ed1f317902acf8a20df0ad188d165 # v5 + with: + distribution: "temurin" + java-version: "17" + + - name: Set up Nextflow + uses: nf-core/setup-nextflow@v2 + with: + version: "${{ env.NXF_VER }}" + + - name: Set up Python + uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6 + with: + python-version: "3.13" + + - name: Set up nf-test + uses: nf-core/setup-nf-test@v1 + with: + version: "${{ env.NFT_VER }}" + install-pdiff: true + + - name: Update snapshot + id: update-snapshots + run: | + nf-test test \ + --profile=docker \ + --verbose \ + --ci \ + --update-snapshot + + - name: Commit & push changes + run: | + git config user.email "core@nf-co.re" + git config user.name "nf-core-bot" + git config push.default upstream + git add . + git status + git commit -m "[automated] Update snapshots" + git push + + - name: react if snapshots were updated + id: react-if-updated + if: steps.commit-and-push.outcome == 'success' + uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4 + with: + comment-id: ${{ github.event.comment.id }} + reactions: hooray + + - name: react if snapshots were not updated + if: steps.commit-and-push.outcome == 'failure' + uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4 + with: + comment-id: ${{ github.event.comment.id }} + reactions: confused + + - name: react if snapshots were not updated + if: steps.commit-and-push.outcome == 'failure' + uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4 + with: + issue-number: ${{ github.event.issue.number }} + body: | + @${{ github.actor }} I tried to update the snapshots, but it didn't work. Please update them manually. diff --git a/.gitpod.yml b/.gitpod.yml deleted file mode 100644 index 83599f63..00000000 --- a/.gitpod.yml +++ /dev/null @@ -1,10 +0,0 @@ -image: nfcore/gitpod:latest -tasks: - - name: Update Nextflow and setup pre-commit - command: | - pre-commit install --install-hooks - nextflow self-update - -vscode: - extensions: - - nf-core.nf-core-extensionpack # https://github.com/nf-core/vscode-extensionpack diff --git a/.nf-core.yml b/.nf-core.yml index 6ced5a51..a38a857f 100644 --- a/.nf-core.yml +++ b/.nf-core.yml @@ -1,7 +1,8 @@ lint: files_unchanged: - .github/CONTRIBUTING.md -nf_core_version: 3.2.1 + - .vscode/settings.json +nf_core_version: 3.4.1 repository_type: pipeline template: author: Jonas Scheid, Steffen Lemke, Leon Bichmann, Marissa Dubbelaar @@ -11,4 +12,7 @@ template: name: mhcquant org: nf-core outdir: . - version: 2.7.0dev + version: 3.1.0 + skip_features: + - fastqc + - igenomes diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 1dec8650..d06777a8 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -4,10 +4,24 @@ repos: hooks: - id: prettier additional_dependencies: - - prettier@3.2.5 - - - repo: https://github.com/editorconfig-checker/editorconfig-checker.python - rev: "3.1.2" + - prettier@3.6.2 + - repo: https://github.com/pre-commit/pre-commit-hooks + rev: v6.0.0 hooks: - - id: editorconfig-checker - alias: ec + - id: trailing-whitespace + args: [--markdown-linebreak-ext=md] + exclude: | + (?x)^( + .*ro-crate-metadata.json$| + modules/nf-core/.*| + subworkflows/nf-core/.*| + .*\.snap$ + )$ + - id: end-of-file-fixer + exclude: | + (?x)^( + .*ro-crate-metadata.json$| + modules/nf-core/.*| + subworkflows/nf-core/.*| + .*\.snap$ + )$ diff --git a/.prettierignore b/.prettierignore index edd29f01..ceb1e1ca 100644 --- a/.prettierignore +++ b/.prettierignore @@ -10,4 +10,6 @@ testing/ testing* *.pyc bin/ +.nf-test/ ro-crate-metadata.json +.nf-test/ diff --git a/.prettierrc.yml b/.prettierrc.yml index c81f9a76..07dbd8bb 100644 --- a/.prettierrc.yml +++ b/.prettierrc.yml @@ -1 +1,6 @@ printWidth: 120 +tabWidth: 4 +overrides: + - files: "*.{md,yml,yaml,html,css,scss,js,cff}" + options: + tabWidth: 2 diff --git a/CHANGELOG.md b/CHANGELOG.md index 53c106f9..30b0ff29 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,36 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/) and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## 3.1.0 - BlüBa - 17/11/25 + +### `Added` + +- Added a peptidoform column to the pipeline output [#376](https://github.com/nf-core/mhcquant/pull/376) +- Added Boxplot of intensity distributions to the MulitQC report [#382](https://github.com/nf-core/mhcquant/pull/382) +- Added a config option to hide outliers in box plots, add plot descriptions [#387](https://github.com/nf-core/mhcquant/pull/387) +- Added a `Fasta` column to the input samplesheet to enable sample-specific FASTA files [#391](https://github.com/nf-core/mhcquant/pull/391) +- Added a column for unique accessions to the pipeline output [#403](https://github.com/nf-core/mhcquant/pull/403) + +### `Fixed` + +- Fixed an issue with not providing the full process name in conf/base.config [#384](https://github.com/nf-core/mhcquant/pull/384) +- Template update 3.1.1, migrate to nf-test [#379](https://github.com/nf-core/mhcquant/pull/379) +- Fixed the binning of the TICs histogram and move the general stats table to the top of the report [#388](https://github.com/nf-core/mhcquant/pull/388) +- Write out FDR-filtered peptide list in global FDR-mode, instead of 100% FDR list [#394](https://github.com/nf-core/mhcquant/pull/394/) +- Update labels for global FDR process configurations [#397](https://github.com/nf-core/mhcquant/pull/397/) +- Remove special character '#' from the header of OpenMS TextExporter output [#403](https://github.com/nf-core/mhcquant/pull/403) +- Fixed an issue in the summary process that led the pipeline crash if deeplc was not specified [#411](https://github.com/nf-core/mhcquant/pull/411) + +### `Dependencies` + +| Dependency | Old version | New version | +| ---------- | ----------- | ----------- | +| `EasyPQP` | 0.1.51 | 0.1.53 | +| `Epicore` | | 0.1.6 | +| `MultiQC` | 1.28.0 | 1.31.0 | +| `Nf-core` | 3.2.1 | 3.4.1 | +| `OpenMS` | 3.4.0 | 3.4.1 | + ## 3.0.0 - Monrepos - 22/05/2025 ### `Added` @@ -16,6 +46,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Added support for CCS-based rescoring with `IM2Deep` feature generator [#358](https://github.com/nf-core/mhcquant/pull/358) - Added multiple plots to MultiQC report by @JuliaGraf [#361](https://github.com/nf-core/mhcquant/pull/361) - Added ability to reduce output columns by @JuliaGraf [#361](https://github.com/nf-core/mhcquant/pull/361) +- Added epicore module by @janaHoffmann1 [#386](https://github.com/nf-core/mhcquant/pull/386) ### `Fixed` @@ -26,6 +57,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Template update 3.2.1 [#369](https://github.com/nf-core/mhcquant/pull/369) - Bump OpenMS version 3.1.0 -> 3.4.0 [#370](https://github.com/nf-core/mhcquant/pull/358) +### `Changed` + +- Temporarily drop conda and epicore testing due to unstable CI tests [#426](https://github.com/nf-core/mhcquant/pull/426) + ### `Dependencies` | Dependency | Old version | New version | diff --git a/README.md b/README.md index ba00c599..dab675dc 100644 --- a/README.md +++ b/README.md @@ -5,23 +5,25 @@ -[![GitHub Actions CI Status](https://github.com/nf-core/mhcquant/actions/workflows/ci.yml/badge.svg)](https://github.com/nf-core/mhcquant/actions/workflows/ci.yml) +[![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://github.com/codespaces/new/nf-core/mhcquant) +[![GitHub Actions CI Status](https://github.com/nf-core/mhcquant/actions/workflows/nf-test.yml/badge.svg)](https://github.com/nf-core/mhcquant/actions/workflows/nf-test.yml) [![GitHub Actions Linting Status](https://github.com/nf-core/mhcquant/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/mhcquant/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/mhcquant/results)[![Cite with Zenodo](http://img.shields.io/badge/DOI-10.5281/zenodo.8427707-1073c8?labelColor=000000)](https://doi.org/10.5281/zenodo.8427707) [![nf-test](https://img.shields.io/badge/unit_tests-nf--test-337ab7.svg)](https://www.nf-test.com) -[![Nextflow](https://img.shields.io/badge/nextflow%20DSL2-%E2%89%A524.04.2-23aa62.svg)](https://www.nextflow.io/) +[![Nextflow](https://img.shields.io/badge/version-%E2%89%A525.04.0-green?style=flat&logo=nextflow&logoColor=white&color=%230DC09D&link=https%3A%2F%2Fnextflow.io)](https://www.nextflow.io/) +[![nf-core template version](https://img.shields.io/badge/nf--core_template-3.4.1-green?style=flat&logo=nfcore&logoColor=white&color=%2324B064&link=https%3A%2F%2Fnf-co.re)](https://github.com/nf-core/tools/releases/tag/3.4.1) [![run with conda](http://img.shields.io/badge/run%20with-conda-3EB049?labelColor=000000&logo=anaconda)](https://docs.conda.io/en/latest/) [![run with docker](https://img.shields.io/badge/run%20with-docker-0db7ed?labelColor=000000&logo=docker)](https://www.docker.com/) [![run with singularity](https://img.shields.io/badge/run%20with-singularity-1d355c.svg?labelColor=000000)](https://sylabs.io/docs/) [![Launch on Seqera Platform](https://img.shields.io/badge/Launch%20%F0%9F%9A%80-Seqera%20Platform-%234256e7)](https://cloud.seqera.io/launch?pipeline=https://github.com/nf-core/mhcquant) -[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23mhcquant-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/mhcquant)[![Follow on Twitter](http://img.shields.io/badge/twitter-%40nf__core-1DA1F2?labelColor=000000&logo=twitter)](https://twitter.com/nf_core)[![Follow on Mastodon](https://img.shields.io/badge/mastodon-nf__core-6364ff?labelColor=FFFFFF&logo=mastodon)](https://mstdn.science/@nf_core)[![Watch on YouTube](http://img.shields.io/badge/youtube-nf--core-FF0000?labelColor=000000&logo=youtube)](https://www.youtube.com/c/nf-core) +[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23mhcquant-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/mhcquant)[![Follow on Bluesky](https://img.shields.io/badge/bluesky-%40nf__core-1185fe?labelColor=000000&logo=bluesky)](https://bsky.app/profile/nf-co.re)[![Follow on Mastodon](https://img.shields.io/badge/mastodon-nf__core-6364ff?labelColor=FFFFFF&logo=mastodon)](https://mstdn.science/@nf_core)[![Watch on YouTube](http://img.shields.io/badge/youtube-nf--core-FF0000?labelColor=000000&logo=youtube)](https://www.youtube.com/c/nf-core) ## Introduction **nfcore/mhcquant** is a best-practice bioinformatics pipeline to process data-dependent acquisition (DDA) immunopeptidomics data. This involves mass spectrometry-based identification and quantification of immunopeptides presented on major histocompatibility complex (MHC) molecules which mediate T cell immunosurveillance. Immunopeptidomics has central implications for clinical research, in the context of [T cell-centric immunotherapies](https://www.sciencedirect.com/science/article/pii/S1044532323000180). -The pipeline is based on the OpenMS C++ framework for computational mass spectrometry. Spectrum files (mzML/Thermo raw/Bruker tdf) serve as inputs and a database search (Comet) is performed based on a given input protein database. Peptide properties are predicted by MS²Rescore. FDR rescoring is applied using Percolator based on a competitive target-decoy approach. For label free quantification all input files undergo identification-based retention time alignment, and targeted feature extraction matching ids between runs. +The pipeline is based on the OpenMS C++ framework for computational mass spectrometry. Spectrum files (mzML/Thermo raw/Bruker tdf) serve as inputs and a database search (Comet) is performed based on a given input protein database. Peptide properties are predicted by MS²Rescore. FDR rescoring is applied using Percolator or Mokapot based on a competitive target-decoy approach. The pipeline supports both local FDR control (per sample-condition group) and global FDR control (across all samples). For label-free quantification, all input files undergo identification-based retention time alignment and targeted feature extraction matching ids between runs. The pipeline can also generate spectrum libraries suitable for DIA-based searches as well as computing consensus epitopes using epicore. ![overview](assets/mhcquant_subway.png) @@ -53,13 +55,29 @@ Each row represents a mass spectrometry run in one of the formats: raw, RAW, mzM Now, you can run the pipeline using: ```bash -nextflow run nf-core/mhcquant +nextflow run nf-core/mhcquant \ -profile \ --input 'samplesheet.tsv' \ --fasta 'SWISSPROT_2020.fasta' \ --outdir ./results ``` +Optional parameters for additional functionality: + +```bash +# Enable quantification, global FDR and spectrum library generation, ion annotations, and consenus epitopes +nextflow run nf-core/mhcquant \ + --input 'samplesheet.tsv' \ + --fasta 'SWISSPROT_2020.fasta' \ + --annotate_ions \ + --epicore \ + --generate_speclib \ + --global_fdr \ + --quantify \ + --outdir ./results \ + -profile docker +``` + > [!WARNING] > Please provide pipeline parameters via the CLI or Nextflow `-params-file` option. Custom config files including those provided by the `-c` Nextflow option can be used to provide any configuration _**except for parameters**_; see [docs](https://nf-co.re/docs/usage/getting_started/configuration#custom-configuration-files). @@ -71,34 +89,53 @@ For more details and further functionality, please refer to the [usage documenta By default the pipeline currently performs identification of MHC class I peptides with HCD settings: -- Preparing spectra dependent on the input format (`PrepareSpectra`) -- Creation of reversed decoy database (`DecoyDatabase`) -- Identification of peptides in the MS/MS spectra (`CometAdapter`) -- Refreshes the protein references for all peptide hits and adds target/decoy information (`PeptideIndexer`) -- Merges identification files with the same `Sample` and `Condition` label (`IDMerger`) -- Prediction of retention times and MS2 intensities (`MS²Rescore`) -- Extract PSM features for Percolator (`PSMFeatureExtractor`) -- Peptide-spectrum-match rescoring using Percolator (`PercolatorAdapter`) -- Filters peptide identification result according to 1\% FDR (`IDFilter`) -- Converts identification result to tab-separated files (`TextExporter`) -- Converts identification result to mzTab files (`MzTabExporter`) +- **Spectra Preparation**: Preparing spectra dependent on the input format (`PREPARE_SPECTRA` subworkflow) +- **Database Preparation**: Creation of reversed decoy database (`DecoyDatabase`) +- **Peptide Identification**: Identification of peptides in the MS/MS spectra (`CometAdapter`) +- **Database Indexing**: Refreshes protein references for all peptide hits and adds target/decoy information (`PeptideIndexer`) +- **Identification Merging**: Merges identification files with the same `Sample` and `Condition` label (`IDMerger`) +- **Rescoring**: Feature prediction and peptide-spectrum-match rescoring (`RESCORE` subworkflow) + - Prediction of retention times and MS2 intensities (`MS²Rescore`) + - Extract PSM features for rescoring engines (`PSMFeatureExtractor`) + - Peptide-spectrum-match rescoring using Percolator or Mokapot (`PercolatorAdapter`) + - Filters peptide identification result according to configurable FDR threshold (`IDFilter`) +- **Export**: Converts identification result to tab-separated files (`TextExporter`) + +### FDR Control Modes + +The pipeline supports two FDR control strategies: + +- **Local FDR** (default): FDR control applied per `Sample` and `Condition` group +- **Global FDR**: FDR control applied across all samples in the dataset (enable with `--global_fdr`) ### Additional Steps Additional functionality contained by the pipeline currently includes: -#### Quantification +#### Quantification (`QUANT` subworkflow) -- Corrects retention time distortions between runs (`MapAlignerIdentification`) -- Applies retention time transformations to runs (`MapRTTransformer`) -- Detects features in MS1 data based on peptide identifications (`FeatureFinderIdentification`) -- Group corresponding features across label-free experiments (`FeatureLinkerUnlabeledKD`) -- Resolves ambiguous annotations of features with peptide identifications (`IDConflictResolver`) +When enabled with `--quantify`, the pipeline performs label-free quantification: -#### Output +- **Alignment**: Corrects retention time distortions between runs (`MAP_ALIGNMENT` subworkflow) + - Corrects retention time distortions between runs (`MapAlignerIdentification`) + - Applies retention time transformations to runs (`MapRTTransformer`) +- **Feature Processing**: Detects and processes features (`PROCESS_FEATURE` subworkflow) + - Detects features in MS1 data based on peptide identifications (`FeatureFinderIdentification`) + - Group corresponding features across label-free experiments (`FeatureLinkerUnlabeledKD`) + - Resolves ambiguous annotations of features with peptide identifications (`IDConflictResolver`) + +#### Spectrum Library Generation (`SPECLIB` subworkflow) + +When enabled with `--generate_speclib`, the pipeline generates spectrum libraries suitable for DIA-based searches. Outputs one library per sample or a single library across all samples (if global FDR mode is enabled with `--global_fdr`). + +#### Ion Annotation (`IONANNOTATOR` subworkflow) + +The pipeline annotates the final list of peptides with their respective ions and charges: - Annotates final list of peptides with their respective ions and charges (`IonAnnotator`) +#### Output + ## Documentation To see the the results of a test run with a full size dataset refer to the [results](https://nf-co.re/mhcquant/results) tab on the nf-core website pipeline page. @@ -107,7 +144,7 @@ For more details about the output files and reports, please refer to the 1. [Nextflow installation](https://nf-co.re/usage/installation) 2. Pipeline configuration - - [Pipeline installation](https://nf-co.re/usage/local_installation) + - [Pipeline installation](https://nf-co.re/docs/usage/getting_started/offline) - [Adding your own system config](https://nf-co.re/usage/adding_own_config) 3. [Running the pipeline](https://nf-co.re/mhcquant/docs/usage.md) - This includes tutorials, FAQs, and troubleshooting instructions @@ -131,6 +168,7 @@ Helpful contributors: - [Sven Fillinger](https://github.com/sven1103) - [Kevin Menden](https://github.com/KevinMenden) - [Julia Graf](https://github.com/JuliaGraf) +- [Jana Hoffmann](https://github.com/janaHoffmann1) ## Contributions and Support @@ -140,7 +178,13 @@ For further information or help, don't hesitate to get in touch on the [Slack `# ## Citations -If you use nf-core/mhcquant for your analysis, please cite it using the following doi: [10.5281/zenodo.1569909](https://doi.org/10.5281/zenodo.1569909) and the corresponding manuscript: +If you use nf-core/mhcquant for your analysis, please cite the corresponding manuscript: [10.1186/s13059-025-03763-8](https://doi.org/10.1186/s13059-025-03763-8) + +> **MHCquant2 refines immunopeptidomics tumor antigen discovery** +> +> Jonas Scheid, Steffen Lemke, Naomi Hoenisch-Gravel, Anna Dengler, Timo Sachsenberg, Arthur Declerq, Ralf Gabriels, Jens Bauer, Marcel Wacker, Leon Bichmann, Lennart Martens, Marissa L. Dubbelaar, Sven Nahnsen & Juliane S. Walz +> +> _Genome Biology_ 2025 26 (1), 290. doi: [10.1021/acs.jproteome.9b00313](https://pubs.acs.org/doi/10.1021/acs.jproteome.9b00313) > **MHCquant: Automated and Reproducible Data Analysis for Immunopeptidomics** > diff --git a/assets/250120_unimod_tables.xml b/assets/250120_unimod_tables.xml index 7e0313ee..5758157b 100644 --- a/assets/250120_unimod_tables.xml +++ b/assets/250120_unimod_tables.xml @@ -27855,12 +27855,12 @@ Szychowski J, Mahdavi A, Hodas JJ, Bagert JD, Ngo JT, Landgraf P, Dieterich DC, Chemistry and Biology -Volume 9, Issue 10, 1 October 2002, Pages 1149-1159 +Volume 9, Issue 10, 1 October 2002, Pages 1149-1159 Chemistry-based functional proteomics reveals novel members of the deubiquitinating enzyme family Chemistry and Biology -Volume 9, Issue 10, 1 October 2002, Pages 1149-1159 +Volume 9, Issue 10, 1 October 2002, Pages 1149-1159 Chemistry-based functional proteomics reveals novel members of the deubiquitinating enzyme family diff --git a/assets/multiqc_config.yml b/assets/multiqc_config.yml index e6c75d4f..6db209cc 100644 --- a/assets/multiqc_config.yml +++ b/assets/multiqc_config.yml @@ -3,9 +3,9 @@ custom_logo_url: https://github.com/nf-core/mhcquant custom_logo_title: "nf-core/mhcquant" report_comment: > - This report has been generated by the nf-core/mhcquant + This report has been generated by the nf-core/mhcquant analysis pipeline. For information about how to interpret these results, please see the - documentation. + documentation. report_section_order: "nf-core-mhcquant-methods-description": order: -1000 @@ -17,6 +17,9 @@ report_section_order: export_plots: true disable_version_detection: true +# Control how outliers are displayed in box plots +boxplot_boxpoints: false + # Modules to run run_modules: - custom_content @@ -24,6 +27,15 @@ run_modules: # Custom tables and plots custom_data: + # Summary of general statistics + stats_table: + plot_type: "table" + file_format: "csv" + section_name: "General Statistics" + pconfig: + id: "general_stats" + title: "General Statistics" + # Summary of chromatogram plot chromatogram: plot_type: "linegraph" @@ -43,7 +55,7 @@ custom_data: # Mass error plot mass_error: - plot_type: "linegraph" + plot_type: "boxplot" file_format: "tsv" section_name: "Fragment mass error" description: | @@ -53,20 +65,13 @@ custom_data: or parts-per-million (ppm). pconfig: xlab: "Mass deviation [Da/ppm]" - ylab: "Frequency" - - stats_table: - plot_type: "table" - file_format: "csv" - section_name: "General Statistics" - pconfig: - id: "general_stats" - title: "General Statistics" len_plot: plot_type: "linegraph" file_format: "csv" section_name: "Peptide lengths" + description: | + This plot shows the distribution of peptide sequence lengths to assess variability and typical length ranges. pconfig: id: "length_dist" title: "Distribution of peptide lengths" @@ -77,6 +82,9 @@ custom_data: plot_type: "linegraph" file_format: "csv" section_name: "Mass-to-Charge" + description: | + This plot displays the distribution of precursor ion mass-to-charge (m/z) values detected in the dataset. + It helps identify the typical m/z ranges and assess the overall coverage and instrument performance during acquisition. pconfig: id: "histogram_mz" title: "Mass-to-Charge Histogram" @@ -87,6 +95,9 @@ custom_data: plot_type: "linegraph" file_format: "csv" section_name: "Retention time" + description: | + This plot shows the distribution of peptide retention times across the chromatographic gradient. + It provides insight into peptide elution profiles and helps assess gradient performance and sample complexity. pconfig: id: "histogram_rt" title: "Retention time Histogram" @@ -97,35 +108,56 @@ custom_data: plot_type: "linegraph" file_format: "csv" section_name: "Q-Value" + description: | + A q-value histogram in Percolator visualizes q-value distributions for PSMs, helping set the FDR threshold (typically 1%). + It ensures only high-confidence identifications are retained, with a sharp drop-off beyond the threshold. pconfig: id: "histogram_scores" title: "Percolator q-value Histogram" - description: "A q-value histogram in Percolator visualizes q-value distributions for PSMs, helping set the FDR threshold (typically 1%). It ensures only high-confidence identifications are retained, with a sharp drop-off beyond the threshold." xlab: "q-value" ylab: "Frequency" scores_plot_xcorr: - plot_type: "linegraph" + plot_type: "boxplot" file_format: "csv" section_name: "Xcorr-Value" + description: | + The Comet Xcorr boxplot visualizes the cross-correlation (Xcorr) score distribution for PSMs, indicating match quality. + Higher Xcorr values signify better peptide-spectrum matches. + This helps set a threshold to filter out low-confidence identifications. pconfig: - id: "histogram_scores_xcorr" - title: "Comet Xcorr Histogram" - description: "A Comet Xcorr histogram visualizes the cross-correlation (Xcorr) score distribution for PSMs, indicating match quality. Higher Xcorr values signify better peptide-spectrum matches. This helps set a threshold to filter out low-confidence identifications." + id: "scores_xcorr" + title: "Comet Xcorr Distribution" xlab: "Xcorr" ylab: "Frequency" -#id: custom_box -#plot_type: 'box' -#section_name: 'Custom box plot' -#description: "Box plot for a sample" -#pconfig: -# title: 'Box plot' + + peptide_intensity_plot: + plot_type: "boxplot" + file_format: "csv" + section_name: "Peptide Intensity" + description: | + Comparison of log2-transformed peptide intensities across samples. + Helps assess data consistency and detect potential outliers or batch effects. + pconfig: + id: "peptide_intensity" + title: "Peptide Intensity Distribution" + xlab: "log2(Intensity)" + + epicore_length_distribution: + file_format: "html" + section_name: "Epicore length distribution" + description: "The histogram visualizes the number and length of the input peptides in the evidence file in grey. The red bars correspond to the number of identified consensus epitopes and their length." + + epicore_intensity_histogram: + file_format: "html" + section_name: "Epicore intensity histogram" + description: "The histogram visualizes how many peptides contribute to each identified consensus epitope." sp: chromatogram: fn: "*_chrom.csv" mass_error: - fn: "*_binned.tsv" + fn: "*frag_mass_err.tsv" stats_table: fn: "*_general_stats.csv" len_plot: @@ -137,7 +169,14 @@ sp: qvalue_plot: fn: "*_histogram_scores.csv" scores_plot_xcorr: - fn: "*_histogram_xcorr_scores.csv" + fn: "*_xcorr_scores.csv" + peptide_intensity_plot: + fn: "*_peptide_intensity.csv" + epicore_length_distribution: + fn: "epicore_length_distribution.html" + epicore_intensity_histogram: + fn: "epicore_intensity_histogram.html" + ### Define the order of sections #module_order: # - custom_content diff --git a/assets/samplesheet.tsv b/assets/samplesheet.tsv index b412d973..8ac7f56e 100644 --- a/assets/samplesheet.tsv +++ b/assets/samplesheet.tsv @@ -1,13 +1,7 @@ -ID Sample Condition ReplicateFileName -1 WT A /path/to/MS/files/WT_A1.raw -2 WT A /path/to/MS/files/WT_A2.raw -3 WT A /path/to/MS/files/WT_A3.raw -4 WT B /path/to/MS/files/WT_B1.raw -5 WT B /path/to/MS/files/WT_B2.raw -6 WT B /path/to/MS/files/WT_B3.raw -7 KO A /path/to/MS/files/KO_A1.raw -8 KO A /path/to/MS/files/KO_A2.raw -9 KO A /path/to/MS/files/KO_A3.raw -10 KO B /path/to/MS/files/KO_B1.raw -11 KO B /path/to/MS/files/KO_B2.raw -12 KO B /path/to/MS/files/KO_B3.raw +ID Sample Condition ReplicateFileName Fasta +1 PBMC009 A ftp://ftp.pride.ebi.ac.uk/pride/data/archive/2019/10/PXD011628/PBMC009_msms37.raw https://raw.githubusercontent.com/nf-core/test-datasets/mhcquant/testdata/UP000005640_9606.fasta +2 PBMC009 A ftp://ftp.pride.ebi.ac.uk/pride/data/archive/2019/10/PXD011628/PBMC009_msms36.raw https://raw.githubusercontent.com/nf-core/test-datasets/mhcquant/testdata/UP000005640_9606.fasta +3 PBMC009 A ftp://ftp.pride.ebi.ac.uk/pride/data/archive/2019/10/PXD011628/PBMC009_msms35.raw https://raw.githubusercontent.com/nf-core/test-datasets/mhcquant/testdata/UP000005640_9606.fasta +4 PBMC007 B ftp://ftp.pride.ebi.ac.uk/pride/data/archive/2019/10/PXD011628/PBMC007_msms31.raw https://raw.githubusercontent.com/nf-core/test-datasets/mhcquant/testdata/2025_02_human_swissprot.fasta +5 PBMC007 B ftp://ftp.pride.ebi.ac.uk/pride/data/archive/2019/10/PXD011628/PBMC007_msms30.raw https://raw.githubusercontent.com/nf-core/test-datasets/mhcquant/testdata/2025_02_human_swissprot.fasta +6 PBMC007 B ftp://ftp.pride.ebi.ac.uk/pride/data/archive/2019/10/PXD011628/PBMC007_msms29.raw https://raw.githubusercontent.com/nf-core/test-datasets/mhcquant/testdata/2025_02_human_swissprot.fasta diff --git a/assets/schema_input.json b/assets/schema_input.json index 3f71d4ed..253b30dd 100644 --- a/assets/schema_input.json +++ b/assets/schema_input.json @@ -30,6 +30,13 @@ "exists": true, "pattern": "^\\S+\\.(raw|RAW|mzML|mzML.gz|d|d.tar|d.tar.gz|d.zip)$", "errorMessage": "MS file cannot contain spaces and must have one of the extensions: raw | RAW | mzML | mzML.gz | d | d.tar | d.tar.gz | d.zip" + }, + "Fasta": { + "type": "string", + "format": "path", + "exists": true, + "pattern": "^\\S+\\.(fasta|fa|fas|fna|faa|ffn)$", + "errorMessage": "FASTA file cannot contain spaces and must have one of the extensions: fasta | fa | fas | fna | faa | ffn" } }, "required": ["ID", "Sample", "Condition", "ReplicateFileName"] diff --git a/bin/chromatogram_extractor.py b/bin/chromatogram_extractor.py index ca870e0e..46f6bd51 100755 --- a/bin/chromatogram_extractor.py +++ b/bin/chromatogram_extractor.py @@ -31,7 +31,7 @@ def main(): mzml_file.load(input_file, exp) # Get RT and Spectrum TIC of MS1 Spectra - chromatogram = [(spectrum.getRT() / 60 , spectrum.calculateTIC()) for spectrum in exp.getSpectra() if spectrum.getMSLevel() == 1] + chromatogram = [(round(spectrum.getRT() / 60, 1) , spectrum.calculateTIC()) for spectrum in exp.getSpectra() if spectrum.getMSLevel() == 1] logging.info(f'Found {len(chromatogram)} MS1 Spectra') try: logging.info(f'RT range: {round(chromatogram[0][0],2)} - {round(chromatogram[-1][0],2)} [min]') diff --git a/bin/ms2rescore_cli.py b/bin/ms2rescore_cli.py index 9600d8c6..9cf2cfc6 100755 --- a/bin/ms2rescore_cli.py +++ b/bin/ms2rescore_cli.py @@ -24,7 +24,7 @@ def parse_cli_arguments_to_config(**kwargs): for key, value in kwargs.items(): # Skip these arguments since they need to set in a nested dict of feature_generators - if key in ["ms2pip_model", "ms2_tolerance", "rng", "calibration_set_size"]: + if key in ["ms2pip_model", "ms2_tolerance", "test_fdr", "calibration_set_size"]: continue elif key == "feature_generators": @@ -60,6 +60,7 @@ def parse_cli_arguments_to_config(**kwargs): "write_txt": False, "write_flashlfq": False, "max_workers": kwargs["processes"], + "test_fdr" : kwargs["test_fdr"] } if value == "percolator": logging.info( @@ -80,7 +81,7 @@ def rescore_idxml(input_file, output_file, config) -> None: psm_list = reader.read_file() # Rescore - rescore(config, psm_list) + rescore(config, psm_list, ) # Filter out PeptideHits within PeptideIdentification(s) that could not be processed by all feature generators peptide_ids_filtered = filter_out_artifact_psms(psm_list, reader.peptide_ids) @@ -157,6 +158,7 @@ def filter_out_artifact_psms( default=0.15, ) @click.option("-re", "--rescoring_engine", help="Either mokapot or percolator (default: `mokapot`)", default="mokapot") +@click.option("--test_fdr", help="Test FDR for Mokapot (default: `0.05`)", type=float, default=0.05) @click.option("-d", "--id_decoy_pattern", help="Regex decoy pattern (default: `DECOY_`)", default="^DECOY_") @click.option( "-lsb", diff --git a/bin/summarize_results.py b/bin/summarize_results.py index fb445444..c63d5b83 100755 --- a/bin/summarize_results.py +++ b/bin/summarize_results.py @@ -103,10 +103,12 @@ def process_file(file, prefix, quantify, keep_cols): n_psms = np.sum(data["psm"]) else: data = pd.read_csv(file, sep='\t') + # Remove the special character '#' from the first column name + data.rename(columns={data.columns[0]: data.columns[0].replace('#', '')}, inplace=True) n_psms = 0 # Check if all required columns are present in the DataFrame - required_columns = ['sequence', 'accessions', 'mz', 'observed_retention_time_best', 'score', 'COMET:xcorr'] + required_columns = ['sequence', 'accessions', 'mz', 'rt', 'score', 'COMET:xcorr'] missing_columns = set(required_columns) - set(data.columns) if data.shape[0] > 0: # If the DataFrame is not empty if missing_columns: @@ -118,23 +120,26 @@ def process_file(file, prefix, quantify, keep_cols): data.to_csv(f"{prefix}.tsv", sep='\t', index=False) return + # Remove modification information from the sequence column + data["peptidoform"] = data["sequence"] + data["sequence"] = data["sequence"].apply(lambda seq: re.sub(r'\(.*?\)', '', seq)) + # --------------------------------- # Length distribution plot # --------------------------------- - # Remove everything inside parentheses, including the parentheses. - seq_length = data["sequence"].apply(lambda seq: len(re.sub(r'\(.*?\)', '', seq))) + seq_length = data["sequence"].apply(lambda seq: len(seq)) seq_length = dict(Counter(seq_length)) with open(f"{prefix}_peptide_length.csv", "w") as f: for length, count in seq_length.items(): - f.write(f"{length},{count}\n") + f.write(f"{length},{count / len(data.index)}\n") # --------------------------------- # General statistics # --------------------------------- n_peptides = len(set(data["sequence"])) - n_modified_peptides = sum(1 for s in set(data["sequence"]) if '(' in s) + n_modified_peptides = sum(1 for s in set(data["peptidoform"]) if '(' in s) # Split the accession codes and count each protein accession individually n_proteins = len(set([protein for entry in data["accessions"] for protein in entry.split(';')])) with open(f"{prefix}_general_stats.csv", "w") as f: @@ -146,9 +151,8 @@ def process_file(file, prefix, quantify, keep_cols): # --------------------------------- histograms = [[data["mz"].astype(float), f"{prefix}_histogram_mz.csv"], - [data["observed_retention_time_best"].astype(float), f"{prefix}_histogram_rt.csv"], - [data["score"].astype(float), f"{prefix}_histogram_scores.csv"], - [data["COMET:xcorr"].astype(float), f"{prefix}_histogram_xcorr_scores.csv"]] + [data["rt"].astype(float), f"{prefix}_histogram_rt.csv"], + [data["score"].astype(float), f"{prefix}_histogram_scores.csv"]] for values, title in histograms: hist, bin_edges = np.histogram(values, bins='auto') @@ -157,6 +161,19 @@ def process_file(file, prefix, quantify, keep_cols): bin_midpoint = (bin_edges[i] + bin_edges[i + 1]) / 2 f.write(f'{bin_midpoint},{hist[i]}\n') + # --------------------------------- + # Box plots + # --------------------------------- + data["COMET:xcorr"].astype(float).to_csv( + f"{prefix}_xcorr_scores.csv", index=False, header=False + ) + if 'intensity_cf' in data.columns: + np.log2(data["intensity_cf"].astype(float)).to_csv( + f"{prefix}_peptide_intensity.csv", + index=False, + header=False + ) + # Filter the columns down to a user-defined subset of columns if keep_cols: missing_columns = set(keep_cols) - set(data.columns) @@ -171,6 +188,13 @@ def process_file(file, prefix, quantify, keep_cols): keep_cols = list(dict.fromkeys(keep_cols)) data = data.loc[:, keep_cols] + # Round all floating point values to 5 decimal places to ensure nf-test checksum stability is guaranteed + float_cols = data.select_dtypes(include=['float']).columns + data.loc[:, float_cols] = data.loc[:, float_cols].round(5) + + # Add a column with unique protein accessions + data['unique_accessions'] = data['accessions'].map(lambda x: ';'.join(dict.fromkeys(x.split(';')))) + data.to_csv(f"{prefix}.tsv", sep='\t', index=False) diff --git a/conf/base.config b/conf/base.config index 7d6b2fdd..9d0500d2 100644 --- a/conf/base.config +++ b/conf/base.config @@ -14,7 +14,7 @@ process { memory = { 4.GB * task.attempt } time = { 2.h * task.attempt } - errorStrategy = { task.exitStatus in ((130..145) + 104) ? 'retry' : 'finish' } + errorStrategy = { task.exitStatus in ((130..145) + 104 + 175) ? 'retry' : 'finish' } maxRetries = 1 maxErrors = '-1' @@ -46,6 +46,11 @@ process { withLabel:process_high_memory { memory = { 200.GB * task.attempt } } + withLabel:process_high_mem_high_cpu { + cpus = { 12 * task.attempt } + memory = { 200.GB * task.attempt } + time = { 16.h * task.attempt } + } withLabel:error_ignore { errorStrategy = 'ignore' } @@ -53,9 +58,13 @@ process { errorStrategy = 'retry' maxRetries = 2 } - withName:TDF2MZML { + withName:NFCORE_MHCQUANT:MHCQUANT:PREPARE_SPECTRA:TDF2MZML { cpus = { 1 * task.attempt, 'cpus' } memory = { 10.GB * task.attempt, 'memory' } time = { 16.h * task.attempt, 'time' } } + withLabel: process_gpu { + ext.use_gpu = { workflow.profile.contains('gpu') } + accelerator = { workflow.profile.contains('gpu') ? 1 : null } + } } diff --git a/conf/modules.config b/conf/modules.config index a4d1d886..c5b93fae 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -176,7 +176,7 @@ process { "-remove_decoys", "-precursor:length '${params.peptide_min_length}:${params.peptide_max_length}'", "-delete_unreferenced_peptide_hits", - (params.fdr_threshold == '0.01') ? "-score:pep 0.05" : "-score:pep " + params.fdr_threshold + (params.fdr_threshold == '0.01') ? "-score:peptide 0.05" : "-score:peptide " + params.fdr_threshold ].join(' ').trim() publishDir = [ enabled: false @@ -184,7 +184,7 @@ process { } withName: 'OPENMS_IDFILTER_GLOBAL' { - label = 'process_high_memory' + label = 'process_medium' ext.prefix = {"${meta.id}_pout_filtered"} ext.args = [ "-remove_decoys", @@ -217,6 +217,7 @@ process { "--perform_rt_calibration False", "--perform_im_calibration False", "--nofdr", + "--diannpqp", ].join(' ').trim() publishDir = [ path: {"${params.outdir}/spectrum_library"}, @@ -225,6 +226,21 @@ process { ] } + withName: 'EASYPQP_LIBRARY_GLOBAL' { + label = 'process_high_memory' + ext.args = [ + "--perform_rt_calibration False", + "--perform_im_calibration False", + "--nofdr", + "--diannpqp", + ].join(' ').trim() + publishDir = [ + path: {"${params.outdir}/global_fdr"}, + mode: params.publish_dir_mode, + pattern: 'global_speclib.tsv' + ] + } + withName: 'OPENMS_IDFILTER_QUANT' { ext.prefix = {"${meta.spectra}_fdr_filtered"} ext.args = "-best:spectrum_per_peptide 'sequence+charge+modification'" @@ -335,13 +351,6 @@ process { ] } - withName: 'DATAMASH_HISTOGRAM' { - ext.prefix = {"${meta.spectra}"} - publishDir = [ - enabled: false - ] - } - withName: 'MS2RESCORE' { ext.args = [ "--ms2_tolerance ${2 * params.fragment_mass_tolerance}", @@ -379,7 +388,7 @@ process { } withName: 'OPENMS_PERCOLATORADAPTER_GLOBAL' { - label = 'process_high' + label = 'process_high_mem_high_cpu' ext.args = [ "-seed 4711", "-trainFDR 0.05", @@ -439,7 +448,48 @@ process { } withName: 'SUMMARIZE_RESULTS' { - ext.args = "--columns sequence,score,score_type,psm,rt,mz,charge,accessions,aa_before,aa_after,start,end,COMET:deltaCn,COMET:deltaLCn,COMET:lnExpect,COMET:xcorr,rt_diff_best,observed_retention_time_best,predicted_retention_time_best,spec_pearson,std_abs_diff,ccs_observed_im2deep,ccs_predicted_im2deep,ccs_error_im2deep" + ext.args = [ + "--columns ", + [ + "peptidoform", + "sequence", + "score", "score_type", + "psm", + "rt", + "mz", + "charge", + "accessions", + "aa_before", "aa_after", + "start", "end", + "COMET:deltaCn", "COMET:deltaLCn", "COMET:lnExpect", "COMET:xcorr", + "rt_diff_best", + "observed_retention_time_best", "predicted_retention_time_best", + "spec_pearson", + "std_abs_diff", + "ccs_observed_im2deep", "ccs_predicted_im2deep", "ccs_error_im2deep" + ].join(',').trim(), + ].join(' ').trim() + publishDir = [ + path: {"${params.outdir}"}, + mode: params.publish_dir_mode, + pattern: "*.tsv", + enabled: !params.epicore + ] + } + + withName: 'EPICORE' { + ext.args = [ + "--seq_column sequence", + "--protacc_column accessions", + params.quantify ? "--intensity_column intensity_cf" : "--intensity_column ''", + "--start_column ''", + "--end_column ''", + "--mod_pattern ''", + "--delimiter ';'", + "--min_overlap ${params.epicore_min_overlap}", + "--max_step_size ${params.epicore_max_step_size}", + "--min_epi_length ${params.epicore_min_epi_length}" + ].join(' ').trim() publishDir = [ path: {"${params.outdir}"}, mode: params.publish_dir_mode, diff --git a/conf/test_full.config b/conf/test_full.config index 666ca25a..4fc59bc5 100644 --- a/conf/test_full.config +++ b/conf/test_full.config @@ -16,15 +16,14 @@ params { // Input data input = params.pipelines_testdata_base_path + 'mhcquant/testdata/sample_sheet_full.tsv' - fasta = params.pipelines_testdata_base_path + 'mhcquant/testdata/UP000005640_9606.fasta' // Test multiple modifications fixed_mods = 'Oxidation (M),Carbamidomethyl (C)' variable_mods = 'Oxidation (M),Carbamidomethyl (C)' // Pipeline settings - filter_mzml = true quantify = true generate_speclib = true annotate_ions = true + epicore = true } diff --git a/conf/test_ionannotator.config b/conf/test_ionannotator.config index bf0cd9f7..eea51b67 100644 --- a/conf/test_ionannotator.config +++ b/conf/test_ionannotator.config @@ -28,6 +28,7 @@ params { fasta = params.pipelines_testdata_base_path + 'mhcquant/testdata/UP000005640_9606.fasta' // Pipeline settings + fdr_threshold = 0.03 annotate_ions = true use_x_ions = true use_z_ions = true diff --git a/conf/test_percolator.config b/conf/test_percolator.config deleted file mode 100644 index ba7b9f8d..00000000 --- a/conf/test_percolator.config +++ /dev/null @@ -1,32 +0,0 @@ -/* -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Nextflow config file for running minimal tests with MS²Rescore and Percolator -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Defines input files and everything required to run a fast and simple pipeline test. - - Use as follows: - nextflow run nf-core/mhcquant -profile test_percolator, --outdir - ----------------------------------------------------------------------------------------- -*/ - -// Limit resources so that this can run on GitHub Actions -process { - resourceLimits = [ - cpus: 2, - memory: '6.GB', - time: '2.h' - ] -} - -params { - config_profile_name = 'Test Percolator profile' - config_profile_description = 'Minimal test dataset to check pipeline function with MS2PIP' - - // Input data - input = params.pipelines_testdata_base_path + 'mhcquant/testdata/HepG2_sample_sheet.tsv' - fasta = params.pipelines_testdata_base_path + 'mhcquant/testdata/UP000005640_9606.fasta' - - // Pipeline settings - rescoring_engine = 'percolator' -} diff --git a/docs/output.md b/docs/output.md index 7b4921d1..cba83e93 100644 --- a/docs/output.md +++ b/docs/output.md @@ -19,26 +19,31 @@ The directories listed below will be created in the results directory after the The TSV output of MHCquant is a tab-delimited file holding information about FDR-filtered peptides and their properties such as retention time, charge, mass-to-charge, and protein accessions. Additionally, a selected number of features produced by `Comet` and `MS²Rescore` are stored. Understanding these scores and features is crucial in narrowing down peptides of interest. -| **Tool** | **Metric** | **Description** | -| -------- | ------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| Comet | `COMET:xcorr` | Cross-correlation score between observed and theoretical spectra; higher scores indicate better matches. | -| Comet | `COMET:deltaCn` | Normalized difference between the top two XCorr scores; higher values indicate better discrimination between top matches. | -| Comet | `COMET:deltaLCn` | Similar to deltaCn but considers the difference between the top match and the best match with a different peptide sequence. | -| Comet | `COMET:lnExpect` | Natural logarithm of the Expectation value; lower values suggest more statistically significant matches. | -| DeepLC | `predicted_retention_time_best` | Predicted retention time for the precursor peak (all PSMs with the same sequence, modifications, and charge) closest to the predicted retention time. | -| DeepLC | `observed_retention_time_best` | Observed retention time for the precursor peak (all PSMs with the same sequence, modifications, and charge) closest to the predicted retention time. | -| DeepLC | `rt_diff_best` | Difference between observed and predicted retention time for the precursor peak (all PSMs with the same sequence, modifications, and charge) closest to the predicted retention time. | -| MS2PIP | `spec_pearson` | Pearson correlation coefficient between observed and predicted b and y ion intensities of MS2 spectra; higher values indicate better agreement. | -| MS2PIP | `std_abs_diff` | Standard deviation of absolute differences between observed and predicted b and y ion intensities; lower values indicate better agreement. | -| IM2Deep | `ccs_observed_im2deep` | Observed peptide collisional cross-section (CCS) value. | -| IM2Deep | `ccs_predicted_im2deep` | Predicted peptide CCS value by IM2Deep. | -| IM2Deep | `ccs_error_im2deep` | Difference between observed and predicted CCS values; indicates prediction accuracy. | +| **Tool** | **Metric** | **Description** | +| -------- | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| Comet | `COMET:xcorr` | Cross-correlation score between observed and theoretical spectra; higher scores indicate better matches. | +| Comet | `COMET:deltaCn` | Normalized difference between the top two XCorr scores; higher values indicate better discrimination between top matches. | +| Comet | `COMET:deltaLCn` | Similar to deltaCn but considers the difference between the top match and the best match with a different peptide sequence. | +| Comet | `COMET:lnExpect` | Natural logarithm of the Expectation value; lower values suggest more statistically significant matches. | +| DeepLC | `predicted_retention_time_best` | Predicted retention time for the precursor peak (all PSMs with the same sequence, modifications, and charge) closest to the predicted retention time. | +| DeepLC | `observed_retention_time_best` | Observed retention time for the precursor peak (all PSMs with the same sequence, modifications, and charge) closest to the predicted retention time. | +| DeepLC | `rt_diff_best` | Difference between observed and predicted retention time for the precursor peak (all PSMs with the same sequence, modifications, and charge) closest to the predicted retention time. | +| MS2PIP | `spec_pearson` | Pearson correlation coefficient between observed and predicted b and y ion intensities of MS2 spectra; higher values indicate better agreement. | +| MS2PIP | `std_abs_diff` | Standard deviation of absolute differences between observed and predicted b and y ion intensities; lower values indicate better agreement. | +| IM2Deep | `ccs_observed_im2deep` | Observed peptide collisional cross-section (CCS) value. | +| IM2Deep | `ccs_predicted_im2deep` | Predicted peptide CCS value by IM2Deep. | +| IM2Deep | `ccs_error_im2deep` | Difference between observed and predicted CCS values; indicates prediction accuracy. | +| Epicore | `entire_epitope_sequence` | Sequences of epicore groups to which the peptide belongs. | +| Epicore | `core_epitope_sequence` | Core sequences of epicore groups to which the peptide belongs. | +| Epicore | `proteome_occurrence` | Protein accessions and positions of core epitopes. | +| Epicore | `consensus_epitope_intensity` | Sum of intensities of all peptides belonging to the epicore group. | +| Epicore | `relative_consensus_epitope_intensity` | Relative epicore group intensity (core_epitope_intensity divided by the total intensity of peptides in output file). | The TSV file in quantification mode (by using `--quantify`) additionally holds the columns `rt_cf|0|1|..`, `mz_cf|0|1|..`, `intensity_cf|0|1|..`, and `charge_cf|0|1|..`, where `cf` (consensus feature) represents the aggregated value of the individual MS runs (`0|1|..`) that are part of the `_` group in the input samplesheet. Use e.g. the individual intensities of MS runs to compare two groups and conduct a differential-presentation analysis. #### mzTab -The mzTab output file follows the a [HUPO-PSI format]() and combines all information of the sample-condition group extracted from a database search throughout the pipeline. A detailed explanation of the respective entries are elaborately explained [here](https://psidev.info/sites/default/files/2017-07/R2_The_ten_minute_guide_to_mzTab.pdf). MzTab files are compatible with the PRIDE Archive - proteomics data repository and can be uploaded as search files. +The mzTab output file follows the a [HUPO-PSI format](https://doi.org/10.1074/mcp.O113.036681) and combines all information of the sample-condition group extracted from a database search throughout the pipeline. A detailed explanation of the respective entries are elaborately explained [here](https://github.com/HUPO-PSI/mzTab/blob/master/specification_document-releases/1_0-Proteomics-Release/20minute_guide_mzTab.pdf). MzTab files are compatible with the PRIDE Archive - proteomics data repository and can be uploaded as search files. MzTab files contain many columns and annotate the most important information - here are a few outpointed: @@ -111,7 +116,6 @@ Results generated by MultiQC collate pipeline QC from supported tools e.g. FastQ Output files - `pipeline_info/` - - Reports generated by Nextflow: `execution_report.html`, `execution_timeline.html`, `execution_trace.txt` and `pipeline_dag.html`. - Reports generated by the pipeline: `software_versions.yml`. - Reformatted samplesheet files used as input to the pipeline: `samplesheet.valid.csv`. diff --git a/docs/usage.md b/docs/usage.md index 4d021fe4..b90afdba 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -6,7 +6,7 @@ ## Samplesheet input -You will need to create a samplesheet with information about the samples you would like to analyse before running the pipeline. Use this parameter to specify its location. It has to be a tab-separated file with 4 columns, and a header row as shown in the examples below. +You will need to create a samplesheet with information about the samples you would like to analyse before running the pipeline. Use this parameter to specify its location. It has to be a tab-separated file with at least four columns, and a header row as shown in the examples below. ```bash --input '[path to samplesheet file]' @@ -19,7 +19,11 @@ You will need to create a samplesheet with information about the samples you wou | `ID` | An incrementing value which acts as a unique number for the given sample | | `Sample` | Custom sample name. This entry will be identical for multiple MS runs from the same sample. | | `Condition` | Additional information of the sample can be defined here. | -| `ReplicateFileName` | Full path to the MS file. These files have the extentions .raw, .mzML, mzML.gz, .d, .d.tar.gz, .d.zip | +| `ReplicateFileName` | Full path to the MS file. These files have the extensions .raw, .mzML, mzML.gz, .d, .d.tar.gz, .d.zip | +| `Fasta` | Full path to the FASTA file. These files have the extensions .fasta, .fa, .fas, .fna, .faa, .ffn | + +> [!NOTE] +> The `Fasta` column is optional, but you can use it to provide sample-specific FASTA files. If you want to use the same FASTA file for all samples, provide it via the `--fasta` parameter. Please ensure you use one of these options. The pipeline will auto-detect whether a sample is either in mzML, raw or tdf file format using the information provided in the samplesheet. @@ -58,15 +62,117 @@ Fine-tuning search settings is important to obtain the most optimal results for | fragment_mass_tolerance | 0.02 | 0.02 | 0.02 | 0.02 | 0.02 | 0.02 | 0.50025 | 0.50025 | | fragment_bin_offset | 0 | 0 | 0 | 0 | 0 | 0 | 0.4 | 0.4 | -Modifications are specified via `--variable_mods` and `fixed_mods` using the [UNIMOD nomenclature](https://www.unimod.org/unimod_help.html) via OpenMS. Check out [helper page](https://abibuilder.informatik.uni-tuebingen.de/archive/openms/Documentation/nightly/html/TOPP_CometAdapter.html) of OpenMS for the full list of options. Multiple modifications are specified as `'Oxidation (M),Acetyl (N-term),Phospho (S)'`. +Modifications are specified via `--variable_mods` and `fixed_mods` using the [UNIMOD nomenclature](https://www.unimod.org/unimod_help.html) via OpenMS. Check out [helper page](https://abibuilder.cs.uni-tuebingen.de/archive/openms/Documentation/nightly/html/TOPP_CometAdapter.html) of OpenMS for the full list of options. Multiple modifications are specified as `'Oxidation (M),Acetyl (N-term),Phospho (S)'`. Further information about the command line arguments is documented on the [nf-core website](https://nf-co.re/mhcquant/dev/parameters) or by using `--help`. ## Rescoring using MS²Rescore -By default the pipline generates additional features using MS²PIP and DeepLC via the MS²Rescore framework (`--feature_generators deeplc,ms2pip`). Additional feature generators can be added (`basic,deeplc,ms2pip,ionmob,im2deep`) to boost identification rates and quality. Please make sure you provide the correct `--ms2pip_model` (default: `Immuno-HCD`). All available MS²PIP models can be found on [GitHub](https://github.com/compomics/ms2pip). +The pipeline employs MS²Rescore for comprehensive feature prediction and rescoring of peptide-spectrum matches. By default, the pipeline generates additional features using MS²PIP and DeepLC via the MS²Rescore framework (`--feature_generators deeplc,ms2pip`). Additional feature generators can be added (`basic,deeplc,ms2pip,ionmob,im2deep`) to boost identification rates and quality. Please make sure you provide the correct `--ms2pip_model` (default: `Immuno-HCD`). All available MS²PIP models can be found on [GitHub](https://github.com/compomics/ms2pip). + +### Rescoring Engines + +The pipeline supports two rescoring engines: + +- **Percolator** (default): Semi-supervised learning tool for rescoring PSMs (`--rescoring_engine percolator`) +- **Mokapot**: Fast and flexible rescoring tool using gradient boosting (`--rescoring_engine mokapot`) + +> [!NOTE] +> MS²Rescore creates a comprehensive QC report of the added features used for rescoring. This report is only available when `--rescoring_engine mokapot` is specified. The report can be found in `/multiqc/ms2rescore`. + +### FDR Control Strategies + +The pipeline offers flexible FDR control strategies: + +#### Local FDR (Default) + +By default, FDR control is applied per sample-condition group: + +- FDR is calculated separately for each `Sample` and `Condition` combination +- Allows for sample-specific identification thresholds +- Suitable when samples have varying complexity or quality + +#### Global FDR Mode + +Enable global FDR control with `--global_fdr`: + +- FDR is calculated across all samples in the dataset +- Provides consistent identification criteria across all samples +- Particularly useful for comparative studies or when generating spectrum libraries +- Can improve identification rates for low-quality samples by leveraging high-quality samples in the dataset + +> [!WARNING] +> Global FDR is currently not supported by mokapot. If `--global_fdr` is enabled with `--rescoring_engine mokapot`, the global_fdr parameter will be ignored and local FDR will be applied. + +Further information on the MS²Rescore tool can be found in the published paper [Declerq et al. 2022](). + +## Quantification + +By default, the pipeline operates in identification mode. To enable quantification, use the `--quantify` parameter: + +```bash +nextflow run nf-core/mhcquant \ + --input 'samplesheet.tsv' \ + --fasta 'SWISSPROT_2020.fasta' \ + --quantify \ + -profile docker +``` + +When quantification is enabled, the pipeline performs retention time alignment and feature processing as detailed in the README documentation. + +The quantification workflow produces a ConsensusXML file containing integrated peak areas for identified peptides across all samples. + +## Spectrum Library Generation + +The pipeline can generate spectrum libraries suitable for DIA-based searches using the `--generate_speclib` parameter: + +For one spectrum library per sample: -MS²Rescore creates a comprehensive QC report of the added features used for rescoring. This report is only available if `--rescoring_engine mokapot` is specified (default: `percolator`). The report can be found in `/multiqc/ms2rescore`. Further information on the tool itself can be read up in the published paper [Declerq et al. 2022]() +```bash +nextflow run nf-core/mhcquant \ + --input 'samplesheet.tsv' \ + --fasta 'SWISSPROT_2020.fasta' \ + --generate_speclib \ + -profile docker +``` + +### Library Generation Process (`SPECLIB` subworkflow) + +- **Format Conversion**: PSMs and spectra are converted to appropriate formats using EasyPQP +- **Library Construction**: Sample-specific spectrum libraries are generated for each sample-condition group +- **Global Libraries**: When combined with `--global_fdr`, creates comprehensive spectrum libraries across all samples + +### Global Spectrum Libraries + +For comprehensive library generation across all samples add the `--global_fdr` flag: + +```bash +nextflow run nf-core/mhcquant \ + --input 'samplesheet.tsv' \ + --fasta 'SWISSPROT_2020.fasta' \ + --generate_speclib \ + --global_fdr \ + -profile docker +``` + +This approach is particularly useful when creating reference libraries for subsequent DIA analyses, as it maximizes the number of identifiable peptides by combining information from all samples.. + +## Epicore + +> [!NOTE] +> This tool is still experimental and under active development. + +Length variants of HLA peptides, especially HLA class II peptides, pose a distinct challenge when performing downstream cohort-wide analyses. [Epicore](https://github.com/AG-Walz/epicore) uses rules-based parameters to aggregate length variants of the same epitope into a `consensus epitope`. + +Run epicore in the pipeline: + +```bash +nextflow run nf-core/mhcquant \ + --input 'samplesheet.tsv' \ + --fasta 'SWISSPROT_2020.fasta' \ + --epicore \ + -profile docker +``` ## Running the pipeline @@ -77,13 +183,34 @@ nextflow run nf-core/mhcquant \ --input 'samplesheet.tsv' \ --outdir \ --fasta 'SWISSPROT_2020.fasta' \ - \ + --digest_mass_range 800:2500 \ + --activation_method CID \ + --prec_charge 2:3 \ + --fdr_threshold 0.01 \ + --fdr_level peptide_level_fdrs \ --peptide_min_length 8 \ - --peptide_max_length 14 \ + --peptide_max_length 12 \ --ms2pip_model 'Immuno-HCD' \ -profile docker ``` +**Complete workflow with all features**: + +```console +nextflow run nf-core/mhcquant \ + --input 'samplesheet.tsv' \ + --fasta 'SWISSPROT_2020.fasta' \ + --annotate_ions \ + --epicore \ + --generate_speclib \ + --global_fdr \ + --quantify \ + --outdir ./results \ + --feature_generators 'deeplc,ms2pip,im2deep' \ + --outdir results \ + -profile docker +``` + This will launch the pipeline with the `docker` configuration profile. See below for more information about profiles. Note that the pipeline will create the following files in your working directory: @@ -172,7 +299,7 @@ If `-profile` is not specified, the pipeline will run locally and expect all sof - `shifter` - A generic configuration profile to be used with [Shifter](https://nersc.gitlab.io/development/shifter/how-to-use/) - `charliecloud` - - A generic configuration profile to be used with [Charliecloud](https://hpc.github.io/charliecloud/) + - A generic configuration profile to be used with [Charliecloud](https://charliecloud.io/) - `apptainer` - A generic configuration profile to be used with [Apptainer](https://apptainer.org/) - `wave` diff --git a/main.nf b/main.nf index a89e1db4..5067acde 100644 --- a/main.nf +++ b/main.nf @@ -64,7 +64,10 @@ workflow { params.monochrome_logs, args, params.outdir, - params.input + params.input, + params.help, + params.help_full, + params.show_hidden ) // diff --git a/modules.json b/modules.json index c3ba548e..32f6f4c5 100644 --- a/modules.json +++ b/modules.json @@ -7,67 +7,67 @@ "nf-core": { "gunzip": { "branch": "master", - "git_sha": "3a5fef109d113b4997c9822198664ca5f2716208", + "git_sha": "41dfa3f7c0ffabb96a6a813fe321c6d1cc5b6e46", "installed_by": ["modules"] }, "multiqc": { "branch": "master", - "git_sha": "7b50cb7be890e4b28cffb82e438cc6a8d7805d3f", + "git_sha": "e10b76ca0c66213581bec2833e30d31f239dec0b", "installed_by": ["modules"] }, "openms/decoydatabase": { "branch": "master", - "git_sha": "0a42e8fb96e7a97a0d01070770be12b33426bb70", + "git_sha": "0c47e4193ddde2c5edbc206b5420cbcbee5c9797", "installed_by": ["modules"] }, "openms/filefilter": { "branch": "master", - "git_sha": "0a42e8fb96e7a97a0d01070770be12b33426bb70", + "git_sha": "0c47e4193ddde2c5edbc206b5420cbcbee5c9797", "installed_by": ["modules"] }, "openms/idfilter": { "branch": "master", - "git_sha": "0a42e8fb96e7a97a0d01070770be12b33426bb70", + "git_sha": "0c47e4193ddde2c5edbc206b5420cbcbee5c9797", "installed_by": ["modules"] }, "openms/idmassaccuracy": { "branch": "master", - "git_sha": "0a42e8fb96e7a97a0d01070770be12b33426bb70", + "git_sha": "0c47e4193ddde2c5edbc206b5420cbcbee5c9797", "installed_by": ["modules"] }, "openms/idmerger": { "branch": "master", - "git_sha": "0a42e8fb96e7a97a0d01070770be12b33426bb70", + "git_sha": "0c47e4193ddde2c5edbc206b5420cbcbee5c9797", "installed_by": ["modules"] }, "openms/idripper": { "branch": "master", - "git_sha": "0a42e8fb96e7a97a0d01070770be12b33426bb70", + "git_sha": "0c47e4193ddde2c5edbc206b5420cbcbee5c9797", "installed_by": ["modules"] }, "openms/idscoreswitcher": { "branch": "master", - "git_sha": "0a42e8fb96e7a97a0d01070770be12b33426bb70", + "git_sha": "0c47e4193ddde2c5edbc206b5420cbcbee5c9797", "installed_by": ["modules"] }, "openms/peakpickerhires": { "branch": "master", - "git_sha": "0a42e8fb96e7a97a0d01070770be12b33426bb70", + "git_sha": "0c47e4193ddde2c5edbc206b5420cbcbee5c9797", "installed_by": ["modules"] }, "openms/peptideindexer": { "branch": "master", - "git_sha": "0a42e8fb96e7a97a0d01070770be12b33426bb70", + "git_sha": "0c47e4193ddde2c5edbc206b5420cbcbee5c9797", "installed_by": ["modules"] }, "openmsthirdparty/cometadapter": { "branch": "master", - "git_sha": "0a42e8fb96e7a97a0d01070770be12b33426bb70", + "git_sha": "0c47e4193ddde2c5edbc206b5420cbcbee5c9797", "installed_by": ["modules"] }, "thermorawfileparser": { "branch": "master", - "git_sha": "05954dab2ff481bcb999f24455da29a5828af08d", + "git_sha": "41dfa3f7c0ffabb96a6a813fe321c6d1cc5b6e46", "installed_by": ["modules"] } } @@ -76,17 +76,17 @@ "nf-core": { "utils_nextflow_pipeline": { "branch": "master", - "git_sha": "c2b22d85f30a706a3073387f30380704fcae013b", + "git_sha": "05954dab2ff481bcb999f24455da29a5828af08d", "installed_by": ["subworkflows"] }, "utils_nfcore_pipeline": { "branch": "master", - "git_sha": "51ae5406a030d4da1e49e4dab49756844fdd6c7a", + "git_sha": "05954dab2ff481bcb999f24455da29a5828af08d", "installed_by": ["subworkflows"] }, "utils_nfschema_plugin": { "branch": "master", - "git_sha": "2fd2cd6d0e7b273747f32e465fdc6bcc3ae0814e", + "git_sha": "4b406a74dc0449c0401ed87d5bfff4252fd277fd", "installed_by": ["subworkflows"] } } diff --git a/modules/local/datamash_histogram/main.nf b/modules/local/datamash_histogram/main.nf deleted file mode 100644 index 44c5c071..00000000 --- a/modules/local/datamash_histogram/main.nf +++ /dev/null @@ -1,53 +0,0 @@ -process DATAMASH_HISTOGRAM { - tag "$meta.id" - label 'process_single' - - conda "${moduleDir}/environment.yml" - container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/datamash:1.1.0--0' : - 'biocontainers/datamash:1.1.0--0' }" - - input: - tuple val(meta), path(tsv) - - output: - tuple val(meta), path("*.tsv"), emit: binned_tsv - path "versions.yml" , emit: versions - - when: - task.ext.when == null || task.ext.when - - script: - def args = task.ext.args ?: '' - def prefix = task.ext.prefix ?: "${meta.id}" - - """ - datamash \\ - bin:0.0002 1 \\ - $args \\ - < $tsv \\ - | \\ - datamash \\ - --sort \\ - --group 1 \\ - count 1 \\ - > ${prefix}_binned.tsv - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - datamash: \$(datamash --version | grep 'datamash' | cut -d ' ' -f4) - END_VERSIONS - """ - - stub: - prefix = task.ext.prefix ?: "${meta.id}" - - """ - touch ${prefix}_binned.tsv - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - datamash: \$(datamash --version | grep 'datamash' | cut -d ' ' -f4) - END_VERSIONS - """ -} diff --git a/modules/local/easypqp/convert/environment.yml b/modules/local/easypqp/convert/environment.yml index df6ff650..a4d3cedd 100644 --- a/modules/local/easypqp/convert/environment.yml +++ b/modules/local/easypqp/convert/environment.yml @@ -2,4 +2,4 @@ channels: - conda-forge - bioconda dependencies: - - bioconda::easypqp=0.1.51 + - bioconda::easypqp=0.1.53 diff --git a/modules/local/easypqp/convert/main.nf b/modules/local/easypqp/convert/main.nf index 8cd3ff62..45387cdc 100644 --- a/modules/local/easypqp/convert/main.nf +++ b/modules/local/easypqp/convert/main.nf @@ -4,8 +4,8 @@ process EASYPQP_CONVERT { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/easypqp:0.1.51--pyhdfd78af_0' : - 'biocontainers/easypqp:0.1.51--pyhdfd78af_0' }" + 'https://depot.galaxyproject.org/singularity/easypqp:0.1.53--pyhdfd78af_0' : + 'biocontainers/easypqp:0.1.53--pyhdfd78af_0' }" input: tuple val(meta), path(pepxml), path(spectra) diff --git a/modules/local/easypqp/library/environment.yml b/modules/local/easypqp/library/environment.yml index df6ff650..a4d3cedd 100644 --- a/modules/local/easypqp/library/environment.yml +++ b/modules/local/easypqp/library/environment.yml @@ -2,4 +2,4 @@ channels: - conda-forge - bioconda dependencies: - - bioconda::easypqp=0.1.51 + - bioconda::easypqp=0.1.53 diff --git a/modules/local/easypqp/library/main.nf b/modules/local/easypqp/library/main.nf index 54b5535b..6f720fb1 100644 --- a/modules/local/easypqp/library/main.nf +++ b/modules/local/easypqp/library/main.nf @@ -4,8 +4,8 @@ process EASYPQP_LIBRARY { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/easypqp:0.1.51--pyhdfd78af_0' : - 'biocontainers/easypqp:0.1.51--pyhdfd78af_0' }" + 'https://depot.galaxyproject.org/singularity/easypqp:0.1.53--pyhdfd78af_0' : + 'biocontainers/easypqp:0.1.53--pyhdfd78af_0' }" input: tuple val(meta), path(psmpkl), path(peakpkl) diff --git a/modules/local/datamash_histogram/environment.yml b/modules/local/epicore/environment.yml similarity index 64% rename from modules/local/datamash_histogram/environment.yml rename to modules/local/epicore/environment.yml index 923ffe76..89ac527d 100644 --- a/modules/local/datamash_histogram/environment.yml +++ b/modules/local/epicore/environment.yml @@ -2,4 +2,4 @@ channels: - conda-forge - bioconda dependencies: - - bioconda::datamash=1.1.0 + - bioconda::epicore=0.1.7 diff --git a/modules/local/epicore/main.nf b/modules/local/epicore/main.nf new file mode 100644 index 00000000..a04efff9 --- /dev/null +++ b/modules/local/epicore/main.nf @@ -0,0 +1,56 @@ +process EPICORE { + tag "$meta.id" + label 'process_high' + + conda "${moduleDir}/environment.yml" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/epicore:0.1.7--pyhdfd78af_0' : + 'biocontainers/epicore:0.1.7--pyhdfd78af_0' }" + + input: + path(fasta) + tuple val(meta), path(result_tsv), path(general_stats) + + output: + path "*_general_stats.csv", emit: stats + path "${result_tsv}", emit: final_epicore_tsv + path "epicore_length_distribution.html", emit: length_dist + path "epicore_intensity_histogram.html", emit: intensity_hist + path "versions.yml", emit: versions + + script: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + """ + + epicore --reference_proteome $fasta --out_dir . generate-epicore-csv $args --evidence_file $result_tsv --html + + mv pep_cores_mapping.tsv ${prefix}.tsv + mv length_distributions.html epicore_length_distribution.html + mv epitope_intensity_hist.html epicore_intensity_histogram.html + + # Add epicore statistics to MultiQC general stats table + wc -l < epitopes.csv | awk '{print \$1 - 1}' > epicores.txt + awk 'NR==1 {print \$0 ",# Epicores"; next} NR==2 {getline extra < "epicores.txt"; print \$0 "," extra}' $general_stats > _modified_$general_stats + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + epicore: \$(echo \$(epicore --version) | grep 'epicore' | cut -d ' ' -f3 | cut -c2-) + END_VERSIONS + """ + + stub: + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}" + """ + touch ${prefix}_general_stats.csv + touch ${prefix}.tsv + touch epicore_length_distribution.html + touch epicore_intensity_hist.html + + cat <<-END_VERSIONS > versions.yml + "${task.process}": + epicore: \$(echo \$(epicore --version) | grep 'epicore' | cut -d ' ' -f3 | cut -c2-) + END_VERSIONS + """ +} diff --git a/modules/local/ms2rescore/environment.yml b/modules/local/ms2rescore/environment.yml index 828ccfea..9aa854d8 100644 --- a/modules/local/ms2rescore/environment.yml +++ b/modules/local/ms2rescore/environment.yml @@ -2,4 +2,5 @@ channels: - conda-forge - bioconda dependencies: + - conda-forge::sqlalchemy>=2 - bioconda::ms2rescore=3.1.5 diff --git a/modules/local/ms2rescore/main.nf b/modules/local/ms2rescore/main.nf index 673b1618..06fcb72a 100644 --- a/modules/local/ms2rescore/main.nf +++ b/modules/local/ms2rescore/main.nf @@ -4,8 +4,8 @@ process MS2RESCORE { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/ms2rescore:3.1.5--pyh7e72e81_0': - 'biocontainers/ms2rescore:3.1.5--pyh7e72e81_0' }" + 'https://depot.galaxyproject.org/singularity/ms2rescore:3.1.5--pyhdfd78af_1': + 'biocontainers/ms2rescore:3.1.5--pyhdfd78af_1' }" // userEmulation settings when docker is specified containerOptions = (workflow.containerEngine == 'docker') ? '-u $(id -u) -e "HOME=${HOME}" -v /etc/passwd:/etc/passwd:ro -v /etc/shadow:/etc/shadow:ro -v /etc/group:/etc/group:ro -v $HOME:$HOME' : '' diff --git a/modules/local/openms/featurefinderidentification/environment.yml b/modules/local/openms/featurefinderidentification/environment.yml index 031d2398..d85a93ef 100644 --- a/modules/local/openms/featurefinderidentification/environment.yml +++ b/modules/local/openms/featurefinderidentification/environment.yml @@ -4,4 +4,4 @@ channels: - conda-forge - bioconda dependencies: - - bioconda::openms=3.4.0 + - bioconda::openms=3.4.1 diff --git a/modules/local/openms/featurefinderidentification/main.nf b/modules/local/openms/featurefinderidentification/main.nf index 5cfba1d5..794455ec 100644 --- a/modules/local/openms/featurefinderidentification/main.nf +++ b/modules/local/openms/featurefinderidentification/main.nf @@ -4,8 +4,8 @@ process OPENMS_FEATUREFINDERIDENTIFICATION { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/openms:3.4.0--hc77a4c7_0' : - 'biocontainers/openms:3.4.0--hc77a4c7_0' }" + 'https://depot.galaxyproject.org/singularity/openms:3.4.1--h81ffffe_1' : + 'biocontainers/openms:3.4.1--h81ffffe_1' }" input: diff --git a/modules/local/openms/idconflictresolver/environment.yml b/modules/local/openms/idconflictresolver/environment.yml index 031d2398..d85a93ef 100644 --- a/modules/local/openms/idconflictresolver/environment.yml +++ b/modules/local/openms/idconflictresolver/environment.yml @@ -4,4 +4,4 @@ channels: - conda-forge - bioconda dependencies: - - bioconda::openms=3.4.0 + - bioconda::openms=3.4.1 diff --git a/modules/local/openms/idconflictresolver/main.nf b/modules/local/openms/idconflictresolver/main.nf index f51d77b5..9228ee81 100644 --- a/modules/local/openms/idconflictresolver/main.nf +++ b/modules/local/openms/idconflictresolver/main.nf @@ -4,8 +4,8 @@ process OPENMS_IDCONFLICTRESOLVER { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/openms:3.4.0--hc77a4c7_0' : - 'biocontainers/openms:3.4.0--hc77a4c7_0' }" + 'https://depot.galaxyproject.org/singularity/openms:3.4.1--h81ffffe_1' : + 'biocontainers/openms:3.4.1--h81ffffe_1' }" input: tuple val(meta), path(consensus) diff --git a/modules/local/openms/mapaligneridentification/environment.yml b/modules/local/openms/mapaligneridentification/environment.yml index 031d2398..d85a93ef 100644 --- a/modules/local/openms/mapaligneridentification/environment.yml +++ b/modules/local/openms/mapaligneridentification/environment.yml @@ -4,4 +4,4 @@ channels: - conda-forge - bioconda dependencies: - - bioconda::openms=3.4.0 + - bioconda::openms=3.4.1 diff --git a/modules/local/openms/mapaligneridentification/main.nf b/modules/local/openms/mapaligneridentification/main.nf index 26132f46..fd19d5c3 100644 --- a/modules/local/openms/mapaligneridentification/main.nf +++ b/modules/local/openms/mapaligneridentification/main.nf @@ -4,8 +4,8 @@ process OPENMS_MAPALIGNERIDENTIFICATION { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/openms:3.4.0--hc77a4c7_0' : - 'biocontainers/openms:3.4.0--hc77a4c7_0' }" + 'https://depot.galaxyproject.org/singularity/openms:3.4.1--h81ffffe_1' : + 'biocontainers/openms:3.4.1--h81ffffe_1' }" input: tuple val(meta), path(idxmls) diff --git a/modules/local/openms/maprttransformer/environment.yml b/modules/local/openms/maprttransformer/environment.yml index 031d2398..d85a93ef 100644 --- a/modules/local/openms/maprttransformer/environment.yml +++ b/modules/local/openms/maprttransformer/environment.yml @@ -4,4 +4,4 @@ channels: - conda-forge - bioconda dependencies: - - bioconda::openms=3.4.0 + - bioconda::openms=3.4.1 diff --git a/modules/local/openms/maprttransformer/main.nf b/modules/local/openms/maprttransformer/main.nf index 9553e218..a2889e35 100644 --- a/modules/local/openms/maprttransformer/main.nf +++ b/modules/local/openms/maprttransformer/main.nf @@ -4,8 +4,8 @@ process OPENMS_MAPRTTRANSFORMER { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/openms:3.4.0--hc77a4c7_0' : - 'biocontainers/openms:3.4.0--hc77a4c7_0' }" + 'https://depot.galaxyproject.org/singularity/openms:3.4.1--h81ffffe_1' : + 'biocontainers/openms:3.4.1--h81ffffe_1' }" input: tuple val(meta), path(alignment_file), path(trafoxml) diff --git a/modules/local/openms/mztabexporter/environment.yml b/modules/local/openms/mztabexporter/environment.yml index 031d2398..d85a93ef 100644 --- a/modules/local/openms/mztabexporter/environment.yml +++ b/modules/local/openms/mztabexporter/environment.yml @@ -4,4 +4,4 @@ channels: - conda-forge - bioconda dependencies: - - bioconda::openms=3.4.0 + - bioconda::openms=3.4.1 diff --git a/modules/local/openms/mztabexporter/main.nf b/modules/local/openms/mztabexporter/main.nf index 787cf398..ee5500b4 100644 --- a/modules/local/openms/mztabexporter/main.nf +++ b/modules/local/openms/mztabexporter/main.nf @@ -4,8 +4,8 @@ process OPENMS_MZTABEXPORTER { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/openms:3.4.0--hc77a4c7_0' : - 'biocontainers/openms:3.4.0--hc77a4c7_0' }" + 'https://depot.galaxyproject.org/singularity/openms:3.4.1--h81ffffe_1' : + 'biocontainers/openms:3.4.1--h81ffffe_1' }" input: tuple val(meta), path(in_file) diff --git a/modules/local/openms/psmfeatureextractor/environment.yml b/modules/local/openms/psmfeatureextractor/environment.yml index 031d2398..d85a93ef 100644 --- a/modules/local/openms/psmfeatureextractor/environment.yml +++ b/modules/local/openms/psmfeatureextractor/environment.yml @@ -4,4 +4,4 @@ channels: - conda-forge - bioconda dependencies: - - bioconda::openms=3.4.0 + - bioconda::openms=3.4.1 diff --git a/modules/local/openms/psmfeatureextractor/main.nf b/modules/local/openms/psmfeatureextractor/main.nf index c73e7a79..870e6519 100644 --- a/modules/local/openms/psmfeatureextractor/main.nf +++ b/modules/local/openms/psmfeatureextractor/main.nf @@ -4,8 +4,8 @@ process OPENMS_PSMFEATUREEXTRACTOR { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/openms:3.4.0--hc77a4c7_0' : - 'biocontainers/openms:3.4.0--hc77a4c7_0' }" + 'https://depot.galaxyproject.org/singularity/openms:3.4.1--h81ffffe_1' : + 'biocontainers/openms:3.4.1--h81ffffe_1' }" input: tuple val(meta), path(idxml), path(feature_file) diff --git a/modules/local/openms/textexporter/environment.yml b/modules/local/openms/textexporter/environment.yml index 031d2398..d85a93ef 100644 --- a/modules/local/openms/textexporter/environment.yml +++ b/modules/local/openms/textexporter/environment.yml @@ -4,4 +4,4 @@ channels: - conda-forge - bioconda dependencies: - - bioconda::openms=3.4.0 + - bioconda::openms=3.4.1 diff --git a/modules/local/openms/textexporter/main.nf b/modules/local/openms/textexporter/main.nf index a144a6e7..46dd8f33 100644 --- a/modules/local/openms/textexporter/main.nf +++ b/modules/local/openms/textexporter/main.nf @@ -4,8 +4,8 @@ process OPENMS_TEXTEXPORTER { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/openms:3.4.0--hc77a4c7_0' : - 'biocontainers/openms:3.4.0--hc77a4c7_0' }" + 'https://depot.galaxyproject.org/singularity/openms:3.4.1--h81ffffe_1' : + 'biocontainers/openms:3.4.1--h81ffffe_1' }" input: tuple val(meta), path(file) diff --git a/modules/local/openmsthirdparty/featurelinkerunlabeledkd/environment.yml b/modules/local/openmsthirdparty/featurelinkerunlabeledkd/environment.yml index 1da7b29a..dde2f844 100644 --- a/modules/local/openmsthirdparty/featurelinkerunlabeledkd/environment.yml +++ b/modules/local/openmsthirdparty/featurelinkerunlabeledkd/environment.yml @@ -4,4 +4,4 @@ channels: - conda-forge - bioconda dependencies: - - bioconda::openms-thirdparty=3.4.0 + - bioconda::openms-thirdparty=3.4.1 diff --git a/modules/local/openmsthirdparty/featurelinkerunlabeledkd/main.nf b/modules/local/openmsthirdparty/featurelinkerunlabeledkd/main.nf index f6547798..96ce7b37 100644 --- a/modules/local/openmsthirdparty/featurelinkerunlabeledkd/main.nf +++ b/modules/local/openmsthirdparty/featurelinkerunlabeledkd/main.nf @@ -4,8 +4,8 @@ process OPENMS_FEATURELINKERUNLABELEDKD { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/openms-thirdparty:3.4.0--h9ee0642_0' : - 'biocontainers/openms-thirdparty:3.4.0--h9ee0642_0' }" + 'https://depot.galaxyproject.org/singularity/openms-thirdparty:3.4.1--h9ee0642_1' : + 'biocontainers/openms-thirdparty:3.4.1--h9ee0642_1' }" input: tuple val(meta), path(features) diff --git a/modules/local/openmsthirdparty/percolatoradapter/environment.yml b/modules/local/openmsthirdparty/percolatoradapter/environment.yml index 1da7b29a..dde2f844 100644 --- a/modules/local/openmsthirdparty/percolatoradapter/environment.yml +++ b/modules/local/openmsthirdparty/percolatoradapter/environment.yml @@ -4,4 +4,4 @@ channels: - conda-forge - bioconda dependencies: - - bioconda::openms-thirdparty=3.4.0 + - bioconda::openms-thirdparty=3.4.1 diff --git a/modules/local/openmsthirdparty/percolatoradapter/main.nf b/modules/local/openmsthirdparty/percolatoradapter/main.nf index a3ea3ede..8199ce17 100644 --- a/modules/local/openmsthirdparty/percolatoradapter/main.nf +++ b/modules/local/openmsthirdparty/percolatoradapter/main.nf @@ -4,8 +4,8 @@ process OPENMS_PERCOLATORADAPTER { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/openms-thirdparty:3.4.0--h9ee0642_0' : - 'biocontainers/openms-thirdparty:3.4.0--h9ee0642_0' }" + 'https://depot.galaxyproject.org/singularity/openms-thirdparty:3.4.1--h9ee0642_1' : + 'biocontainers/openms-thirdparty:3.4.1--h9ee0642_1' }" input: tuple val(meta), path(merged_with_features) diff --git a/modules/local/pyopenms/chromatogramextractor/environment.yml b/modules/local/pyopenms/chromatogramextractor/environment.yml index 3c8b5456..d0a1e992 100644 --- a/modules/local/pyopenms/chromatogramextractor/environment.yml +++ b/modules/local/pyopenms/chromatogramextractor/environment.yml @@ -4,4 +4,4 @@ channels: - conda-forge - bioconda dependencies: - - bioconda::pyopenms=3.3.0 + - bioconda::pyopenms=3.4.1 diff --git a/modules/local/pyopenms/chromatogramextractor/main.nf b/modules/local/pyopenms/chromatogramextractor/main.nf index 2548ee3f..33f138e0 100644 --- a/modules/local/pyopenms/chromatogramextractor/main.nf +++ b/modules/local/pyopenms/chromatogramextractor/main.nf @@ -4,8 +4,8 @@ process PYOPENMS_CHROMATOGRAMEXTRACTOR { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/pyopenms:3.3.0--py313h9b5bd11_0' : - 'biocontainers/pyopenms:3.3.0--py313h9b5bd11_0' }" + 'https://depot.galaxyproject.org/singularity/pyopenms:3.4.1--py312h6b06db6_2' : + 'biocontainers/pyopenms:3.4.1--py312h6b06db6_2' }" input: tuple val(meta), path(mzml) @@ -28,7 +28,7 @@ process PYOPENMS_CHROMATOGRAMEXTRACTOR { cat <<-END_VERSIONS > versions.yml "${task.process}": - pyOpenMS: \$(pip show pyopenms | grep Version | cut -d ' ' -f 2) + pyopenms: \$(pip show pyopenms | grep Version | sed 's/Version: //') END_VERSIONS """ @@ -40,7 +40,7 @@ process PYOPENMS_CHROMATOGRAMEXTRACTOR { cat <<-END_VERSIONS > versions.yml "${task.process}": - pyOpenMS: \$(pip show pyopenms | grep Version | cut -d ' ' -f 2) + pyopenms: \$(pip show pyopenms | grep Version | sed 's/Version: //') END_VERSIONS """ } diff --git a/modules/local/pyopenms/ionannotator/environment.yml b/modules/local/pyopenms/ionannotator/environment.yml index 3c8b5456..d0a1e992 100644 --- a/modules/local/pyopenms/ionannotator/environment.yml +++ b/modules/local/pyopenms/ionannotator/environment.yml @@ -4,4 +4,4 @@ channels: - conda-forge - bioconda dependencies: - - bioconda::pyopenms=3.3.0 + - bioconda::pyopenms=3.4.1 diff --git a/modules/local/pyopenms/ionannotator/main.nf b/modules/local/pyopenms/ionannotator/main.nf index 4e0272ce..cb5f06a6 100644 --- a/modules/local/pyopenms/ionannotator/main.nf +++ b/modules/local/pyopenms/ionannotator/main.nf @@ -4,8 +4,8 @@ process PYOPENMS_IONANNOTATOR { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/pyopenms:3.3.0--py313h9b5bd11_0' : - 'biocontainers/pyopenms:3.3.0--py313h9b5bd11_0' }" + 'https://depot.galaxyproject.org/singularity/pyopenms:3.4.1--py312h6b06db6_2' : + 'biocontainers/pyopenms:3.4.1--py312h6b06db6_2' }" input: tuple val(meta), path(mzml), path(fdr_filtered_idxml) @@ -39,7 +39,7 @@ process PYOPENMS_IONANNOTATOR { cat <<-END_VERSIONS > versions.yml "${task.process}": - pyopenms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') + pyopenms: \$(pip show pyopenms | grep Version | sed 's/Version: //') END_VERSIONS """ @@ -52,7 +52,7 @@ process PYOPENMS_IONANNOTATOR { cat <<-END_VERSIONS > versions.yml "${task.process}": - pyopenms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') + pyopenms: \$(pip show pyopenms | grep Version | sed 's/Version: //') END_VERSIONS """ } diff --git a/modules/local/pyopenms/summarize_results/environment.yml b/modules/local/pyopenms/summarize_results/environment.yml index 3c8b5456..d0a1e992 100644 --- a/modules/local/pyopenms/summarize_results/environment.yml +++ b/modules/local/pyopenms/summarize_results/environment.yml @@ -4,4 +4,4 @@ channels: - conda-forge - bioconda dependencies: - - bioconda::pyopenms=3.3.0 + - bioconda::pyopenms=3.4.1 diff --git a/modules/local/pyopenms/summarize_results/main.nf b/modules/local/pyopenms/summarize_results/main.nf index fb76c766..e92edd38 100644 --- a/modules/local/pyopenms/summarize_results/main.nf +++ b/modules/local/pyopenms/summarize_results/main.nf @@ -2,21 +2,21 @@ process SUMMARIZE_RESULTS { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/pyopenms:3.3.0--py313h9b5bd11_0' : - 'biocontainers/pyopenms:3.3.0--py313h9b5bd11_0' }" + 'https://depot.galaxyproject.org/singularity/pyopenms:3.4.1--py312h6b06db6_2' : + 'biocontainers/pyopenms:3.4.1--py312h6b06db6_2' }" input: tuple val(meta), path(file) output: - path '*_histogram_mz.csv' , emit: hist_mz, optional: true - path '*_histogram_rt.csv' , emit: hist_rt, optional: true - path '*_histogram_scores.csv' , emit: hist_scores, optional: true - path '*_histogram_xcorr_scores.csv' , emit: hist_xcorr, optional: true - path '*_peptide_length.csv' , emit: lengths, optional: true - path '*_general_stats.csv' , emit: stats - path '*.tsv' , emit: final_tsv - path 'versions.yml' , emit: versions + path '*_histogram_mz.csv' , emit: hist_mz, optional: true + path '*_histogram_rt.csv' , emit: hist_rt, optional: true + path '*_histogram_scores.csv' , emit: hist_scores, optional: true + path '*_xcorr_scores.csv' , emit: xcorr, optional: true + path '*_peptide_length.csv' , emit: lengths, optional: true + path '*_peptide_intensity.csv' , emit: intensities, optional: true + tuple val(meta), path('*.tsv'), path('*_general_stats.csv') , emit: epicore_input + path 'versions.yml' , emit: versions script: def args = task.ext.args ?: '' @@ -32,7 +32,7 @@ process SUMMARIZE_RESULTS { cat <<-END_VERSIONS > versions.yml "${task.process}": - pyopenms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') + pyopenms: \$(pip show pyopenms | grep Version | sed 's/Version: //') END_VERSIONS """ @@ -43,14 +43,15 @@ process SUMMARIZE_RESULTS { touch ${prefix}_histogram_mz.csv touch ${prefix}_histogram_rt.csv touch ${prefix}_histogram_scores.csv - touch ${prefix}_histogram_xcorr_scores.csv + touch ${prefix}_xcorr_scores.csv touch ${prefix}_peptide_length.csv + touch ${prefix}_peptide_intensity.csv touch ${prefix}_general_stats.csv touch ${prefix}.tsv cat <<-END_VERSIONS > versions.yml "${task.process}": - pyopenms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') + pyopenms: \$(pip show pyopenms | grep Version | sed 's/Version: //') END_VERSIONS """ } diff --git a/modules/nf-core/gunzip/environment.yml b/modules/nf-core/gunzip/environment.yml index 5ac9b57b..9b926b1f 100644 --- a/modules/nf-core/gunzip/environment.yml +++ b/modules/nf-core/gunzip/environment.yml @@ -1,6 +1,12 @@ -name: gunzip +--- +# yaml-language-server: $schema=https://raw.githubusercontent.com/nf-core/modules/master/modules/environment-schema.json channels: - conda-forge - bioconda dependencies: - - conda-forge::sed=4.7 + - conda-forge::coreutils=9.5 + - conda-forge::grep=3.11 + - conda-forge::gzip=1.13 + - conda-forge::lbzip2=2.5 + - conda-forge::sed=4.8 + - conda-forge::tar=1.34 diff --git a/modules/nf-core/gunzip/main.nf b/modules/nf-core/gunzip/main.nf index 468a6f28..3ffc8e92 100644 --- a/modules/nf-core/gunzip/main.nf +++ b/modules/nf-core/gunzip/main.nf @@ -1,34 +1,37 @@ process GUNZIP { - tag "$archive" + tag "${archive}" label 'process_single' conda "${moduleDir}/environment.yml" - container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/ubuntu:20.04' : - 'nf-core/ubuntu:20.04' }" + container "${workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container + ? 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/52/52ccce28d2ab928ab862e25aae26314d69c8e38bd41ca9431c67ef05221348aa/data' + : 'community.wave.seqera.io/library/coreutils_grep_gzip_lbzip2_pruned:838ba80435a629f8'}" input: tuple val(meta), path(archive) output: - tuple val(meta), path("$gunzip"), emit: gunzip - path "versions.yml" , emit: versions + tuple val(meta), path("${gunzip}"), emit: gunzip + path "versions.yml", emit: versions when: task.ext.when == null || task.ext.when script: def args = task.ext.args ?: '' - gunzip = archive.toString() - '.gz' + def extension = (archive.toString() - '.gz').tokenize('.')[-1] + def name = archive.toString() - '.gz' - ".${extension}" + def prefix = task.ext.prefix ?: name + gunzip = prefix + ".${extension}" """ # Not calling gunzip itself because it creates files # with the original group ownership rather than the # default one for that user / the work directory gzip \\ -cd \\ - $args \\ - $archive \\ - > $gunzip + ${args} \\ + ${archive} \\ + > ${gunzip} cat <<-END_VERSIONS > versions.yml "${task.process}": @@ -37,9 +40,13 @@ process GUNZIP { """ stub: - gunzip = archive.toString() - '.gz' + def args = task.ext.args ?: '' + def extension = (archive.toString() - '.gz').tokenize('.')[-1] + def name = archive.toString() - '.gz' - ".${extension}" + def prefix = task.ext.prefix ?: name + gunzip = prefix + ".${extension}" """ - touch $gunzip + touch ${gunzip} cat <<-END_VERSIONS > versions.yml "${task.process}": gunzip: \$(echo \$(gunzip --version 2>&1) | sed 's/^.*(gzip) //; s/ Copyright.*\$//') diff --git a/modules/nf-core/gunzip/meta.yml b/modules/nf-core/gunzip/meta.yml index 231034f2..926bb22a 100644 --- a/modules/nf-core/gunzip/meta.yml +++ b/modules/nf-core/gunzip/meta.yml @@ -10,25 +10,37 @@ tools: gzip is a file format and a software application used for file compression and decompression. documentation: https://www.gnu.org/software/gzip/manual/gzip.html licence: ["GPL-3.0-or-later"] + identifier: "" input: - - meta: - type: map - description: | - Optional groovy Map containing meta information - e.g. [ id:'test', single_end:false ] - - archive: - type: file - description: File to be compressed/uncompressed - pattern: "*.*" + - - meta: + type: map + description: | + Optional groovy Map containing meta information + e.g. [ id:'test', single_end:false ] + - archive: + type: file + description: File to be compressed/uncompressed + pattern: "*.*" + ontologies: [] output: - - gunzip: - type: file - description: Compressed/uncompressed file - pattern: "*.*" - - versions: - type: file - description: File containing software versions - pattern: "versions.yml" + gunzip: + - - meta: + type: file + description: Compressed/uncompressed file + pattern: "*.*" + ontologies: [] + - ${gunzip}: + type: file + description: Compressed/uncompressed file + pattern: "*.*" + ontologies: [] + versions: + - versions.yml: + type: file + description: File containing software versions + pattern: "versions.yml" + ontologies: + - edam: http://edamontology.org/format_3750 # YAML authors: - "@joseespinosa" - "@drpatelh" @@ -37,3 +49,4 @@ maintainers: - "@joseespinosa" - "@drpatelh" - "@jfy133" + - "@gallvp" diff --git a/modules/nf-core/gunzip/tests/main.nf.test b/modules/nf-core/gunzip/tests/main.nf.test index 6406008e..776211ad 100644 --- a/modules/nf-core/gunzip/tests/main.nf.test +++ b/modules/nf-core/gunzip/tests/main.nf.test @@ -33,4 +33,89 @@ nextflow_process { } + test("Should run without failures - prefix") { + + config './nextflow.config' + + when { + params { + outdir = "$outputDir" + } + process { + """ + input[0] = Channel.of([ + [ id: 'test' ], + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) + ] + ) + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + + test("Should run without failures - stub") { + + options '-stub' + + when { + params { + outdir = "$outputDir" + } + process { + """ + input[0] = Channel.of([ + [], + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) + ] + ) + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + + test("Should run without failures - prefix - stub") { + + options '-stub' + config './nextflow.config' + + when { + params { + outdir = "$outputDir" + } + process { + """ + input[0] = Channel.of([ + [ id: 'test' ], + file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastq/test_1.fastq.gz', checkIfExists: true) + ] + ) + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert snapshot(process.out).match() } + ) + } + + } + } diff --git a/modules/nf-core/gunzip/tests/main.nf.test.snap b/modules/nf-core/gunzip/tests/main.nf.test.snap index 720fd9ff..a0f0e67e 100644 --- a/modules/nf-core/gunzip/tests/main.nf.test.snap +++ b/modules/nf-core/gunzip/tests/main.nf.test.snap @@ -1,4 +1,70 @@ { + "Should run without failures - prefix - stub": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test.xyz.fastq:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + "versions.yml:md5,d327e4a19a6d5c5e974136cef8999d8c" + ], + "gunzip": [ + [ + { + "id": "test" + }, + "test.xyz.fastq:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,d327e4a19a6d5c5e974136cef8999d8c" + ] + } + ], + "meta": { + "nf-test": "0.9.2", + "nextflow": "24.10.2" + }, + "timestamp": "2024-12-13T11:48:22.080222697" + }, + "Should run without failures - stub": { + "content": [ + { + "0": [ + [ + [ + + ], + "test_1.fastq:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "1": [ + "versions.yml:md5,d327e4a19a6d5c5e974136cef8999d8c" + ], + "gunzip": [ + [ + [ + + ], + "test_1.fastq:md5,d41d8cd98f00b204e9800998ecf8427e" + ] + ], + "versions": [ + "versions.yml:md5,d327e4a19a6d5c5e974136cef8999d8c" + ] + } + ], + "meta": { + "nf-test": "0.9.2", + "nextflow": "24.10.2" + }, + "timestamp": "2024-12-13T11:48:14.593020264" + }, "Should run without failures": { "content": [ { @@ -11,7 +77,7 @@ ] ], "1": [ - "versions.yml:md5,54376d32aca20e937a4ec26dac228e84" + "versions.yml:md5,d327e4a19a6d5c5e974136cef8999d8c" ], "gunzip": [ [ @@ -22,10 +88,47 @@ ] ], "versions": [ - "versions.yml:md5,54376d32aca20e937a4ec26dac228e84" + "versions.yml:md5,d327e4a19a6d5c5e974136cef8999d8c" + ] + } + ], + "meta": { + "nf-test": "0.9.2", + "nextflow": "24.10.2" + }, + "timestamp": "2024-12-13T11:48:01.295397925" + }, + "Should run without failures - prefix": { + "content": [ + { + "0": [ + [ + { + "id": "test" + }, + "test.xyz.fastq:md5,4161df271f9bfcd25d5845a1e220dbec" + ] + ], + "1": [ + "versions.yml:md5,d327e4a19a6d5c5e974136cef8999d8c" + ], + "gunzip": [ + [ + { + "id": "test" + }, + "test.xyz.fastq:md5,4161df271f9bfcd25d5845a1e220dbec" + ] + ], + "versions": [ + "versions.yml:md5,d327e4a19a6d5c5e974136cef8999d8c" ] } ], - "timestamp": "2023-10-17T15:35:37.690477896" + "meta": { + "nf-test": "0.9.2", + "nextflow": "24.10.2" + }, + "timestamp": "2024-12-13T11:48:07.414271387" } } \ No newline at end of file diff --git a/modules/nf-core/gunzip/tests/nextflow.config b/modules/nf-core/gunzip/tests/nextflow.config new file mode 100644 index 00000000..dec77642 --- /dev/null +++ b/modules/nf-core/gunzip/tests/nextflow.config @@ -0,0 +1,5 @@ +process { + withName: GUNZIP { + ext.prefix = { "${meta.id}.xyz" } + } +} diff --git a/modules/nf-core/gunzip/tests/tags.yml b/modules/nf-core/gunzip/tests/tags.yml deleted file mode 100644 index fd3f6915..00000000 --- a/modules/nf-core/gunzip/tests/tags.yml +++ /dev/null @@ -1,2 +0,0 @@ -gunzip: - - modules/nf-core/gunzip/** diff --git a/modules/nf-core/multiqc/environment.yml b/modules/nf-core/multiqc/environment.yml index d430da5f..dd513cbd 100644 --- a/modules/nf-core/multiqc/environment.yml +++ b/modules/nf-core/multiqc/environment.yml @@ -4,4 +4,4 @@ channels: - conda-forge - bioconda dependencies: - - bioconda::multiqc=1.28 + - bioconda::multiqc=1.31 diff --git a/modules/nf-core/multiqc/main.nf b/modules/nf-core/multiqc/main.nf index f3b57047..5288f5cc 100644 --- a/modules/nf-core/multiqc/main.nf +++ b/modules/nf-core/multiqc/main.nf @@ -3,8 +3,8 @@ process MULTIQC { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/multiqc:1.28--pyhdfd78af_0' : - 'biocontainers/multiqc:1.28--pyhdfd78af_0' }" + 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/ef/eff0eafe78d5f3b65a6639265a16b89fdca88d06d18894f90fcdb50142004329/data' : + 'community.wave.seqera.io/library/multiqc:1.31--1efbafd542a23882' }" input: path multiqc_files, stageAs: "?/*" diff --git a/modules/nf-core/multiqc/meta.yml b/modules/nf-core/multiqc/meta.yml index b16c1879..ce30eb73 100644 --- a/modules/nf-core/multiqc/meta.yml +++ b/modules/nf-core/multiqc/meta.yml @@ -15,57 +15,71 @@ tools: licence: ["GPL-3.0-or-later"] identifier: biotools:multiqc input: - - - multiqc_files: - type: file - description: | - List of reports / files recognised by MultiQC, for example the html and zip output of FastQC - - - multiqc_config: - type: file - description: Optional config yml for MultiQC - pattern: "*.{yml,yaml}" - - - extra_multiqc_config: - type: file - description: Second optional config yml for MultiQC. Will override common sections - in multiqc_config. - pattern: "*.{yml,yaml}" - - - multiqc_logo: + - multiqc_files: + type: file + description: | + List of reports / files recognised by MultiQC, for example the html and zip output of FastQC + ontologies: [] + - multiqc_config: + type: file + description: Optional config yml for MultiQC + pattern: "*.{yml,yaml}" + ontologies: + - edam: http://edamontology.org/format_3750 # YAML + - extra_multiqc_config: + type: file + description: Second optional config yml for MultiQC. Will override common sections + in multiqc_config. + pattern: "*.{yml,yaml}" + ontologies: + - edam: http://edamontology.org/format_3750 # YAML + - multiqc_logo: + type: file + description: Optional logo file for MultiQC + pattern: "*.{png}" + ontologies: [] + - replace_names: + type: file + description: | + Optional two-column sample renaming file. First column a set of + patterns, second column a set of corresponding replacements. Passed via + MultiQC's `--replace-names` option. + pattern: "*.{tsv}" + ontologies: + - edam: http://edamontology.org/format_3475 # TSV + - sample_names: + type: file + description: | + Optional TSV file with headers, passed to the MultiQC --sample_names + argument. + pattern: "*.{tsv}" + ontologies: + - edam: http://edamontology.org/format_3475 # TSV +output: + report: + - "*multiqc_report.html": type: file - description: Optional logo file for MultiQC - pattern: "*.{png}" - - - replace_names: + description: MultiQC report file + pattern: "multiqc_report.html" + ontologies: [] + data: + - "*_data": + type: directory + description: MultiQC data dir + pattern: "multiqc_data" + plots: + - "*_plots": type: file - description: | - Optional two-column sample renaming file. First column a set of - patterns, second column a set of corresponding replacements. Passed via - MultiQC's `--replace-names` option. - pattern: "*.{tsv}" - - - sample_names: + description: Plots created by MultiQC + pattern: "*_data" + ontologies: [] + versions: + - versions.yml: type: file - description: | - Optional TSV file with headers, passed to the MultiQC --sample_names - argument. - pattern: "*.{tsv}" -output: - - report: - - "*multiqc_report.html": - type: file - description: MultiQC report file - pattern: "multiqc_report.html" - - data: - - "*_data": - type: directory - description: MultiQC data dir - pattern: "multiqc_data" - - plots: - - "*_plots": - type: file - description: Plots created by MultiQC - pattern: "*_data" - - versions: - - versions.yml: - type: file - description: File containing software versions - pattern: "versions.yml" + description: File containing software versions + pattern: "versions.yml" + ontologies: + - edam: http://edamontology.org/format_3750 # YAML authors: - "@abhi18av" - "@bunop" diff --git a/modules/nf-core/multiqc/tests/main.nf.test.snap b/modules/nf-core/multiqc/tests/main.nf.test.snap index 26d74307..e1f36138 100644 --- a/modules/nf-core/multiqc/tests/main.nf.test.snap +++ b/modules/nf-core/multiqc/tests/main.nf.test.snap @@ -2,14 +2,14 @@ "multiqc_versions_single": { "content": [ [ - "versions.yml:md5,b05075d2d2b4f485c0d627a5c8e475b2" + "versions.yml:md5,8968b114a3e20756d8af2b80713bcc4f" ] ], "meta": { - "nf-test": "0.9.0", - "nextflow": "24.10.4" + "nf-test": "0.9.2", + "nextflow": "25.04.6" }, - "timestamp": "2025-03-26T16:05:18.927925" + "timestamp": "2025-09-08T20:57:36.139055243" }, "multiqc_stub": { "content": [ @@ -17,25 +17,25 @@ "multiqc_report.html", "multiqc_data", "multiqc_plots", - "versions.yml:md5,b05075d2d2b4f485c0d627a5c8e475b2" + "versions.yml:md5,8968b114a3e20756d8af2b80713bcc4f" ] ], "meta": { - "nf-test": "0.9.0", - "nextflow": "24.10.4" + "nf-test": "0.9.2", + "nextflow": "25.04.6" }, - "timestamp": "2025-03-26T16:05:55.639955" + "timestamp": "2025-09-08T20:59:15.142230631" }, "multiqc_versions_config": { "content": [ [ - "versions.yml:md5,b05075d2d2b4f485c0d627a5c8e475b2" + "versions.yml:md5,8968b114a3e20756d8af2b80713bcc4f" ] ], "meta": { - "nf-test": "0.9.0", - "nextflow": "24.10.4" + "nf-test": "0.9.2", + "nextflow": "25.04.6" }, - "timestamp": "2025-03-26T16:05:44.067369" + "timestamp": "2025-09-08T20:58:29.629087066" } -} \ No newline at end of file +} diff --git a/modules/nf-core/openms/decoydatabase/environment.yml b/modules/nf-core/openms/decoydatabase/environment.yml index 031d2398..d85a93ef 100644 --- a/modules/nf-core/openms/decoydatabase/environment.yml +++ b/modules/nf-core/openms/decoydatabase/environment.yml @@ -4,4 +4,4 @@ channels: - conda-forge - bioconda dependencies: - - bioconda::openms=3.4.0 + - bioconda::openms=3.4.1 diff --git a/modules/nf-core/openms/decoydatabase/main.nf b/modules/nf-core/openms/decoydatabase/main.nf index 91bef3a2..42494818 100644 --- a/modules/nf-core/openms/decoydatabase/main.nf +++ b/modules/nf-core/openms/decoydatabase/main.nf @@ -4,8 +4,8 @@ process OPENMS_DECOYDATABASE { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/openms:3.4.0--hc77a4c7_0' : - 'biocontainers/openms:3.4.0--hc77a4c7_0' }" + 'https://depot.galaxyproject.org/singularity/openms:3.4.1--h81ffffe_1' : + 'biocontainers/openms:3.4.1--h81ffffe_1' }" input: tuple val(meta), path(fasta) diff --git a/modules/nf-core/openms/decoydatabase/meta.yml b/modules/nf-core/openms/decoydatabase/meta.yml index ce9399d2..b0c13d16 100644 --- a/modules/nf-core/openms/decoydatabase/meta.yml +++ b/modules/nf-core/openms/decoydatabase/meta.yml @@ -26,9 +26,10 @@ input: type: file description: Fasta file containing protein sequences pattern: "*.{fasta}" + ontologies: [] output: - - decoy_fasta: - - meta: + decoy_fasta: + - - meta: type: map description: | Groovy Map containing sample information @@ -37,11 +38,14 @@ output: type: file description: Fasta file containing proteins and decoy proteins pattern: "*.{fasta}" - - versions: - - versions.yml: - type: file - description: File containing software versions - pattern: "versions.yml" + ontologies: [] + versions: + - versions.yml: + type: file + description: File containing software versions + pattern: "versions.yml" + ontologies: + - edam: http://edamontology.org/format_3750 # YAML authors: - "@jonasscheid" maintainers: diff --git a/modules/nf-core/openms/decoydatabase/tests/main.nf.test.snap b/modules/nf-core/openms/decoydatabase/tests/main.nf.test.snap index d900f29f..d4167208 100644 --- a/modules/nf-core/openms/decoydatabase/tests/main.nf.test.snap +++ b/modules/nf-core/openms/decoydatabase/tests/main.nf.test.snap @@ -11,7 +11,7 @@ ] ], "1": [ - "versions.yml:md5,b0d04a10e7ff432572002175d1a67304" + "versions.yml:md5,3faa02db1ca8efaa13ffb542d3a418f0" ], "decoy_fasta": [ [ @@ -22,14 +22,14 @@ ] ], "versions": [ - "versions.yml:md5,b0d04a10e7ff432572002175d1a67304" + "versions.yml:md5,3faa02db1ca8efaa13ffb542d3a418f0" ] } ], "meta": { - "nf-test": "0.9.2", - "nextflow": "24.10.6" + "nf-test": "0.9.3", + "nextflow": "25.04.8" }, - "timestamp": "2025-05-11T06:06:13.820720463" + "timestamp": "2025-10-28T07:59:28.940912845" } } \ No newline at end of file diff --git a/modules/nf-core/openms/filefilter/environment.yml b/modules/nf-core/openms/filefilter/environment.yml index e7e68f4f..ad4685c0 100644 --- a/modules/nf-core/openms/filefilter/environment.yml +++ b/modules/nf-core/openms/filefilter/environment.yml @@ -4,4 +4,4 @@ channels: - conda-forge - bioconda dependencies: - - "bioconda::openms=3.4.0" + - "bioconda::openms=3.4.1" diff --git a/modules/nf-core/openms/filefilter/main.nf b/modules/nf-core/openms/filefilter/main.nf index b4942586..55788339 100644 --- a/modules/nf-core/openms/filefilter/main.nf +++ b/modules/nf-core/openms/filefilter/main.nf @@ -4,8 +4,8 @@ process OPENMS_FILEFILTER { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/openms:3.4.0--hc77a4c7_0' : - 'biocontainers/openms:3.4.0--hc77a4c7_0' }" + 'https://depot.galaxyproject.org/singularity/openms:3.4.1--h81ffffe_1' : + 'biocontainers/openms:3.4.1--h81ffffe_1' }" input: tuple val(meta), path(file) diff --git a/modules/nf-core/openms/filefilter/meta.yml b/modules/nf-core/openms/filefilter/meta.yml index 4c26bd1e..9721f9b3 100644 --- a/modules/nf-core/openms/filefilter/meta.yml +++ b/modules/nf-core/openms/filefilter/meta.yml @@ -27,9 +27,10 @@ input: description: Peptide-spectrum matches. pattern: "*.{mzML,featureXML,consensusXML}" + ontologies: [] output: - - mzml: - - meta: + mzml: + - - meta: type: map description: | Groovy Map containing sample information @@ -38,8 +39,9 @@ output: type: file description: Filtered mzML file. pattern: "*.mzML" - - featurexml: - - meta: + ontologies: [] + featurexml: + - - meta: type: map description: | Groovy Map containing sample information @@ -48,8 +50,9 @@ output: type: file description: Filtered featureXML file. pattern: "*.featureXML" - - consensusxml: - - meta: + ontologies: [] + consensusxml: + - - meta: type: map description: | Groovy Map containing sample information @@ -58,12 +61,15 @@ output: type: file description: Filtered consensusXML file. pattern: "*.consensusXML" - - versions: - - versions.yml: - type: file - description: File containing software version - pattern: "versions.yml" + ontologies: [] + versions: + - versions.yml: + type: file + description: File containing software version + pattern: "versions.yml" + ontologies: + - edam: http://edamontology.org/format_3750 # YAML authors: - "@jonasscheid" maintainers: diff --git a/modules/nf-core/openms/filefilter/tests/main.nf.test.snap b/modules/nf-core/openms/filefilter/tests/main.nf.test.snap index 9b6674ba..23a8efdd 100644 --- a/modules/nf-core/openms/filefilter/tests/main.nf.test.snap +++ b/modules/nf-core/openms/filefilter/tests/main.nf.test.snap @@ -43,7 +43,7 @@ ], "3": [ - "versions.yml:md5,9d201e84f5ae42d6c618d7537c4cf4d6" + "versions.yml:md5,1ea875205d6d20aea4dabd5e580f4d6a" ], "consensusxml": [ @@ -60,14 +60,14 @@ ] ], "versions": [ - "versions.yml:md5,9d201e84f5ae42d6c618d7537c4cf4d6" + "versions.yml:md5,1ea875205d6d20aea4dabd5e580f4d6a" ] } ], "meta": { - "nf-test": "0.9.2", - "nextflow": "24.10.6" + "nf-test": "0.9.3", + "nextflow": "25.04.8" }, - "timestamp": "2025-05-11T06:07:23.763837266" + "timestamp": "2025-10-27T13:03:04.483705593" } } \ No newline at end of file diff --git a/modules/nf-core/openms/idfilter/environment.yml b/modules/nf-core/openms/idfilter/environment.yml index e7e68f4f..ad4685c0 100644 --- a/modules/nf-core/openms/idfilter/environment.yml +++ b/modules/nf-core/openms/idfilter/environment.yml @@ -4,4 +4,4 @@ channels: - conda-forge - bioconda dependencies: - - "bioconda::openms=3.4.0" + - "bioconda::openms=3.4.1" diff --git a/modules/nf-core/openms/idfilter/main.nf b/modules/nf-core/openms/idfilter/main.nf index 718a022e..c15927bf 100644 --- a/modules/nf-core/openms/idfilter/main.nf +++ b/modules/nf-core/openms/idfilter/main.nf @@ -4,8 +4,8 @@ process OPENMS_IDFILTER { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/openms:3.4.0--hc77a4c7_0' : - 'biocontainers/openms:3.4.0--hc77a4c7_0' }" + 'https://depot.galaxyproject.org/singularity/openms:3.4.1--h81ffffe_1' : + 'biocontainers/openms:3.4.1--h81ffffe_1' }" input: tuple val(meta), path(id_file), path(filter_file) diff --git a/modules/nf-core/openms/idfilter/meta.yml b/modules/nf-core/openms/idfilter/meta.yml index d333e4b3..2bab8552 100644 --- a/modules/nf-core/openms/idfilter/meta.yml +++ b/modules/nf-core/openms/idfilter/meta.yml @@ -26,13 +26,15 @@ input: type: file description: Peptide-spectrum matches. pattern: "*.{idXML,consensusXML}" + ontologies: [] - filter_file: type: file description: Optional idXML file to filter on/out peptides or proteins patter: "*.{idXML,fasta}" + ontologies: [] output: - - filtered: - - meta: + filtered: + - - meta: type: map description: | Groovy Map containing sample information @@ -41,11 +43,14 @@ output: type: file description: Filtered peptide-spectrum matches. pattern: "*.{idXML,consensusXML}" - - versions: - - versions.yml: - type: file - description: File containing software versions - pattern: "versions.yml" + ontologies: [] + versions: + - versions.yml: + type: file + description: File containing software versions + pattern: "versions.yml" + ontologies: + - edam: http://edamontology.org/format_3750 # YAML authors: - "@jonasscheid" maintainers: diff --git a/modules/nf-core/openms/idfilter/tests/main.nf.test.snap b/modules/nf-core/openms/idfilter/tests/main.nf.test.snap index e5ea1b08..b0f4bce3 100644 --- a/modules/nf-core/openms/idfilter/tests/main.nf.test.snap +++ b/modules/nf-core/openms/idfilter/tests/main.nf.test.snap @@ -11,7 +11,7 @@ ] ], "1": [ - "versions.yml:md5,3ea19989645a1b3ac731c5cf7c6bfc0a" + "versions.yml:md5,992aca62fe3990b1ebb21d11e999dd67" ], "filtered": [ [ @@ -22,15 +22,15 @@ ] ], "versions": [ - "versions.yml:md5,3ea19989645a1b3ac731c5cf7c6bfc0a" + "versions.yml:md5,992aca62fe3990b1ebb21d11e999dd67" ] } ], "meta": { - "nf-test": "0.9.2", - "nextflow": "24.10.6" + "nf-test": "0.9.3", + "nextflow": "25.04.8" }, - "timestamp": "2025-05-11T06:07:37.369646607" + "timestamp": "2025-10-28T08:37:44.032335833" }, "proteomics - filter - idxml": { "content": [ @@ -44,7 +44,7 @@ ] ], "1": [ - "versions.yml:md5,3ea19989645a1b3ac731c5cf7c6bfc0a" + "versions.yml:md5,992aca62fe3990b1ebb21d11e999dd67" ], "filtered": [ [ @@ -55,14 +55,14 @@ ] ], "versions": [ - "versions.yml:md5,3ea19989645a1b3ac731c5cf7c6bfc0a" + "versions.yml:md5,992aca62fe3990b1ebb21d11e999dd67" ] } ], "meta": { - "nf-test": "0.9.2", - "nextflow": "24.10.6" + "nf-test": "0.9.3", + "nextflow": "25.04.8" }, - "timestamp": "2025-05-11T06:07:30.918596859" + "timestamp": "2025-10-28T08:37:18.617593794" } } \ No newline at end of file diff --git a/modules/nf-core/openms/idmassaccuracy/environment.yml b/modules/nf-core/openms/idmassaccuracy/environment.yml index e7e68f4f..ad4685c0 100644 --- a/modules/nf-core/openms/idmassaccuracy/environment.yml +++ b/modules/nf-core/openms/idmassaccuracy/environment.yml @@ -4,4 +4,4 @@ channels: - conda-forge - bioconda dependencies: - - "bioconda::openms=3.4.0" + - "bioconda::openms=3.4.1" diff --git a/modules/nf-core/openms/idmassaccuracy/main.nf b/modules/nf-core/openms/idmassaccuracy/main.nf index 5b5b3cec..819720e2 100644 --- a/modules/nf-core/openms/idmassaccuracy/main.nf +++ b/modules/nf-core/openms/idmassaccuracy/main.nf @@ -4,8 +4,8 @@ process OPENMS_IDMASSACCURACY { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/openms:3.4.0--hc77a4c7_0' : - 'biocontainers/openms:3.4.0--hc77a4c7_0' }" + 'https://depot.galaxyproject.org/singularity/openms:3.4.1--h81ffffe_1' : + 'biocontainers/openms:3.4.1--h81ffffe_1' }" input: tuple val(meta), path(mzmls), path(idxmls) diff --git a/modules/nf-core/openms/idmassaccuracy/meta.yml b/modules/nf-core/openms/idmassaccuracy/meta.yml index 5e8b1f2f..7417d69d 100644 --- a/modules/nf-core/openms/idmassaccuracy/meta.yml +++ b/modules/nf-core/openms/idmassaccuracy/meta.yml @@ -28,15 +28,17 @@ input: List containing one or more mzML files e.g. `[ 'file1.mzML', 'file2.mzML' ]` pattern: "*.{mzML}" + ontologies: [] - idxmls: type: file description: | List containing one or more idXML files e.g. `[ 'file1.idXML', 'file2.idXML' ]` pattern: "*.{idXML}" + ontologies: [] output: - - frag_err: - - meta: + frag_err: + - - meta: type: map description: | Groovy Map containing sample information @@ -45,8 +47,10 @@ output: type: file description: TSV file containing the fragment mass errors pattern: "*frag_mass_err.{tsv}" - - prec_err: - - meta: + ontologies: + - edam: http://edamontology.org/format_3475 # TSV + prec_err: + - - meta: type: map description: | Groovy Map containing sample information @@ -55,10 +59,14 @@ output: type: file description: Optional TSV file containing the precursor mass errors pattern: "*prec_mass_err.{tsv}" - - versions: - - versions.yml: - type: file - description: File containing software versions - pattern: "versions.yml" + ontologies: + - edam: http://edamontology.org/format_3475 # TSV + versions: + - versions.yml: + type: file + description: File containing software versions + pattern: "versions.yml" + ontologies: + - edam: http://edamontology.org/format_3750 # YAML authors: - "@jonasscheid" diff --git a/modules/nf-core/openms/idmassaccuracy/tests/main.nf.test.snap b/modules/nf-core/openms/idmassaccuracy/tests/main.nf.test.snap index 73c61605..69fce941 100644 --- a/modules/nf-core/openms/idmassaccuracy/tests/main.nf.test.snap +++ b/modules/nf-core/openms/idmassaccuracy/tests/main.nf.test.snap @@ -19,7 +19,7 @@ ] ], "2": [ - "versions.yml:md5,b69d76a36b0acc89f3f67b6fcab67e80" + "versions.yml:md5,1957953273bbbb30ee405df5972c299a" ], "frag_err": [ [ @@ -38,15 +38,15 @@ ] ], "versions": [ - "versions.yml:md5,b69d76a36b0acc89f3f67b6fcab67e80" + "versions.yml:md5,1957953273bbbb30ee405df5972c299a" ] } ], "meta": { - "nf-test": "0.9.2", - "nextflow": "24.10.6" + "nf-test": "0.9.3", + "nextflow": "25.04.8" }, - "timestamp": "2025-05-11T06:14:44.42431662" + "timestamp": "2025-10-28T08:11:12.815918913" }, "proteomics - openms - mass_error": { "content": [ @@ -63,7 +63,7 @@ ], "2": [ - "versions.yml:md5,b69d76a36b0acc89f3f67b6fcab67e80" + "versions.yml:md5,1957953273bbbb30ee405df5972c299a" ], "frag_err": [ [ @@ -77,14 +77,14 @@ ], "versions": [ - "versions.yml:md5,b69d76a36b0acc89f3f67b6fcab67e80" + "versions.yml:md5,1957953273bbbb30ee405df5972c299a" ] } ], "meta": { - "nf-test": "0.9.2", - "nextflow": "24.10.6" + "nf-test": "0.9.3", + "nextflow": "25.04.8" }, - "timestamp": "2025-05-11T06:14:25.837534674" + "timestamp": "2025-10-28T08:10:28.906846753" } } \ No newline at end of file diff --git a/modules/nf-core/openms/idmerger/environment.yml b/modules/nf-core/openms/idmerger/environment.yml index 031d2398..d85a93ef 100644 --- a/modules/nf-core/openms/idmerger/environment.yml +++ b/modules/nf-core/openms/idmerger/environment.yml @@ -4,4 +4,4 @@ channels: - conda-forge - bioconda dependencies: - - bioconda::openms=3.4.0 + - bioconda::openms=3.4.1 diff --git a/modules/nf-core/openms/idmerger/main.nf b/modules/nf-core/openms/idmerger/main.nf index 64c8ccae..421a77f8 100644 --- a/modules/nf-core/openms/idmerger/main.nf +++ b/modules/nf-core/openms/idmerger/main.nf @@ -4,8 +4,8 @@ process OPENMS_IDMERGER { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/openms:3.4.0--hc77a4c7_0' : - 'biocontainers/openms:3.4.0--hc77a4c7_0' }" + 'https://depot.galaxyproject.org/singularity/openms:3.4.1--h81ffffe_1' : + 'biocontainers/openms:3.4.1--h81ffffe_1' }" input: tuple val(meta), path(idxmls) diff --git a/modules/nf-core/openms/idmerger/meta.yml b/modules/nf-core/openms/idmerger/meta.yml index bf87a645..002fc578 100644 --- a/modules/nf-core/openms/idmerger/meta.yml +++ b/modules/nf-core/openms/idmerger/meta.yml @@ -28,9 +28,10 @@ input: List containing 2 or more idXML files e.g. `[ 'file1.idXML', 'file2.idXML' ]` pattern: "*.{idXML}" + ontologies: [] output: - - idxml: - - meta: + idxml: + - - meta: type: map description: | Groovy Map containing sample information @@ -39,10 +40,13 @@ output: type: file description: Merged idXML output file pattern: "*.{idXML}" - - versions: - - versions.yml: - type: file - description: File containing software versions - pattern: "versions.yml" + ontologies: [] + versions: + - versions.yml: + type: file + description: File containing software versions + pattern: "versions.yml" + ontologies: + - edam: http://edamontology.org/format_3750 # YAML authors: - "@jonasscheid" diff --git a/modules/nf-core/openms/idmerger/tests/main.nf.test.snap b/modules/nf-core/openms/idmerger/tests/main.nf.test.snap index 0c68677a..a2edce86 100644 --- a/modules/nf-core/openms/idmerger/tests/main.nf.test.snap +++ b/modules/nf-core/openms/idmerger/tests/main.nf.test.snap @@ -2,14 +2,14 @@ "proteomics - openms - idxml": { "content": [ [ - "versions.yml:md5,78d5b83faef7c749a2bd0bc0349904eb" + "versions.yml:md5,80b0fb4560c930fd7b9c31dbbd3f66d2" ] ], "meta": { - "nf-test": "0.9.2", - "nextflow": "24.10.6" + "nf-test": "0.9.3", + "nextflow": "25.04.8" }, - "timestamp": "2025-05-11T06:14:53.24277799" + "timestamp": "2025-10-28T08:54:12.914656629" }, "proteomics - openms - idxml - stub": { "content": [ @@ -23,7 +23,7 @@ ] ], "1": [ - "versions.yml:md5,78d5b83faef7c749a2bd0bc0349904eb" + "versions.yml:md5,80b0fb4560c930fd7b9c31dbbd3f66d2" ], "idxml": [ [ @@ -34,14 +34,14 @@ ] ], "versions": [ - "versions.yml:md5,78d5b83faef7c749a2bd0bc0349904eb" + "versions.yml:md5,80b0fb4560c930fd7b9c31dbbd3f66d2" ] } ], "meta": { - "nf-test": "0.9.2", - "nextflow": "24.10.6" + "nf-test": "0.9.3", + "nextflow": "25.04.8" }, - "timestamp": "2025-05-11T06:15:01.271329413" + "timestamp": "2025-10-28T08:54:41.780756135" } } \ No newline at end of file diff --git a/modules/nf-core/openms/idripper/environment.yml b/modules/nf-core/openms/idripper/environment.yml index e7e68f4f..ad4685c0 100644 --- a/modules/nf-core/openms/idripper/environment.yml +++ b/modules/nf-core/openms/idripper/environment.yml @@ -4,4 +4,4 @@ channels: - conda-forge - bioconda dependencies: - - "bioconda::openms=3.4.0" + - "bioconda::openms=3.4.1" diff --git a/modules/nf-core/openms/idripper/main.nf b/modules/nf-core/openms/idripper/main.nf index 0284b1e3..e545b906 100644 --- a/modules/nf-core/openms/idripper/main.nf +++ b/modules/nf-core/openms/idripper/main.nf @@ -4,8 +4,8 @@ process OPENMS_IDRIPPER { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/openms:3.4.0--hc77a4c7_0': - 'biocontainers/openms:3.4.0--hc77a4c7_0' }" + 'https://depot.galaxyproject.org/singularity/openms:3.4.1--h81ffffe_1': + 'biocontainers/openms:3.4.1--h81ffffe_1' }" input: tuple val(meta), path(merged_idxml) diff --git a/modules/nf-core/openms/idripper/meta.yml b/modules/nf-core/openms/idripper/meta.yml index ac35b7bc..72e62935 100644 --- a/modules/nf-core/openms/idripper/meta.yml +++ b/modules/nf-core/openms/idripper/meta.yml @@ -27,9 +27,10 @@ input: type: file description: Merged idXML file pattern: "*.{idXML}" + ontologies: [] output: - - idxmls: - - meta: + idxmls: + - - meta: type: map description: | Groovy Map containing sample information @@ -38,11 +39,14 @@ output: type: file description: Multiple idXML files pattern: "*.{idXML}" - - versions: - - versions.yml: - type: file - description: File containing software versions - pattern: "versions.yml" + ontologies: [] + versions: + - versions.yml: + type: file + description: File containing software versions + pattern: "versions.yml" + ontologies: + - edam: http://edamontology.org/format_3750 # YAML authors: - "@jonasscheid" maintainers: diff --git a/modules/nf-core/openms/idripper/tests/main.nf.test.snap b/modules/nf-core/openms/idripper/tests/main.nf.test.snap index 33de521e..6192f348 100644 --- a/modules/nf-core/openms/idripper/tests/main.nf.test.snap +++ b/modules/nf-core/openms/idripper/tests/main.nf.test.snap @@ -14,7 +14,7 @@ ] ], "1": [ - "versions.yml:md5,f610d4d87a66554519a6d7d9d0585798" + "versions.yml:md5,3949806b2abeb3db36c6dc0596f39a14" ], "idxmls": [ [ @@ -28,15 +28,15 @@ ] ], "versions": [ - "versions.yml:md5,f610d4d87a66554519a6d7d9d0585798" + "versions.yml:md5,3949806b2abeb3db36c6dc0596f39a14" ] } ], "meta": { - "nf-test": "0.9.2", - "nextflow": "24.10.6" + "nf-test": "0.9.3", + "nextflow": "25.04.8" }, - "timestamp": "2025-05-11T06:15:11.159997579" + "timestamp": "2025-10-28T08:55:11.687007226" }, "proteomics - split - idxml - stub": { "content": [ @@ -53,7 +53,7 @@ ] ], "1": [ - "versions.yml:md5,f610d4d87a66554519a6d7d9d0585798" + "versions.yml:md5,3949806b2abeb3db36c6dc0596f39a14" ], "idxmls": [ [ @@ -67,14 +67,14 @@ ] ], "versions": [ - "versions.yml:md5,f610d4d87a66554519a6d7d9d0585798" + "versions.yml:md5,3949806b2abeb3db36c6dc0596f39a14" ] } ], "meta": { - "nf-test": "0.9.2", - "nextflow": "24.10.6" + "nf-test": "0.9.3", + "nextflow": "25.04.8" }, - "timestamp": "2025-05-11T06:15:21.956236504" + "timestamp": "2025-10-28T08:55:38.405209447" } } \ No newline at end of file diff --git a/modules/nf-core/openms/idscoreswitcher/environment.yml b/modules/nf-core/openms/idscoreswitcher/environment.yml index e7e68f4f..ad4685c0 100644 --- a/modules/nf-core/openms/idscoreswitcher/environment.yml +++ b/modules/nf-core/openms/idscoreswitcher/environment.yml @@ -4,4 +4,4 @@ channels: - conda-forge - bioconda dependencies: - - "bioconda::openms=3.4.0" + - "bioconda::openms=3.4.1" diff --git a/modules/nf-core/openms/idscoreswitcher/main.nf b/modules/nf-core/openms/idscoreswitcher/main.nf index b4726002..6911b2c5 100644 --- a/modules/nf-core/openms/idscoreswitcher/main.nf +++ b/modules/nf-core/openms/idscoreswitcher/main.nf @@ -4,8 +4,8 @@ process OPENMS_IDSCORESWITCHER { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/openms:3.4.0--hc77a4c7_0': - 'biocontainers/openms:3.4.0--hc77a4c7_0' }" + 'https://depot.galaxyproject.org/singularity/openms:3.4.1--h81ffffe_1': + 'biocontainers/openms:3.4.1--h81ffffe_1' }" input: tuple val(meta), path(idxml) diff --git a/modules/nf-core/openms/idscoreswitcher/meta.yml b/modules/nf-core/openms/idscoreswitcher/meta.yml index ac4c5070..2a00b66b 100644 --- a/modules/nf-core/openms/idscoreswitcher/meta.yml +++ b/modules/nf-core/openms/idscoreswitcher/meta.yml @@ -28,9 +28,10 @@ input: type: file description: Identification file containing a primary PSM score pattern: "*.{idXML}" + ontologies: [] output: - - idxml: - - meta: + idxml: + - - meta: type: map description: | Groovy Map containing sample information @@ -41,11 +42,14 @@ output: Identification file containing a new primary PSM score obtained from a specified meta value pattern: "*.{idXML}" - - versions: - - versions.yml: - type: file - description: File containing software versions - pattern: "versions.yml" + ontologies: [] + versions: + - versions.yml: + type: file + description: File containing software versions + pattern: "versions.yml" + ontologies: + - edam: http://edamontology.org/format_3750 # YAML authors: - "@jonasscheid" maintainers: diff --git a/modules/nf-core/openms/idscoreswitcher/tests/main.nf.test.snap b/modules/nf-core/openms/idscoreswitcher/tests/main.nf.test.snap index 89eaad70..c9d84825 100644 --- a/modules/nf-core/openms/idscoreswitcher/tests/main.nf.test.snap +++ b/modules/nf-core/openms/idscoreswitcher/tests/main.nf.test.snap @@ -11,7 +11,7 @@ ] ], "1": [ - "versions.yml:md5,8ac4c680e1cc079a0b736ac11cf86c27" + "versions.yml:md5,658341a6b21a155b1c141c94c54c4ae3" ], "idxml": [ [ @@ -22,15 +22,15 @@ ] ], "versions": [ - "versions.yml:md5,8ac4c680e1cc079a0b736ac11cf86c27" + "versions.yml:md5,658341a6b21a155b1c141c94c54c4ae3" ] } ], "meta": { - "nf-test": "0.9.2", - "nextflow": "24.10.6" + "nf-test": "0.9.3", + "nextflow": "25.04.8" }, - "timestamp": "2025-05-11T06:15:42.364545675" + "timestamp": "2025-10-28T09:04:11.118518193" }, "proteomics - switch_score - idxml": { "content": [ @@ -44,7 +44,7 @@ ] ], "1": [ - "versions.yml:md5,8ac4c680e1cc079a0b736ac11cf86c27" + "versions.yml:md5,658341a6b21a155b1c141c94c54c4ae3" ], "idxml": [ [ @@ -55,14 +55,14 @@ ] ], "versions": [ - "versions.yml:md5,8ac4c680e1cc079a0b736ac11cf86c27" + "versions.yml:md5,658341a6b21a155b1c141c94c54c4ae3" ] } ], "meta": { - "nf-test": "0.9.2", - "nextflow": "24.10.6" + "nf-test": "0.9.3", + "nextflow": "25.04.8" }, - "timestamp": "2025-05-11T06:15:34.913738356" + "timestamp": "2025-10-28T09:03:44.673575882" } } \ No newline at end of file diff --git a/modules/nf-core/openms/peakpickerhires/environment.yml b/modules/nf-core/openms/peakpickerhires/environment.yml index 90fd54af..664bf59d 100644 --- a/modules/nf-core/openms/peakpickerhires/environment.yml +++ b/modules/nf-core/openms/peakpickerhires/environment.yml @@ -2,4 +2,4 @@ channels: - conda-forge - bioconda dependencies: - - "bioconda::openms=3.4.0" + - "bioconda::openms=3.4.1" diff --git a/modules/nf-core/openms/peakpickerhires/main.nf b/modules/nf-core/openms/peakpickerhires/main.nf index 5eafad22..9ac6e935 100644 --- a/modules/nf-core/openms/peakpickerhires/main.nf +++ b/modules/nf-core/openms/peakpickerhires/main.nf @@ -4,8 +4,8 @@ process OPENMS_PEAKPICKERHIRES { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/openms:3.4.0--hc77a4c7_0' : - 'biocontainers/openms:3.4.0--hc77a4c7_0' }" + 'https://depot.galaxyproject.org/singularity/openms:3.4.1--h81ffffe_1' : + 'biocontainers/openms:3.4.1--h81ffffe_1' }" input: tuple val(meta), path(mzml) diff --git a/modules/nf-core/openms/peakpickerhires/meta.yml b/modules/nf-core/openms/peakpickerhires/meta.yml index b10460b9..db8feaad 100644 --- a/modules/nf-core/openms/peakpickerhires/meta.yml +++ b/modules/nf-core/openms/peakpickerhires/meta.yml @@ -27,9 +27,10 @@ input: type: file description: Mass spectrometer output file in mzML format pattern: "*.{mzML}" + ontologies: [] output: - - mzml: - - meta: + mzml: + - - meta: type: map description: | Groovy Map containing sample information @@ -38,11 +39,14 @@ output: type: file description: Peak-picked mass spectrometer output file in mzML format pattern: "*.{mzML}" - - versions: - - versions.yml: - type: file - description: File containing software versions - pattern: "versions.yml" + ontologies: [] + versions: + - versions.yml: + type: file + description: File containing software versions + pattern: "versions.yml" + ontologies: + - edam: http://edamontology.org/format_3750 # YAML authors: - "@jonasscheid" maintainers: diff --git a/modules/nf-core/openms/peakpickerhires/tests/main.nf.test.snap b/modules/nf-core/openms/peakpickerhires/tests/main.nf.test.snap index d86b6154..83f15738 100644 --- a/modules/nf-core/openms/peakpickerhires/tests/main.nf.test.snap +++ b/modules/nf-core/openms/peakpickerhires/tests/main.nf.test.snap @@ -2,14 +2,14 @@ "proteomics - mzML": { "content": [ [ - "versions.yml:md5,a4838f8642ae49bf81211bd7cf868f00" + "versions.yml:md5,69c600d25edebd411ef84718668821df" ] ], "meta": { - "nf-test": "0.9.2", - "nextflow": "24.10.6" + "nf-test": "0.9.3", + "nextflow": "25.04.8" }, - "timestamp": "2025-05-11T06:15:50.174009616" + "timestamp": "2025-10-28T09:07:00.776951188" }, "proteomics - mzML - stub": { "content": [ @@ -23,7 +23,7 @@ ] ], "1": [ - "versions.yml:md5,a4838f8642ae49bf81211bd7cf868f00" + "versions.yml:md5,69c600d25edebd411ef84718668821df" ], "mzml": [ [ @@ -34,14 +34,14 @@ ] ], "versions": [ - "versions.yml:md5,a4838f8642ae49bf81211bd7cf868f00" + "versions.yml:md5,69c600d25edebd411ef84718668821df" ] } ], "meta": { - "nf-test": "0.9.2", - "nextflow": "24.10.6" + "nf-test": "0.9.3", + "nextflow": "25.04.8" }, - "timestamp": "2025-05-11T06:15:58.056639511" + "timestamp": "2025-10-28T09:07:18.50818535" } } \ No newline at end of file diff --git a/modules/nf-core/openms/peptideindexer/environment.yml b/modules/nf-core/openms/peptideindexer/environment.yml index e7e68f4f..ad4685c0 100644 --- a/modules/nf-core/openms/peptideindexer/environment.yml +++ b/modules/nf-core/openms/peptideindexer/environment.yml @@ -4,4 +4,4 @@ channels: - conda-forge - bioconda dependencies: - - "bioconda::openms=3.4.0" + - "bioconda::openms=3.4.1" diff --git a/modules/nf-core/openms/peptideindexer/main.nf b/modules/nf-core/openms/peptideindexer/main.nf index 37dc9ddb..1456a908 100644 --- a/modules/nf-core/openms/peptideindexer/main.nf +++ b/modules/nf-core/openms/peptideindexer/main.nf @@ -4,8 +4,8 @@ process OPENMS_PEPTIDEINDEXER { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/openms:3.4.0--hc77a4c7_0' : - 'biocontainers/openms:3.4.0--hc77a4c7_0' }" + 'https://depot.galaxyproject.org/singularity/openms:3.4.1--h81ffffe_1' : + 'biocontainers/openms:3.4.1--h81ffffe_1' }" input: tuple val(meta), path(idxml), path(fasta) diff --git a/modules/nf-core/openms/peptideindexer/meta.yml b/modules/nf-core/openms/peptideindexer/meta.yml index c55a5927..1c200b5d 100644 --- a/modules/nf-core/openms/peptideindexer/meta.yml +++ b/modules/nf-core/openms/peptideindexer/meta.yml @@ -25,13 +25,15 @@ input: type: file description: idXML identification file pattern: "*.idXML" + ontologies: [] - fasta: type: file description: Input sequence database in FASTA format pattern: "*.fasta" + ontologies: [] output: - - indexed_idxml: - - meta: + indexed_idxml: + - - meta: type: map description: | Groovy Map containing sample information @@ -40,11 +42,14 @@ output: type: file description: Refreshed idXML identification file pattern: "*.idXML" - - versions: - - versions.yml: - type: file - description: File containing software versions - pattern: "versions.yml" + ontologies: [] + versions: + - versions.yml: + type: file + description: File containing software versions + pattern: "versions.yml" + ontologies: + - edam: http://edamontology.org/format_3750 # YAML authors: - "@jonasscheid" maintainers: diff --git a/modules/nf-core/openms/peptideindexer/tests/main.nf.test.snap b/modules/nf-core/openms/peptideindexer/tests/main.nf.test.snap index 3cecc1e7..0aa17984 100644 --- a/modules/nf-core/openms/peptideindexer/tests/main.nf.test.snap +++ b/modules/nf-core/openms/peptideindexer/tests/main.nf.test.snap @@ -11,7 +11,7 @@ ] ], "1": [ - "versions.yml:md5,2f8e7d19cf57587652e1377a6273177f" + "versions.yml:md5,c2965a55db2530b792b1620a935107d2" ], "indexed_idxml": [ [ @@ -22,15 +22,15 @@ ] ], "versions": [ - "versions.yml:md5,2f8e7d19cf57587652e1377a6273177f" + "versions.yml:md5,c2965a55db2530b792b1620a935107d2" ] } ], "meta": { - "nf-test": "0.9.2", - "nextflow": "24.10.6" + "nf-test": "0.9.3", + "nextflow": "25.04.8" }, - "timestamp": "2025-05-11T06:16:11.225978857" + "timestamp": "2025-10-28T08:11:48.453753483" }, "proteomics - refresh_idxml - stub": { "content": [ @@ -44,7 +44,7 @@ ] ], "1": [ - "versions.yml:md5,2f8e7d19cf57587652e1377a6273177f" + "versions.yml:md5,c2965a55db2530b792b1620a935107d2" ], "indexed_idxml": [ [ @@ -55,14 +55,14 @@ ] ], "versions": [ - "versions.yml:md5,2f8e7d19cf57587652e1377a6273177f" + "versions.yml:md5,c2965a55db2530b792b1620a935107d2" ] } ], "meta": { - "nf-test": "0.9.2", - "nextflow": "24.10.6" + "nf-test": "0.9.3", + "nextflow": "25.04.8" }, - "timestamp": "2025-05-11T06:16:21.235680472" + "timestamp": "2025-10-28T08:12:25.400421367" } } \ No newline at end of file diff --git a/modules/nf-core/openmsthirdparty/cometadapter/environment.yml b/modules/nf-core/openmsthirdparty/cometadapter/environment.yml index dac67a18..7e9c2818 100644 --- a/modules/nf-core/openmsthirdparty/cometadapter/environment.yml +++ b/modules/nf-core/openmsthirdparty/cometadapter/environment.yml @@ -4,4 +4,4 @@ channels: - conda-forge - bioconda dependencies: - - "bioconda::openms-thirdparty=3.4.0" + - "bioconda::openms-thirdparty=3.4.1" diff --git a/modules/nf-core/openmsthirdparty/cometadapter/main.nf b/modules/nf-core/openmsthirdparty/cometadapter/main.nf index 7056129d..27fc32fd 100644 --- a/modules/nf-core/openmsthirdparty/cometadapter/main.nf +++ b/modules/nf-core/openmsthirdparty/cometadapter/main.nf @@ -4,8 +4,8 @@ process OPENMSTHIRDPARTY_COMETADAPTER { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://depot.galaxyproject.org/singularity/openms-thirdparty:3.4.0--h9ee0642_0' : - 'biocontainers/openms-thirdparty:3.4.0--h9ee0642_0' }" + 'https://depot.galaxyproject.org/singularity/openms-thirdparty:3.4.1--h9ee0642_1' : + 'biocontainers/openms-thirdparty:3.4.1--h9ee0642_1' }" input: tuple val(meta), path(mzml), path(fasta) diff --git a/modules/nf-core/openmsthirdparty/cometadapter/meta.yml b/modules/nf-core/openmsthirdparty/cometadapter/meta.yml index 453781fb..50c1e1e4 100644 --- a/modules/nf-core/openmsthirdparty/cometadapter/meta.yml +++ b/modules/nf-core/openmsthirdparty/cometadapter/meta.yml @@ -27,13 +27,15 @@ input: type: file description: File containing mass spectra in mzML format pattern: "*.{mzML}" + ontologies: [] - fasta: type: file description: Protein sequence database containing targets and decoys pattern: "*.{fasta}" + ontologies: [] output: - - idxml: - - meta: + idxml: + - - meta: type: map description: | Groovy Map containing sample information @@ -42,8 +44,9 @@ output: type: file description: File containing target and decoy hits in idXML format pattern: "*.{idXML}" - - pin: - - meta: + ontologies: [] + pin: + - - meta: type: map description: | Groovy Map containing sample information @@ -52,11 +55,15 @@ output: type: file description: TSV file tailored as Percolator input (pin) file pattern: "*.{tsv}" - - versions: - - versions.yml: - type: file - description: File containing software versions - pattern: "versions.yml" + ontologies: + - edam: http://edamontology.org/format_3475 # TSV + versions: + - versions.yml: + type: file + description: File containing software versions + pattern: "versions.yml" + ontologies: + - edam: http://edamontology.org/format_3750 # YAML authors: - "@jonasscheid" maintainers: diff --git a/modules/nf-core/openmsthirdparty/cometadapter/tests/main.nf.test.snap b/modules/nf-core/openmsthirdparty/cometadapter/tests/main.nf.test.snap index 685c4851..81a248a8 100644 --- a/modules/nf-core/openmsthirdparty/cometadapter/tests/main.nf.test.snap +++ b/modules/nf-core/openmsthirdparty/cometadapter/tests/main.nf.test.snap @@ -45,15 +45,15 @@ "content": [ { "OPENMSTHIRDPARTY_COMETADAPTER": { - "CometAdapter": "3.4.0", + "CometAdapter": "3.4.1", "Comet": "2024.01 rev. 1" } } ], "meta": { - "nf-test": "0.9.2", - "nextflow": "24.10.6" + "nf-test": "0.9.3", + "nextflow": "25.04.8" }, - "timestamp": "2025-05-11T06:19:57.937114544" + "timestamp": "2025-10-28T08:16:50.757046344" } } \ No newline at end of file diff --git a/modules/nf-core/thermorawfileparser/meta.yml b/modules/nf-core/thermorawfileparser/meta.yml index 7235bc31..26e37e07 100644 --- a/modules/nf-core/thermorawfileparser/meta.yml +++ b/modules/nf-core/thermorawfileparser/meta.yml @@ -28,9 +28,10 @@ input: type: file description: Thermo RAW file pattern: "*.{raw,RAW}" + ontologies: [] output: - - spectra: - - meta: + spectra: + - - meta: type: map description: | Groovy Map containing sample information @@ -39,11 +40,14 @@ output: type: file description: Mass spectra in open format pattern: "*.{mzML,mzML.gz,mgf,mgf.gz,parquet,parquet.gz}" - - versions: - - versions.yml: - type: file - description: File containing software versions - pattern: "versions.yml" + ontologies: [] + versions: + - versions.yml: + type: file + description: File containing software versions + pattern: "versions.yml" + ontologies: + - edam: http://edamontology.org/format_3750 # YAML authors: - "@jonasscheid" maintainers: diff --git a/nextflow.config b/nextflow.config index 87574cff..97ebb856 100644 --- a/nextflow.config +++ b/nextflow.config @@ -20,6 +20,7 @@ params { generate_speclib = false quantify = false annotate_ions = false + epicore = false // Comet search parameters default_params_file_comet = ' ' @@ -74,6 +75,11 @@ params { quantification_min_peak_width = 0.2 quantification_mapping_tolerance = 0 + // Epicore settings + epicore_min_overlap = 11 + epicore_max_step_size = 5 + epicore_min_epi_length = 11 + // MultiQC options multiqc_config = null multiqc_title = null @@ -88,13 +94,15 @@ params { email_on_fail = null plaintext_email = false monochrome_logs = false - hook_url = null + hook_url = System.getenv('HOOK_URL') help = false help_full = false show_hidden = false version = false pipelines_testdata_base_path = 'https://raw.githubusercontent.com/nf-core/test-datasets/' - trace_report_suffix = new java.util.Date().format( 'yyyy-MM-dd_HH-mm-ss')// Config options + trace_report_suffix = new java.util.Date().format( 'yyyy-MM-dd_HH-mm-ss') + + // Config options config_profile_name = null config_profile_description = null @@ -147,8 +155,19 @@ profiles { apptainer.enabled = false process.containerOptions = '-u $(id -u):$(id -g)' } - arm { - process.containerOptions = '-u $(id -u):$(id -g) --platform=linux/amd64' + arm64 { + process.arch = 'arm64' + // TODO https://github.com/nf-core/modules/issues/6694 + // For now if you're using arm64 you have to use wave for the sake of the maintainers + // wave profile + apptainer.ociAutoPull = true + singularity.ociAutoPull = true + wave.enabled = true + wave.freeze = true + wave.strategy = 'conda,container' + } + emulate_amd64 { + docker.runOptions = '-u $(id -u):$(id -g) --platform=linux/amd64' } singularity { singularity.enabled = true @@ -204,32 +223,29 @@ profiles { wave.freeze = true wave.strategy = 'conda,container' } - gitpod { - executor.name = 'local' - executor.cpus = 4 - executor.memory = 8.GB - process { - resourceLimits = [ - memory: 8.GB, - cpus : 4, - time : 1.h - ] - } + gpu { + docker.runOptions = '-u $(id -u):$(id -g) --gpus all' + apptainer.runOptions = '--nv' + singularity.runOptions = '--nv' } test { includeConfig 'conf/test.config' } test_mokapot { includeConfig 'conf/test_mokapot.config' } test_percolator { includeConfig 'conf/test_percolator.config' } test_ionannotator { includeConfig 'conf/test_ionannotator.config' } + test_epicore { includeConfig 'conf/test_epicore.config' } test_speclib { includeConfig 'conf/test_speclib.config' } test_timstof { includeConfig 'conf/test_timstof.config' } test_full { includeConfig 'conf/test_full.config' } } -// Load nf-core custom profiles from different Institutions -includeConfig !System.getenv('NXF_OFFLINE') && params.custom_config_base ? "${params.custom_config_base}/nfcore_custom.config" : "/dev/null" +// Load nf-core custom profiles from different institutions +// If params.custom_config_base is set AND either the NXF_OFFLINE environment variable is not set or params.custom_config_base is a local path, the nfcore_custom.config file from the specified base path is included. // Load nf-core/mhcquant custom profiles from different institutions. -includeConfig !System.getenv('NXF_OFFLINE') && params.custom_config_base ? "${params.custom_config_base}/pipeline/mhcquant.config" : "/dev/null" +includeConfig params.custom_config_base && (!System.getenv('NXF_OFFLINE') || !params.custom_config_base.startsWith('http')) ? "${params.custom_config_base}/nfcore_custom.config" : "/dev/null" + +// Optionally, you can add a pipeline-specific nf-core config at https://github.com/nf-core/configs +includeConfig params.custom_config_base && (!System.getenv('NXF_OFFLINE') || !params.custom_config_base.startsWith('http')) ? "${params.custom_config_base}/pipeline/mhcquant.config" : "/dev/null" // Set default registry for Apptainer, Docker, Podman, Charliecloud and Singularity independent of -profile // Will not be used unless Apptainer / Docker / Podman / Charliecloud / Singularity are enabled @@ -283,7 +299,6 @@ dag { manifest { name = 'nf-core/mhcquant' - author = """Jonas Scheid, Steffen Lemke, Leon Bichmann, Marissa Dubbelaar""" // The author field is deprecated from Nextflow version 24.10.0, use contributors instead contributors = [ [ name: 'Jonas Scheid', @@ -324,52 +339,33 @@ manifest { github: '@JuliaGraf', contribution: ['contributor'], // List of contribution types ('author', 'maintainer' or 'contributor') orcid: '' + ], + [ + name: 'Jana Hoffmann', + affiliation: '', + email: '', + github: '@janaHoffmann1', + contribution: ['contributor'], // List of contribution types ('author', 'maintainer' or 'contributor') + orcid: '' ] ] homePage = 'https://github.com/nf-core/mhcquant' description = """Identify and quantify peptides from mass spectrometry raw data""" mainScript = 'main.nf' defaultBranch = 'master' - nextflowVersion = '!>=24.04.2' - version = '3.0.0' - doi = '10.1021/acs.jproteome.9b00313' + nextflowVersion = '!>=25.04.0' + version = '3.1.0' + doi = '10.1186/s13059-025-03763-8' } // Nextflow plugins plugins { - id 'nf-schema@2.2.0' // Validation of pipeline parameters and creation of an input channel from a sample sheet + id 'nf-schema@2.5.1' // Validation of pipeline parameters and creation of an input channel from a sample sheet } validation { defaultIgnoreParams = ["genomes"] monochromeLogs = params.monochrome_logs - help { - enabled = true - command = "nextflow run nf-core/mhcquant -profile --input samplesheet.csv --outdir " - fullParameter = "help_full" - showHiddenParameter = "show_hidden" - beforeText = """ --\033[2m----------------------------------------------------\033[0m- - \033[0;32m,--.\033[0;30m/\033[0;32m,-.\033[0m -\033[0;34m ___ __ __ __ ___ \033[0;32m/,-._.--~\'\033[0m -\033[0;34m |\\ | |__ __ / ` / \\ |__) |__ \033[0;33m} {\033[0m -\033[0;34m | \\| | \\__, \\__/ | \\ |___ \033[0;32m\\`-._,-`-,\033[0m - \033[0;32m`._,._,\'\033[0m -\033[0;35m nf-core/mhcquant ${manifest.version}\033[0m --\033[2m----------------------------------------------------\033[0m- -""" - afterText = """${manifest.doi ? "\n* The pipeline\n" : ""}${manifest.doi.tokenize(",").collect { " https://doi.org/${it.trim().replace('https://doi.org/','')}"}.join("\n")}${manifest.doi ? "\n" : ""} -* The nf-core framework - https://doi.org/10.1038/s41587-020-0439-x - -* Software dependencies - https://github.com/nf-core/mhcquant/blob/master/CITATIONS.md -""" - } - summary { - beforeText = validation.help.beforeText - afterText = validation.help.afterText - } } // Load modules.config for DSL2 module specific options diff --git a/nextflow_schema.json b/nextflow_schema.json index 478f5790..05d3b5b0 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -48,7 +48,6 @@ "type": "object", "fa_icon": "fas fa-database", "description": "Decoy Database generation settings", - "required": ["fasta"], "properties": { "fasta": { "type": "string", @@ -59,6 +58,7 @@ }, "skip_decoy_generation": { "type": "boolean", + "default": false, "fa_icon": "fas fa-fast-forward", "description": "Add this parameter when you want to skip the generation of the decoy database.", "help_text": "If you want to use your own decoys, you can specify a dataset that includes decoy sequences. However, each database entry should keep the prefix 'DECOY_'." @@ -139,11 +139,13 @@ }, "digest_mass_range": { "type": "string", + "default": "800:2500", "fa_icon": "fas fa-line-height", "description": "Specify the mass range in Dalton that peptides should fulfill to be considered for peptide spectrum matching." }, "prec_charge": { "type": "string", + "default": "2:3", "fa_icon": "fas fa-bolt", "description": "Specify the precursor charge range that peptides should fulfill to be considered for peptide spectrum matching." }, @@ -202,34 +204,39 @@ }, "use_x_ions": { "type": "boolean", + "default": false, "fa_icon": "fas fa-wave-sine", "description": "Include x ions into the peptide spectrum matching" }, "use_z_ions": { "type": "boolean", + "default": false, "fa_icon": "fas fa-wave-sine", "description": "Include z ions into the peptide spectrum matching" }, "use_a_ions": { "type": "boolean", + "default": false, "fa_icon": "fas fa-wave-sine", "description": "Include a ions into the peptide spectrum matching" }, "use_c_ions": { "type": "boolean", + "default": false, "fa_icon": "fas fa-wave-sine", "description": "Include c ions into the peptide spectrum matching" }, "use_NL_ions": { "type": "boolean", + "default": false, "fa_icon": "fas fa-wave-sine", "description": "Include NL ions into the peptide spectrum matching" }, "remove_precursor_peak": { "type": "boolean", + "default": false, "fa_icon": "fas fa-pipe", - "description": "Include if you want to remove all peaks around precursor m/z", - "default": "false" + "description": "Include if you want to remove all peaks around precursor m/z" }, "spectrum_batch_size": { "type": "integer", @@ -427,6 +434,39 @@ } } }, + "epicore_options": { + "title": "Epicore Options", + "type": "object", + "fa_icon": "fa-solid fa-stairs", + "description": "", + "default": "", + "properties": { + "epicore": { + "type": "boolean", + "default": false, + "fa_icon": "fa-solid fa-stairs", + "description": "Compute core epitopes from overlapping peptides." + }, + "epicore_min_overlap": { + "type": "integer", + "default": 11, + "fa_icon": "fas fa-filter", + "description": "Specify the minimal overlap of two peptides so they are grouped together." + }, + "epicore_max_step_size": { + "type": "integer", + "default": 5, + "fa_icon": "fas fa-filter", + "description": "Specify the maximal difference between the start position of two peptides so they are still grouped together." + }, + "epicore_min_epi_length": { + "type": "integer", + "default": 11, + "fa_icon": "fas fa-filter", + "description": "Specify the minimal length of an core epitope." + } + } + }, "institutional_config_options": { "title": "Institutional config options", "type": "object", @@ -484,6 +524,7 @@ "properties": { "version": { "type": "boolean", + "default": false, "description": "Display version and exit.", "fa_icon": "fas fa-question-circle", "hidden": true @@ -507,6 +548,7 @@ }, "plaintext_email": { "type": "boolean", + "default": false, "description": "Send plain-text email instead of HTML.", "fa_icon": "fas fa-remove-format", "hidden": true @@ -521,6 +563,7 @@ }, "monochrome_logs": { "type": "boolean", + "default": false, "description": "Do not use coloured log outputs.", "fa_icon": "fas fa-palette", "hidden": true @@ -569,6 +612,18 @@ "fa_icon": "far calendar", "description": "Suffix to add to the trace report filename. Default is the date and time in the format yyyy-MM-dd_HH-mm-ss.", "hidden": true + }, + "help": { + "type": ["boolean", "string"], + "description": "Display the help message." + }, + "help_full": { + "type": "boolean", + "description": "Display the full detailed help message." + }, + "show_hidden": { + "type": "boolean", + "description": "Display hidden parameters in the help message (only works when --help or --help_full are provided)." } } } @@ -595,6 +650,9 @@ { "$ref": "#/$defs/post_processing" }, + { + "$ref": "#/$defs/epicore_options" + }, { "$ref": "#/$defs/institutional_config_options" }, diff --git a/nf-test.config b/nf-test.config new file mode 100644 index 00000000..3a1fff59 --- /dev/null +++ b/nf-test.config @@ -0,0 +1,24 @@ +config { + // location for all nf-test tests + testsDir "." + + // nf-test directory including temporary files for each test + workDir System.getenv("NFT_WORKDIR") ?: ".nf-test" + + // location of an optional nextflow.config file specific for executing tests + configFile "tests/nextflow.config" + + // ignore tests coming from the nf-core/modules repo + ignore 'modules/nf-core/**/tests/*', 'subworkflows/nf-core/**/tests/*' + + // run all test with defined profile(s) from the main nextflow.config + profile "test" + + // list of filenames or patterns that should be trigger a full test run + triggers 'nextflow.config', 'nf-test.config', 'conf/test.config', 'tests/nextflow.config', 'tests/.nftignore' + + // load the necessary plugins + plugins { + load "nft-utils@0.0.3" + } +} diff --git a/ro-crate-metadata.json b/ro-crate-metadata.json index 3d5b4315..9484fb86 100644 --- a/ro-crate-metadata.json +++ b/ro-crate-metadata.json @@ -21,9 +21,9 @@ { "@id": "./", "@type": "Dataset", - "creativeWorkStatus": "InProgress", - "datePublished": "2025-04-30T12:27:00+00:00", - "description": "

\n \n \n \"nf-core/mhcquant\"\n \n

\n\n[![GitHub Actions CI Status](https://github.com/nf-core/mhcquant/actions/workflows/ci.yml/badge.svg)](https://github.com/nf-core/mhcquant/actions/workflows/ci.yml)\n[![GitHub Actions Linting Status](https://github.com/nf-core/mhcquant/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/mhcquant/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/mhcquant/results)[![Cite with Zenodo](http://img.shields.io/badge/DOI-10.5281/zenodo.8427707-1073c8?labelColor=000000)](https://doi.org/10.5281/zenodo.8427707)\n[![nf-test](https://img.shields.io/badge/unit_tests-nf--test-337ab7.svg)](https://www.nf-test.com)\n\n[![Nextflow](https://img.shields.io/badge/nextflow%20DSL2-%E2%89%A524.04.2-23aa62.svg)](https://www.nextflow.io/)\n[![run with conda](http://img.shields.io/badge/run%20with-conda-3EB049?labelColor=000000&logo=anaconda)](https://docs.conda.io/en/latest/)\n[![run with docker](https://img.shields.io/badge/run%20with-docker-0db7ed?labelColor=000000&logo=docker)](https://www.docker.com/)\n[![run with singularity](https://img.shields.io/badge/run%20with-singularity-1d355c.svg?labelColor=000000)](https://sylabs.io/docs/)\n[![Launch on Seqera Platform](https://img.shields.io/badge/Launch%20%F0%9F%9A%80-Seqera%20Platform-%234256e7)](https://cloud.seqera.io/launch?pipeline=https://github.com/nf-core/mhcquant)\n\n[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23mhcquant-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/mhcquant)[![Follow on Twitter](http://img.shields.io/badge/twitter-%40nf__core-1DA1F2?labelColor=000000&logo=twitter)](https://twitter.com/nf_core)[![Follow on Mastodon](https://img.shields.io/badge/mastodon-nf__core-6364ff?labelColor=FFFFFF&logo=mastodon)](https://mstdn.science/@nf_core)[![Watch on YouTube](http://img.shields.io/badge/youtube-nf--core-FF0000?labelColor=000000&logo=youtube)](https://www.youtube.com/c/nf-core)\n\n## Introduction\n\n**nf-core/mhcquant** is a bioinformatics pipeline that ...\n\n\n\n\n1. Read QC ([`FastQC`](https://www.bioinformatics.babraham.ac.uk/projects/fastqc/))2. Present QC for raw reads ([`MultiQC`](http://multiqc.info/))\n\n## Usage\n\n> [!NOTE]\n> If you are new to Nextflow and nf-core, please refer to [this page](https://nf-co.re/docs/usage/installation) on how to set-up Nextflow. Make sure to [test your setup](https://nf-co.re/docs/usage/introduction#how-to-run-a-pipeline) with `-profile test` before running the workflow on actual data.\n\n\n\nNow, you can run the pipeline using:\n\n\n\n```bash\nnextflow run nf-core/mhcquant \\\n -profile \\\n --input samplesheet.csv \\\n --outdir \n```\n\n> [!WARNING]\n> Please provide pipeline parameters via the CLI or Nextflow `-params-file` option. Custom config files including those provided by the `-c` Nextflow option can be used to provide any configuration _**except for parameters**_; see [docs](https://nf-co.re/docs/usage/getting_started/configuration#custom-configuration-files).\n\nFor more details and further functionality, please refer to the [usage documentation](https://nf-co.re/mhcquant/usage) and the [parameter documentation](https://nf-co.re/mhcquant/parameters).\n\n## Pipeline output\n\nTo see the results of an example test run with a full size dataset refer to the [results](https://nf-co.re/mhcquant/results) tab on the nf-core website pipeline page.\nFor more details about the output files and reports, please refer to the\n[output documentation](https://nf-co.re/mhcquant/output).\n\n## Credits\n\nnf-core/mhcquant was originally written by Jonas Scheid, Steffen Lemke, Leon Bichmann, Marissa Dubbelaar.\n\nWe thank the following people for their extensive assistance in the development of this pipeline:\n\n\n\n## Contributions and Support\n\nIf you would like to contribute to this pipeline, please see the [contributing guidelines](.github/CONTRIBUTING.md).\n\nFor further information or help, don't hesitate to get in touch on the [Slack `#mhcquant` channel](https://nfcore.slack.com/channels/mhcquant) (you can join with [this invite](https://nf-co.re/join/slack)).\n\n## Citations\n\n\n\n\n\n\nAn extensive list of references for the tools used by the pipeline can be found in the [`CITATIONS.md`](CITATIONS.md) file.\n\nYou can cite the `nf-core` publication as follows:\n\n> **The nf-core framework for community-curated bioinformatics pipelines.**\n>\n> Philip Ewels, Alexander Peltzer, Sven Fillinger, Harshil Patel, Johannes Alneberg, Andreas Wilm, Maxime Ulysse Garcia, Paolo Di Tommaso & Sven Nahnsen.\n>\n> _Nat Biotechnol._ 2020 Feb 13. doi: [10.1038/s41587-020-0439-x](https://dx.doi.org/10.1038/s41587-020-0439-x).\n", + "creativeWorkStatus": "Stable", + "datePublished": "2025-10-20T07:45:13+00:00", + "description": "

\n \n \n \"nf-core/mhcquant\"\n \n

\n\n[![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://github.com/codespaces/new/nf-core/mhcquant)\n[![GitHub Actions CI Status](https://github.com/nf-core/mhcquant/actions/workflows/nf-test.yml/badge.svg)](https://github.com/nf-core/mhcquant/actions/workflows/nf-test.yml)\n[![GitHub Actions Linting Status](https://github.com/nf-core/mhcquant/actions/workflows/linting.yml/badge.svg)](https://github.com/nf-core/mhcquant/actions/workflows/linting.yml)[![AWS CI](https://img.shields.io/badge/CI%20tests-full%20size-FF9900?labelColor=000000&logo=Amazon%20AWS)](https://nf-co.re/mhcquant/results)[![Cite with Zenodo](http://img.shields.io/badge/DOI-10.5281/zenodo.8427707-1073c8?labelColor=000000)](https://doi.org/10.5281/zenodo.8427707)\n[![nf-test](https://img.shields.io/badge/unit_tests-nf--test-337ab7.svg)](https://www.nf-test.com)\n\n[![Nextflow](https://img.shields.io/badge/version-%E2%89%A525.04.0-green?style=flat&logo=nextflow&logoColor=white&color=%230DC09D&link=https%3A%2F%2Fnextflow.io)](https://www.nextflow.io/)\n[![nf-core template version](https://img.shields.io/badge/nf--core_template-3.4.1-green?style=flat&logo=nfcore&logoColor=white&color=%2324B064&link=https%3A%2F%2Fnf-co.re)](https://github.com/nf-core/tools/releases/tag/3.4.1)\n[![run with conda](http://img.shields.io/badge/run%20with-conda-3EB049?labelColor=000000&logo=anaconda)](https://docs.conda.io/en/latest/)\n[![run with docker](https://img.shields.io/badge/run%20with-docker-0db7ed?labelColor=000000&logo=docker)](https://www.docker.com/)\n[![run with singularity](https://img.shields.io/badge/run%20with-singularity-1d355c.svg?labelColor=000000)](https://sylabs.io/docs/)\n[![Launch on Seqera Platform](https://img.shields.io/badge/Launch%20%F0%9F%9A%80-Seqera%20Platform-%234256e7)](https://cloud.seqera.io/launch?pipeline=https://github.com/nf-core/mhcquant)\n\n[![Get help on Slack](http://img.shields.io/badge/slack-nf--core%20%23mhcquant-4A154B?labelColor=000000&logo=slack)](https://nfcore.slack.com/channels/mhcquant)[![Follow on Bluesky](https://img.shields.io/badge/bluesky-%40nf__core-1185fe?labelColor=000000&logo=bluesky)](https://bsky.app/profile/nf-co.re)[![Follow on Mastodon](https://img.shields.io/badge/mastodon-nf__core-6364ff?labelColor=FFFFFF&logo=mastodon)](https://mstdn.science/@nf_core)[![Watch on YouTube](http://img.shields.io/badge/youtube-nf--core-FF0000?labelColor=000000&logo=youtube)](https://www.youtube.com/c/nf-core)\n\n## Introduction\n\n**nfcore/mhcquant** is a best-practice bioinformatics pipeline to process data-dependent acquisition (DDA) immunopeptidomics data. This involves mass spectrometry-based identification and quantification of immunopeptides presented on major histocompatibility complex (MHC) molecules which mediate T cell immunosurveillance. Immunopeptidomics has central implications for clinical research, in the context of [T cell-centric immunotherapies](https://www.sciencedirect.com/science/article/pii/S1044532323000180).\n\nThe pipeline is based on the OpenMS C++ framework for computational mass spectrometry. Spectrum files (mzML/Thermo raw/Bruker tdf) serve as inputs and a database search (Comet) is performed based on a given input protein database. Peptide properties are predicted by MS\u00b2Rescore. FDR rescoring is applied using Percolator or Mokapot based on a competitive target-decoy approach. The pipeline supports both local FDR control (per sample-condition group) and global FDR control (across all samples). For label-free quantification, all input files undergo identification-based retention time alignment and targeted feature extraction matching ids between runs. The pipeline can also generate spectrum libraries suitable for DIA-based searches as well as computing consensus epitopes using epicore.\n\n![overview](assets/mhcquant_subway.png)\n\nThe pipeline is built using [Nextflow](https://www.nextflow.io), a workflow tool to run tasks across multiple compute infrastructures in a very portable manner. It uses Docker/Singularity containers making installation trivial and results highly reproducible. The [Nextflow DSL2](https://www.nextflow.io/docs/latest/dsl2.html) implementation of this pipeline uses one container per process which makes it much easier to maintain and update software dependencies. Where possible, these processes have been submitted to and installed from [nf-core/modules](https://github.com/nf-core/modules) in order to make them available to all nf-core pipelines, and to everyone within the Nextflow community!\n\nOn release, automated continuous integration tests run the pipeline on a full-sized dataset on the AWS cloud infrastructure. This ensures that the pipeline runs on AWS, has sensible resource allocation defaults set to run on real-world datasets, and permits the persistent storage of results to benchmark between pipeline releases and other analysis sources. The results obtained from the full-sized test can be viewed on the [nf-core website](https://nf-co.re/mhcquant/results).\n\n## Usage\n\n> [!NOTE]\n> If you are new to Nextflow and nf-core, please refer to [this page](https://nf-co.re/docs/usage/installation) on how\n> to set-up Nextflow. Make sure to [test your setup](https://nf-co.re/docs/usage/introduction#how-to-run-a-pipeline)\n> with `-profile test` before running the workflow on actual data.\n\nFirst, prepare a samplesheet with your input data that looks as follows:\n\n`samplesheet.tsv`\n\n```tsv title=\"samplesheet.tsv\nID\tSample\tCondition\tReplicateFileName\n1\ttumor\ttreated\t/path/to/msrun1.raw|mzML|d\n2\ttumor\ttreated\t/path/to/msrun2.raw|mzML|d\n3\ttumor\tuntreated\t/path/to/msrun3.raw|mzML|d\n4\ttumor\tuntreated\t/path/to/msrun4.raw|mzML|d\n```\n\nEach row represents a mass spectrometry run in one of the formats: raw, RAW, mzML, mzML.gz, d, d.tar.gz, d.zip\n\nNow, you can run the pipeline using:\n\n```bash\nnextflow run nf-core/mhcquant \\\n -profile \\\n --input 'samplesheet.tsv' \\\n --fasta 'SWISSPROT_2020.fasta' \\\n --outdir ./results\n```\n\nOptional parameters for additional functionality:\n\n```bash\n# Enable quantification, global FDR and spectrum library generation, ion annotations, and consenus epitopes\nnextflow run nf-core/mhcquant \\\n --input 'samplesheet.tsv' \\\n --fasta 'SWISSPROT_2020.fasta' \\\n --annotate_ions \\\n --epicore \\\n --generate_speclib \\\n --global_fdr \\\n --quantify \\\n --outdir ./results \\\n -profile docker\n```\n\n> [!WARNING]\n> Please provide pipeline parameters via the CLI or Nextflow `-params-file` option. Custom config files including those provided by the `-c` Nextflow option can be used to provide any configuration _**except for parameters**_; see [docs](https://nf-co.re/docs/usage/getting_started/configuration#custom-configuration-files).\n\nFor more details and further functionality, please refer to the [usage documentation](https://nf-co.re/mhcquant/usage) and the [parameter documentation](https://nf-co.re/mhcquant/parameters).\n\n## Pipeline summary\n\n### Default Steps\n\nBy default the pipeline currently performs identification of MHC class I peptides with HCD settings:\n\n- **Spectra Preparation**: Preparing spectra dependent on the input format (`PREPARE_SPECTRA` subworkflow)\n- **Database Preparation**: Creation of reversed decoy database (`DecoyDatabase`)\n- **Peptide Identification**: Identification of peptides in the MS/MS spectra (`CometAdapter`)\n- **Database Indexing**: Refreshes protein references for all peptide hits and adds target/decoy information (`PeptideIndexer`)\n- **Identification Merging**: Merges identification files with the same `Sample` and `Condition` label (`IDMerger`)\n- **Rescoring**: Feature prediction and peptide-spectrum-match rescoring (`RESCORE` subworkflow)\n - Prediction of retention times and MS2 intensities (`MS\u00b2Rescore`)\n - Extract PSM features for rescoring engines (`PSMFeatureExtractor`)\n - Peptide-spectrum-match rescoring using Percolator or Mokapot (`PercolatorAdapter`)\n - Filters peptide identification result according to configurable FDR threshold (`IDFilter`)\n- **Export**: Converts identification result to tab-separated files (`TextExporter`)\n\n### FDR Control Modes\n\nThe pipeline supports two FDR control strategies:\n\n- **Local FDR** (default): FDR control applied per `Sample` and `Condition` group\n- **Global FDR**: FDR control applied across all samples in the dataset (enable with `--global_fdr`)\n\n### Additional Steps\n\nAdditional functionality contained by the pipeline currently includes:\n\n#### Quantification (`QUANT` subworkflow)\n\nWhen enabled with `--quantify`, the pipeline performs label-free quantification:\n\n- **Alignment**: Corrects retention time distortions between runs (`MAP_ALIGNMENT` subworkflow)\n - Corrects retention time distortions between runs (`MapAlignerIdentification`)\n - Applies retention time transformations to runs (`MapRTTransformer`)\n- **Feature Processing**: Detects and processes features (`PROCESS_FEATURE` subworkflow)\n - Detects features in MS1 data based on peptide identifications (`FeatureFinderIdentification`)\n - Group corresponding features across label-free experiments (`FeatureLinkerUnlabeledKD`)\n - Resolves ambiguous annotations of features with peptide identifications (`IDConflictResolver`)\n\n#### Spectrum Library Generation (`SPECLIB` subworkflow)\n\nWhen enabled with `--generate_speclib`, the pipeline generates spectrum libraries suitable for DIA-based searches. Outputs one library per sample or a single library across all samples (if global FDR mode is enabled with `--global_fdr`).\n\n#### Ion Annotation (`IONANNOTATOR` subworkflow)\n\nThe pipeline annotates the final list of peptides with their respective ions and charges:\n\n- Annotates final list of peptides with their respective ions and charges (`IonAnnotator`)\n\n#### Output\n\n## Documentation\n\nTo see the the results of a test run with a full size dataset refer to the [results](https://nf-co.re/mhcquant/results) tab on the nf-core website pipeline page.\nFor more details about the output files and reports, please refer to the\n[output documentation](https://nf-co.re/mhcquant/output).\n\n1. [Nextflow installation](https://nf-co.re/usage/installation)\n2. Pipeline configuration\n - [Pipeline installation](https://nf-co.re/docs/usage/getting_started/offline)\n - [Adding your own system config](https://nf-co.re/usage/adding_own_config)\n3. [Running the pipeline](https://nf-co.re/mhcquant/docs/usage.md)\n - This includes tutorials, FAQs, and troubleshooting instructions\n4. [Output and how to interpret the results](https://nf-co.re/mhcquant/docs/output.md)\n\n## Credits\n\nnf-core/mhcquant was originally written by [Leon Bichmann](https://github.com/Leon-Bichmann) from the [Kohlbacher Lab](https://kohlbacherlab.org/). The pipeline was re-written in Nextflow DSL2 by [Marissa Dubbelaar](https://github.com/marissaDubbelaar) and was significantly improved by [Jonas Scheid](https://github.com/jonasscheid) and [Steffen Lemke](https://github.com/steffenlem) from [Peptide-based Immunotherapy](https://www.medizin.uni-tuebingen.de/en-de/peptid-basierte-immuntherapie) and [Quantitative Biology Center](https://uni-tuebingen.de/forschung/forschungsinfrastruktur/zentrum-fuer-quantitative-biologie-qbic/) in T\u00fcbingen.\n\nHelpful contributors:\n\n- [Lukas Heumos](https://github.com/Zethson)\n- [Alexander Peltzer](https://github.com/apeltzer)\n- [Maxime Garcia](https://github.com/maxulysse)\n- [Gisela Gabernet](https://github.com/ggabernet)\n- [Susanne Jodoin](https://github.com/SusiJo)\n- [Oskar Wacker](https://github.com/WackerO)\n- [Leon Kuchenbecker](https://github.com/lkuchenb)\n- [Phil Ewels](https://github.com/ewels)\n- [Christian Fufezan](https://github.com/fu)\n- [Sven Fillinger](https://github.com/sven1103)\n- [Kevin Menden](https://github.com/KevinMenden)\n- [Julia Graf](https://github.com/JuliaGraf)\n- [Jana Hoffmann](https://github.com/janaHoffmann1)\n\n## Contributions and Support\n\nIf you would like to contribute to this pipeline, please see the [contributing guidelines](.github/CONTRIBUTING.md).\n\nFor further information or help, don't hesitate to get in touch on the [Slack `#mhcquant` channel](https://nfcore.slack.com/channels/mhcquant) (you can join with [this invite](https://nf-co.re/join/slack)).\n\n## Citations\n\nIf you use nf-core/mhcquant for your analysis, please cite the corresponding manuscript: [10.1186/s13059-025-03763-8](https://doi.org/10.1186/s13059-025-03763-8)\n\n> **MHCquant2 refines immunopeptidomics tumor antigen discovery**\n>\n> Jonas Scheid, Steffen Lemke, Naomi Hoenisch-Gravel, Anna Dengler, Timo Sachsenberg, Arthur Declerq, Ralf Gabriels, Jens Bauer, Marcel Wacker, Leon Bichmann, Lennart Martens, Marissa L. Dubbelaar, Sven Nahnsen & Juliane S. Walz\n>\n> _Genome Biology_ 2025 26 (1), 290. doi: [10.1021/acs.jproteome.9b00313](https://pubs.acs.org/doi/10.1021/acs.jproteome.9b00313)\n\n> **MHCquant: Automated and Reproducible Data Analysis for Immunopeptidomics**\n>\n> Leon Bichmann, Annika Nelde, Michael Ghosh, Lukas Heumos, Christopher Mohr, Alexander Peltzer, Leon Kuchenbecker, Timo Sachsenberg, Juliane S. Walz, Stefan Stevanovi\u0107, Hans-Georg Rammensee & Oliver Kohlbacher\n>\n> _Journal of Proteome Research_ 2019 18 (11), 3876-3884. doi: [10.1021/acs.jproteome.9b00313](https://pubs.acs.org/doi/10.1021/acs.jproteome.9b00313)\n\nAn extensive list of references for the tools used by the pipeline can be found in the [`CITATIONS.md`](CITATIONS.md) file.\n\nYou can cite the `nf-core` publication as follows:\n\n> **The nf-core framework for community-curated bioinformatics pipelines.**\n>\n> Philip Ewels, Alexander Peltzer, Sven Fillinger, Harshil Patel, Johannes Alneberg, Andreas Wilm, Maxime Ulysse Garcia, Paolo Di Tommaso & Sven Nahnsen.\n>\n> _Nat Biotechnol._ 2020 Feb 13. doi: [10.1038/s41587-020-0439-x](https://dx.doi.org/10.1038/s41587-020-0439-x).\n\nIn addition, references of tools and data used in this pipeline are as follows:\n\n> **OpenMS framework**\n>\n> Pfeuffer J. et al, _Nat Methods_ 2024 Mar;21(3):365-367. doi: [0.1038/s41592-024-02197-7](https://www.nature.com/articles/s41592-024-02197-7).\n>\n> **Comet Search Engine**\n>\n> Eng J.K. et al, _J Am Soc Mass Spectrom._ 2015 Nov;26(11):1865-74. doi: [10.1007/s13361-015-1179-x](https://pubs.acs.org/doi/10.1007/s13361-015-1179-x).\n>\n> **Retention time prediction**\n>\n> Bouwmeester R. et al, _Nature Methods_ 2021 Oct;18(11):1363-1369. doi: [10.1038/s41592-021-01301-5](https://www.nature.com/articles/s41592-021-01301-5)\n>\n> **MS\u00b2 Peak intensity prediction**\n>\n> Declercq A. et al, _Nucleic Acids Res._ 2023 Jul 5;51(W1):W338-W342. doi: [10.1093/nar/gkad335](https://academic.oup.com/nar/article/51/W1/W338/7151340?login=false)\n>\n> **CCS prediction**\n>\n> Declercq A. et al _Journal of Proteome Research_ 2025 Feb 6. doi: [10.1021/acs.jproteome.4c00609](https://pubs.acs.org/doi/10.1021/acs.jproteome.4c00609)\n>\n> **MS\u00b2Rescore framework**\n>\n> Buur L. M. et al, \\_J Proteome Res. 2024 Mar 16. doi: [10.1021/acs.jproteome.3c00785](https://pubs.acs.org/doi/10.1021/acs.jproteome.3c00785)\n>\n> **Percolator**\n>\n> K\u00e4ll L. et al, _Nat Methods_ 2007 Nov;4(11):923-5. doi: [10.1038/nmeth1113](https://www.nature.com/articles/nmeth1113).\n>\n> **Identification based RT Alignment**\n>\n> Weisser H. et al, _J Proteome Res._ 2013 Apr 5;12(4):1628-44. doi: [10.1021/pr300992u](https://pubs.acs.org/doi/10.1021/pr300992u)\n>\n> **Targeted peptide quantification**\n>\n> Weisser H. et al, _J Proteome Res._ 2017 Aug 4;16(8):2964-2974. doi: [10.1021/acs.jproteome.7b00248](https://pubs.acs.org/doi/10.1021/acs.jproteome.7b00248)\n", "hasPart": [ { "@id": "main.nf" @@ -31,6 +31,9 @@ { "@id": "assets/" }, + { + "@id": "bin/" + }, { "@id": "conf/" }, @@ -43,6 +46,9 @@ { "@id": "modules/" }, + { + "@id": "modules/local/" + }, { "@id": "modules/nf-core/" }, @@ -99,7 +105,7 @@ }, "mentions": [ { - "@id": "#b0929725-e98e-4b1f-9c40-c9c718ec6c28" + "@id": "#3dbe415b-3d82-41eb-a11f-065f425f8a83" } ], "name": "nf-core/mhcquant" @@ -121,20 +127,30 @@ }, { "@id": "main.nf", - "@type": ["File", "SoftwareSourceCode", "ComputationalWorkflow"], + "@type": [ + "File", + "SoftwareSourceCode", + "ComputationalWorkflow" + ], "creator": [ + { + "@id": "https://orcid.org/0000-0002-4930-1467" + }, { "@id": "https://orcid.org/0000-0001-7135-0073" }, + { + "@id": "https://orcid.org/0000-0002-6503-2180" + }, { "@id": "https://orcid.org/0000-0002-8937-3457" }, { - "@id": "https://orcid.org/0000-0002-6503-2180" + "@id": "https://orcid.org/0000-0002-5923-1343" } ], "dateCreated": "", - "dateModified": "2025-04-30T12:27:00Z", + "dateModified": "2025-10-20T07:45:13Z", "dct:conformsTo": "https://bioschemas.org/profiles/ComputationalWorkflow/1.0-RELEASE/", "keywords": [ "nf-core", @@ -146,13 +162,23 @@ "openms", "peptides" ], - "license": ["MIT"], + "license": [ + "MIT" + ], "maintainer": [ + { + "@id": "https://orcid.org/0000-0002-4930-1467" + }, { "@id": "https://orcid.org/0000-0001-7135-0073" + }, + { + "@id": "https://orcid.org/0000-0002-5923-1343" } ], - "name": ["nf-core/mhcquant"], + "name": [ + "nf-core/mhcquant" + ], "programmingLanguage": { "@id": "https://w3id.org/workflowhub/workflow-ro-crate#nextflow" }, @@ -161,10 +187,10 @@ }, "url": [ "https://github.com/nf-core/mhcquant", - "https://nf-co.re/mhcquant/dev/" + "https://nf-co.re/mhcquant/3.1.0/" ], "version": [ - "2.7.0dev" + "3.1.0" ] }, { @@ -177,14 +203,14 @@ "url": { "@id": "https://www.nextflow.io/" }, - "version": "!>=24.04.2" + "version": "!>=25.04.0" }, { - "@id": "#b0929725-e98e-4b1f-9c40-c9c718ec6c28", + "@id": "#3dbe415b-3d82-41eb-a11f-065f425f8a83", "@type": "TestSuite", "instance": [ { - "@id": "#12fe45d1-692e-4a34-ade5-2a83d545d02f" + "@id": "#cd4e5431-8228-4f6a-a3c6-4b722e22ba0a" } ], "mainEntity": { @@ -193,10 +219,10 @@ "name": "Test suite for nf-core/mhcquant" }, { - "@id": "#12fe45d1-692e-4a34-ade5-2a83d545d02f", + "@id": "#cd4e5431-8228-4f6a-a3c6-4b722e22ba0a", "@type": "TestInstance", "name": "GitHub Actions workflow for testing nf-core/mhcquant", - "resource": "repos/nf-core/mhcquant/actions/workflows/ci.yml", + "resource": "repos/nf-core/mhcquant/actions/workflows/nf-test.yml", "runsOn": { "@id": "https://w3id.org/ro/terms/test#GithubService" }, @@ -215,6 +241,11 @@ "@type": "Dataset", "description": "Additional files" }, + { + "@id": "bin/", + "@type": "Dataset", + "description": "Scripts that must be callable from a pipeline process" + }, { "@id": "conf/", "@type": "Dataset", @@ -235,6 +266,11 @@ "@type": "Dataset", "description": "Modules used by the pipeline" }, + { + "@id": "modules/local/", + "@type": "Dataset", + "description": "Pipeline-specific modules" + }, { "@id": "modules/nf-core/", "@type": "Dataset", @@ -321,12 +357,24 @@ "name": "nf-core", "url": "https://nf-co.re/" }, + { + "@id": "https://orcid.org/0000-0002-4930-1467", + "@type": "Person", + "email": "marissa.dubbelaar@gmail.com", + "name": "Marissa Dubbelaar" + }, { "@id": "https://orcid.org/0000-0001-7135-0073", "@type": "Person", "email": "bichmann@informatik.uni-tuebingen.de", "name": "Leon Bichmann" }, + { + "@id": "https://orcid.org/0000-0002-6503-2180", + "@type": "Person", + "email": "apeltzer@users.noreply.github.com", + "name": "Alexander Peltzer" + }, { "@id": "https://orcid.org/0000-0002-8937-3457", "@type": "Person", @@ -334,10 +382,10 @@ "name": "Lukas Heumos" }, { - "@id": "https://orcid.org/0000-0002-6503-2180", + "@id": "https://orcid.org/0000-0002-5923-1343", "@type": "Person", - "email": "apeltzer@users.noreply.github.com", - "name": "Alexander Peltzer" + "email": "43858870+jonasscheid@users.noreply.github.com", + "name": "Jonas Scheid" } ] -} +} \ No newline at end of file diff --git a/subworkflows/local/prepare_spectra/main.nf b/subworkflows/local/prepare_spectra/main.nf index 8538636c..6c199bf6 100644 --- a/subworkflows/local/prepare_spectra/main.nf +++ b/subworkflows/local/prepare_spectra/main.nf @@ -20,7 +20,7 @@ workflow PREPARE_SPECTRA { .branch { meta, filename -> raw : meta.ext == 'raw' - return [ meta, filename ] + return [ meta.subMap('id', 'sample', 'condition', 'group_count', 'spectra'), filename ] mzml : meta.ext == 'mzml' return [ meta.subMap('id', 'sample', 'condition', 'group_count', 'spectra'), filename ] mzml_gz : meta.ext == 'mzml.gz' diff --git a/subworkflows/local/rescore/main.nf b/subworkflows/local/rescore/main.nf index 78da376e..564a6b0c 100644 --- a/subworkflows/local/rescore/main.nf +++ b/subworkflows/local/rescore/main.nf @@ -73,7 +73,7 @@ workflow RESCORE { OPENMS_IDFILTER_GLOBAL(ch_pout.combine(OPENMS_IDFILTER_Q_VALUE_GLOBAL.out.filtered.map{ it[1] })) ch_filter_q_value = OPENMS_IDFILTER_GLOBAL.out.filtered // Save globally merged runs in tsv - OPENMS_TEXTEXPORTER_GLOBAL(OPENMS_PERCOLATORADAPTER_GLOBAL.out.idxml) + OPENMS_TEXTEXPORTER_GLOBAL(OPENMS_IDFILTER_Q_VALUE_GLOBAL.out.filtered) } else { ch_rescored_runs = ch_pout diff --git a/subworkflows/local/utils_nfcore_mhcquant_pipeline/main.nf b/subworkflows/local/utils_nfcore_mhcquant_pipeline/main.nf index 22d001c6..de3353fc 100644 --- a/subworkflows/local/utils_nfcore_mhcquant_pipeline/main.nf +++ b/subworkflows/local/utils_nfcore_mhcquant_pipeline/main.nf @@ -11,6 +11,7 @@ include { UTILS_NFSCHEMA_PLUGIN } from '../../nf-core/utils_nfschema_plugin' include { paramsSummaryMap } from 'plugin/nf-schema' include { samplesheetToList } from 'plugin/nf-schema' +include { paramsHelp } from 'plugin/nf-schema' include { completionEmail } from '../../nf-core/utils_nfcore_pipeline' include { completionSummary } from '../../nf-core/utils_nfcore_pipeline' include { imNotification } from '../../nf-core/utils_nfcore_pipeline' @@ -32,6 +33,9 @@ workflow PIPELINE_INITIALISATION { nextflow_cli_args // array: List of positional nextflow CLI args outdir // string: The output directory where the results will be saved input // string: Path to input samplesheet + help // boolean: Display help message and exit + help_full // boolean: Show the full help message + show_hidden // boolean: Show hidden parameters in the help message main: @@ -50,10 +54,35 @@ workflow PIPELINE_INITIALISATION { // // Validate parameters and generate parameter summary to stdout // + before_text = """ +-\033[2m----------------------------------------------------\033[0m- + \033[0;32m,--.\033[0;30m/\033[0;32m,-.\033[0m +\033[0;34m ___ __ __ __ ___ \033[0;32m/,-._.--~\'\033[0m +\033[0;34m |\\ | |__ __ / ` / \\ |__) |__ \033[0;33m} {\033[0m +\033[0;34m | \\| | \\__, \\__/ | \\ |___ \033[0;32m\\`-._,-`-,\033[0m + \033[0;32m`._,._,\'\033[0m +\033[0;35m nf-core/mhcquant ${workflow.manifest.version}\033[0m +-\033[2m----------------------------------------------------\033[0m- +""" + after_text = """${workflow.manifest.doi ? "\n* The pipeline\n" : ""}${workflow.manifest.doi.tokenize(",").collect { " https://doi.org/${it.trim().replace('https://doi.org/','')}"}.join("\n")}${workflow.manifest.doi ? "\n" : ""} +* The nf-core framework + https://doi.org/10.1038/s41587-020-0439-x + +* Software dependencies + https://github.com/nf-core/mhcquant/blob/master/CITATIONS.md +""" + command = "nextflow run ${workflow.manifest.name} -profile --input samplesheet.csv --outdir " + UTILS_NFSCHEMA_PLUGIN ( workflow, validate_params, - null + null, + help, + help_full, + show_hidden, + before_text, + after_text, + command ) // @@ -69,21 +98,58 @@ workflow PIPELINE_INITIALISATION { Channel .fromList(samplesheetToList(params.input, "${projectDir}/assets/schema_input.json")) - .map { meta, file -> [meta.subMap('sample','condition'), meta, file] } + .map { meta, file, fasta -> [meta.subMap('sample','condition'), meta, file, fasta] } .tap { ch_input } .groupTuple() // get number of files per sample-condition - .map { group_meta, metas, files -> [ group_meta, files.size()] } + .map { group_meta, metas, files, fastas -> [ group_meta, files.size()] } .combine( ch_input, by:0 ) - .map { group_meta, group_count, meta, file -> [meta + ['group_count':group_count, 'spectra':file.baseName.tokenize('.')[0], 'ext':getCustomExtension(file)], file] } - .set { ch_samplesheet } + .map { group_meta, group_count, meta, file, fasta -> [meta + ['group_count':group_count, 'spectra':file.baseName.tokenize('.')[0], 'ext':getCustomExtension(file)], file, fasta] } + .set { ch_samplesheet_raw } + + ch_samplesheet = ch_samplesheet_raw.map { meta, file, fasta -> [ meta, file ]} // - // Create channel from the mandatory reference_database through params.fasta + // Create channel from the reference_database through params.fasta or from the samplesheet fasta files // - Channel.fromPath(params.fasta, checkIfExists: true) - .map { fasta -> [[id:fasta.getBaseName()], fasta] } - .set { ch_fasta } + + if (params.fasta) { + Channel.fromPath(params.fasta, checkIfExists: true) + .map { fasta -> [[id:fasta.getBaseName()], fasta] } + .set { ch_fasta } + + ch_samplesheet_raw + .map{ meta, file, fasta -> fasta } + .flatten() + .first() + .subscribe { + log.warn """\ + Both --fasta and samplesheet FASTA files were provided! + The pipeline will use --fasta (${params.fasta}), ignoring samplesheet FASTA entries. + To use the samplesheet FASTA files instead, remove the --fasta parameter. + """.stripIndent() + } + + } else { + // Check if the FASTA files were provided in the samplesheet + ch_fasta = ch_samplesheet_raw.map { meta, file, fasta -> [ groupKey([id: "${meta.sample}_${meta.condition}"], meta.group_count), fasta] } + ch_fasta + .map { meta, fasta -> fasta } + .flatten() + .ifEmpty { + error '''\ + Error: No FASTA files provided. + Please either: + 1. Use --fasta parameter, or + 2. Include a 'Fasta' column in your samplesheet + '''.stripIndent() + } + // Group FASTA files by sample and condition and keep only the first FASTA file per sample-condition + ch_fasta + .groupTuple() + .map { group_meta, fastas -> [group_meta, fastas.first()] } + .set { ch_fasta } + } emit: samplesheet = ch_samplesheet @@ -236,4 +302,3 @@ def methodsDescriptionText(mqc_methods_yaml) { return description_html.toString() } - diff --git a/subworkflows/nf-core/utils_nextflow_pipeline/tests/tags.yml b/subworkflows/nf-core/utils_nextflow_pipeline/tests/tags.yml deleted file mode 100644 index f8476112..00000000 --- a/subworkflows/nf-core/utils_nextflow_pipeline/tests/tags.yml +++ /dev/null @@ -1,2 +0,0 @@ -subworkflows/utils_nextflow_pipeline: - - subworkflows/nf-core/utils_nextflow_pipeline/** diff --git a/subworkflows/nf-core/utils_nfcore_pipeline/tests/tags.yml b/subworkflows/nf-core/utils_nfcore_pipeline/tests/tags.yml deleted file mode 100644 index ac8523c9..00000000 --- a/subworkflows/nf-core/utils_nfcore_pipeline/tests/tags.yml +++ /dev/null @@ -1,2 +0,0 @@ -subworkflows/utils_nfcore_pipeline: - - subworkflows/nf-core/utils_nfcore_pipeline/** diff --git a/subworkflows/nf-core/utils_nfschema_plugin/main.nf b/subworkflows/nf-core/utils_nfschema_plugin/main.nf index 4994303e..ee4738c8 100644 --- a/subworkflows/nf-core/utils_nfschema_plugin/main.nf +++ b/subworkflows/nf-core/utils_nfschema_plugin/main.nf @@ -4,6 +4,7 @@ include { paramsSummaryLog } from 'plugin/nf-schema' include { validateParameters } from 'plugin/nf-schema' +include { paramsHelp } from 'plugin/nf-schema' workflow UTILS_NFSCHEMA_PLUGIN { @@ -15,29 +16,56 @@ workflow UTILS_NFSCHEMA_PLUGIN { // when this input is empty it will automatically use the configured schema or // "${projectDir}/nextflow_schema.json" as default. This input should not be empty // for meta pipelines + help // boolean: show help message + help_full // boolean: show full help message + show_hidden // boolean: show hidden parameters in help message + before_text // string: text to show before the help message and parameters summary + after_text // string: text to show after the help message and parameters summary + command // string: an example command of the pipeline main: + if(help || help_full) { + help_options = [ + beforeText: before_text, + afterText: after_text, + command: command, + showHidden: show_hidden, + fullHelp: help_full, + ] + if(parameters_schema) { + help_options << [parametersSchema: parameters_schema] + } + log.info paramsHelp( + help_options, + params.help instanceof String ? params.help : "", + ) + exit 0 + } + // // Print parameter summary to stdout. This will display the parameters // that differ from the default given in the JSON schema // + + summary_options = [:] if(parameters_schema) { - log.info paramsSummaryLog(input_workflow, parameters_schema:parameters_schema) - } else { - log.info paramsSummaryLog(input_workflow) + summary_options << [parametersSchema: parameters_schema] } + log.info before_text + log.info paramsSummaryLog(summary_options, input_workflow) + log.info after_text // // Validate the parameters using nextflow_schema.json or the schema // given via the validation.parametersSchema configuration option // if(validate_params) { + validateOptions = [:] if(parameters_schema) { - validateParameters(parameters_schema:parameters_schema) - } else { - validateParameters() + validateOptions << [parametersSchema: parameters_schema] } + validateParameters(validateOptions) } emit: diff --git a/subworkflows/nf-core/utils_nfschema_plugin/tests/main.nf.test b/subworkflows/nf-core/utils_nfschema_plugin/tests/main.nf.test index 8fb30164..c977917a 100644 --- a/subworkflows/nf-core/utils_nfschema_plugin/tests/main.nf.test +++ b/subworkflows/nf-core/utils_nfschema_plugin/tests/main.nf.test @@ -25,6 +25,12 @@ nextflow_workflow { input[0] = workflow input[1] = validate_params input[2] = "" + input[3] = false + input[4] = false + input[5] = false + input[6] = "" + input[7] = "" + input[8] = "" """ } } @@ -51,6 +57,12 @@ nextflow_workflow { input[0] = workflow input[1] = validate_params input[2] = "" + input[3] = false + input[4] = false + input[5] = false + input[6] = "" + input[7] = "" + input[8] = "" """ } } @@ -77,6 +89,12 @@ nextflow_workflow { input[0] = workflow input[1] = validate_params input[2] = "${projectDir}/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow_schema.json" + input[3] = false + input[4] = false + input[5] = false + input[6] = "" + input[7] = "" + input[8] = "" """ } } @@ -103,6 +121,12 @@ nextflow_workflow { input[0] = workflow input[1] = validate_params input[2] = "${projectDir}/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow_schema.json" + input[3] = false + input[4] = false + input[5] = false + input[6] = "" + input[7] = "" + input[8] = "" """ } } @@ -114,4 +138,36 @@ nextflow_workflow { ) } } + + test("Should create a help message") { + + when { + + params { + test_data = '' + outdir = null + } + + workflow { + """ + validate_params = true + input[0] = workflow + input[1] = validate_params + input[2] = "${projectDir}/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow_schema.json" + input[3] = true + input[4] = false + input[5] = false + input[6] = "Before" + input[7] = "After" + input[8] = "nextflow run test/test" + """ + } + } + + then { + assertAll( + { assert workflow.success } + ) + } + } } diff --git a/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow.config b/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow.config index 0907ac58..8d8c7371 100644 --- a/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow.config +++ b/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow.config @@ -1,8 +1,8 @@ plugins { - id "nf-schema@2.1.0" + id "nf-schema@2.5.1" } validation { parametersSchema = "${projectDir}/subworkflows/nf-core/utils_nfschema_plugin/tests/nextflow_schema.json" monochromeLogs = true -} \ No newline at end of file +} diff --git a/tests/.nftignore b/tests/.nftignore new file mode 100644 index 00000000..53b36346 --- /dev/null +++ b/tests/.nftignore @@ -0,0 +1,15 @@ +.DS_Store +multiqc/multiqc_data/fastqc_top_overrepresented_sequences_table.txt +multiqc/multiqc_data/multiqc.parquet +multiqc/multiqc_data/multiqc.log +multiqc/multiqc_data/multiqc_data.json +multiqc/multiqc_data/*.txt +multiqc/multiqc_plots/{svg,pdf,png}/*.{svg,pdf,png} +multiqc/multiqc_report.html +pipeline_info/*.{html,json,txt,yml} +intermediate_results/comet/* +intermediate_results/rescoring/* +intermediate_results/ion_annotations/* +global_fdr/global.tsv +spectrum_library/*_speclib.tsv +*.tsv diff --git a/tests/default.nf.test b/tests/default.nf.test new file mode 100644 index 00000000..20075d55 --- /dev/null +++ b/tests/default.nf.test @@ -0,0 +1,53 @@ +nextflow_pipeline { + + name "Test pipeline" + script "../main.nf" + tag "pipeline" + + test("-profile test") { + + when { + params { + outdir = "$outputDir" + } + } + + then { + // stable_name: All files + folders in ${params.outdir}/ with a stable name + def stable_name = getAllFilesFromDir(params.outdir, relative: true, includeDir: true, ignore: ['pipeline_info/*.{html,json,txt}']) + // stable_path: All files in ${params.outdir}/ with stable content + def stable_path = getAllFilesFromDir(params.outdir, ignoreFile: 'tests/.nftignore') + // Extract peptidoform column from all TSV files + def peptidoform_data = [] + new File(params.outdir).eachFileRecurse { file -> + if (file.name.endsWith('.tsv')) { + def lines = file.readLines() + if (lines.size() > 0) { + def header = lines[0].split('\t') + def peptidoformIndex = header.findIndexOf { it == 'peptidoform' } + if (peptidoformIndex >= 0) { + def peptidoforms = lines.drop(1).collect { line -> + def fields = line.split('\t') + fields.size() > peptidoformIndex ? fields[peptidoformIndex] : '' + }.findAll { it != '' }.sort() + peptidoform_data.add([file.name, peptidoforms]) + } + } + } + } + assertAll( + { assert workflow.success}, + { assert snapshot( + // pipeline versions.yml file for multiqc from which Nextflow version is removed because we test pipelines on multiple Nextflow versions + removeNextflowVersion("$outputDir/pipeline_info/nf_core_mhcquant_software_mqc_versions.yml"), + // All stable path name, with a relative path + stable_name, + // All files with stable contents + stable_path, + // Peptidoform data from TSV files + peptidoform_data + ).match() } + ) + } + } +} diff --git a/tests/default.nf.test.snap b/tests/default.nf.test.snap new file mode 100644 index 00000000..85ba67fb --- /dev/null +++ b/tests/default.nf.test.snap @@ -0,0 +1,389 @@ +{ + "-profile test": { + "content": [ + { + "MS2RESCORE": { + "MS\u00b2Rescore": "3.1.5)" + }, + "OPENMSTHIRDPARTY_COMETADAPTER": { + "CometAdapter": "3.4.1", + "Comet": "2024.01 rev. 1" + }, + "OPENMS_DECOYDATABASE": { + "openms": "3.4.1" + }, + "OPENMS_IDFILTER_Q_VALUE": { + "openms": "3.4.1" + }, + "OPENMS_IDMASSACCURACY": { + "OpenMS": "3.4.1" + }, + "OPENMS_IDMERGER": { + "openms": "3.4.1" + }, + "OPENMS_PEPTIDEINDEXER": { + "openms": "3.4.1" + }, + "OPENMS_PERCOLATORADAPTER": { + "PercolatorAdapter": "3.4.1-pre-exported-20250822", + "percolator": "3.07.1, Build Date Mar 13 2025 17:19:27" + }, + "OPENMS_PSMFEATUREEXTRACTOR": { + "openms": "3.4.1" + }, + "OPENMS_TEXTEXPORTER": { + "openms": "3.4.1" + }, + "PYOPENMS_CHROMATOGRAMEXTRACTOR": { + "pyopenms": "3.4.1" + }, + "SUMMARIZE_RESULTS": { + "pyopenms": "3.4.1" + }, + "Workflow": { + "nf-core/mhcquant": "v3.1.0" + } + }, + [ + "HepG2_A.tsv", + "intermediate_results", + "intermediate_results/comet", + "intermediate_results/comet/HepG2_rep1_small_pin.tsv", + "intermediate_results/comet/HepG2_rep2_small_pin.tsv", + "intermediate_results/comet/HepG2_rep3_small_pin.tsv", + "intermediate_results/rescoring", + "intermediate_results/rescoring/HepG2_A_ms2rescore.idXML", + "intermediate_results/rescoring/HepG2_A_pout.idXML", + "intermediate_results/rescoring/HepG2_A_pout_filtered.idXML", + "intermediate_results/rescoring/HepG2_A_psm.idXML", + "multiqc", + "multiqc/ms2rescore", + "multiqc/multiqc_data", + "multiqc/multiqc_data/llms-full.txt", + "multiqc/multiqc_data/multiqc.log", + "multiqc/multiqc_data/multiqc.parquet", + "multiqc/multiqc_data/multiqc_chromatogram.txt", + "multiqc/multiqc_data/multiqc_citations.txt", + "multiqc/multiqc_data/multiqc_data.json", + "multiqc/multiqc_data/multiqc_general_stats.txt", + "multiqc/multiqc_data/multiqc_histogram_mz.txt", + "multiqc/multiqc_data/multiqc_histogram_rt.txt", + "multiqc/multiqc_data/multiqc_histogram_scores.txt", + "multiqc/multiqc_data/multiqc_length_dist.txt", + "multiqc/multiqc_data/multiqc_mass_error.txt", + "multiqc/multiqc_data/multiqc_percolator_barplot.txt", + "multiqc/multiqc_data/multiqc_scores_xcorr.txt", + "multiqc/multiqc_data/multiqc_software_versions.txt", + "multiqc/multiqc_data/multiqc_sources.txt", + "multiqc/multiqc_data/percolator_plot.txt", + "multiqc/multiqc_plots", + "multiqc/multiqc_plots/pdf", + "multiqc/multiqc_plots/pdf/chromatogram-cnt.pdf", + "multiqc/multiqc_plots/pdf/chromatogram-log.pdf", + "multiqc/multiqc_plots/pdf/general_stats.pdf", + "multiqc/multiqc_plots/pdf/histogram_mz.pdf", + "multiqc/multiqc_plots/pdf/histogram_rt.pdf", + "multiqc/multiqc_plots/pdf/histogram_scores.pdf", + "multiqc/multiqc_plots/pdf/length_dist.pdf", + "multiqc/multiqc_plots/pdf/mass_error.pdf", + "multiqc/multiqc_plots/pdf/percolator_plot-cnt.pdf", + "multiqc/multiqc_plots/pdf/percolator_plot-pct.pdf", + "multiqc/multiqc_plots/pdf/scores_xcorr.pdf", + "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/chromatogram-cnt.png", + "multiqc/multiqc_plots/png/chromatogram-log.png", + "multiqc/multiqc_plots/png/general_stats.png", + "multiqc/multiqc_plots/png/histogram_mz.png", + "multiqc/multiqc_plots/png/histogram_rt.png", + "multiqc/multiqc_plots/png/histogram_scores.png", + "multiqc/multiqc_plots/png/length_dist.png", + "multiqc/multiqc_plots/png/mass_error.png", + "multiqc/multiqc_plots/png/percolator_plot-cnt.png", + "multiqc/multiqc_plots/png/percolator_plot-pct.png", + "multiqc/multiqc_plots/png/scores_xcorr.png", + "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/chromatogram-cnt.svg", + "multiqc/multiqc_plots/svg/chromatogram-log.svg", + "multiqc/multiqc_plots/svg/general_stats.svg", + "multiqc/multiqc_plots/svg/histogram_mz.svg", + "multiqc/multiqc_plots/svg/histogram_rt.svg", + "multiqc/multiqc_plots/svg/histogram_scores.svg", + "multiqc/multiqc_plots/svg/length_dist.svg", + "multiqc/multiqc_plots/svg/mass_error.svg", + "multiqc/multiqc_plots/svg/percolator_plot-cnt.svg", + "multiqc/multiqc_plots/svg/percolator_plot-pct.svg", + "multiqc/multiqc_plots/svg/scores_xcorr.svg", + "multiqc/multiqc_report.html", + "pipeline_info", + "pipeline_info/nf_core_mhcquant_software_mqc_versions.yml" + ], + [ + + ], + [ + [ + "HepG2_A.tsv", + [ + "AAAAAAHRL", + "AAATVTKKV", + "AAHPNVQKV", + "AAKDPSPSV", + "AAM(Oxidation)SVAKRV", + "AANAQPHKL", + "AANDKLKKM", + "AANPDPKKL", + "AAPPPPAHA", + "AAPRPPPKPM(Oxidation)", + "AAQAHTREL", + "AAQSEAKVV", + "AARAEAREI", + "AASPVGKRL", + "AASSLKKQY", + "AATDHSNQL", + "AATPAKKTV", + "AATRWAKKI", + "AATSNLKKL", + "AATVTKKTY", + "AKDVKFGAD", + "ALKDKIEKA", + "ALKDSVQRA", + "ALKENGGARLA", + "ALSDLHAHK", + "AM(Oxidation)AARPHSI", + "AM(Oxidation)AASPHAV", + "AM(Oxidation)ASHLTST", + "AM(Oxidation)HGHVEVV", + "AM(Oxidation)NARPHKV", + "AMNARPHKV", + "APRPPPKPM(Oxidation)", + "ATWSDPHKA", + "AVM(Oxidation)GNPKVKA", + "AVVVKKIETRDG", + "DAAVHQRI", + "DAKKQIKQV", + "DAPAGRKV", + "DGKKKISTV", + "DHVITNM(Oxidation)N", + "DPM(Oxidation)KARVV", + "DPPKTHVT", + "DPPRDSKGL", + "DSKKSQPKI", + "EAKTHEAQI", + "EDRDDNKVY", + "EYSKQM(Oxidation)QRF", + "FADPHSKRV", + "FPHSAHQKY", + "FPSRGKSSSY", + "GKVGAHAGEY", + "GKVGAHAGEYG", + "GLAKSIHHA", + "GMAKKVTKA", + "GNVAEGETKPD", + "GPNKKPRF", + "GRPM(Oxidation)PPSRR", + "GRVVEPKR", + "GVM(Oxidation)VGM(Oxidation)GQKD", + "HAAENPGKY", + "HAANPNGRYY", + "HAATYTKKV", + "HAFGGNKASY", + "HAGPTAHEL", + "HAIGKSQSF", + "HAKEKLTAL", + "HAM(Oxidation)EEVKKF", + "HAPELTKKV", + "HLKEDQTEY", + "HPAENGKSNF", + "HPESERISM(Oxidation)", + "HPNKVKVY", + "HPSQPQGTY", + "HPYQPDPKM(Oxidation)", + "HSRNEGVATY", + "HSSPASSNY", + "HVKDANGNSF", + "HVSTHQHNY", + "IASQTVKKV", + "IKTVETRD", + "ILDKKVEKV", + "IPKKHISQI", + "IPQKFHRSV", + "ISSEAHREV", + "IVGRPRHQ", + "IYTEHAHQV", + "KAAAFEKQV", + "KAAKPKVV", + "KAASHIKSI", + "KAATVTKEL", + "KAISGVHTV", + "KAKPGTYKV", + "KALVKPKEV", + "KASEQAKVV", + "KASGTLREY", + "KAYGKAKSI", + "KAYSEAHEI", + "KHANQVLSL", + "KLAESVEKA", + "KLAPPPKKA", + "KLDNQVSKV", + "KLM(Oxidation)QQQQEV", + "KLQPGSVKKV", + "KLSPKAEEV", + "KM(Oxidation)DESKHEI", + "KM(Oxidation)LDHEYTT", + "KMDESKHEI", + "KMQEHSDQV", + "KSKEFVQKV", + "KTKEGVREV", + "KVAQPKEV", + "KVIDTQQKV", + "KVSNSGITRV", + "KVVNPTQK", + "KYLGKTHNL", + "KYNRQSM(Oxidation)TL", + "KYQPKPKQI", + "KYTPPPHHI", + "LAKTGVHHY", + "LDKKVEKV", + "LLKSEKSSY", + "LPSENHKEM", + "LPSENHKEM(Oxidation)", + "M(Oxidation)LSEHTSKL", + "M(Oxidation)PPEHVRKI", + "M(Oxidation)PQGGGQHY", + "M(Oxidation)PQKERESI", + "M(Oxidation)PRNLREY", + "MPKAEKNAV", + "MPNKVRKI", + "MPPEHVRKI", + "MPQKERESI", + "NAAEGRSF", + "NAHGEPRNY", + "NALAHKYH", + "NAM(Oxidation)KIRDV", + "NASARDNTI", + "NATAVVRHM(Oxidation)", + "NATNAVKRL", + "NGTHVVRHY", + "NIQKITKS", + "NLAEKPKTV", + "NLKVKGPVR", + "NLRPKKKV", + "NLRPKKKVK", + "NLTEEEEKSKS", + "NNLSSLSKK", + "NPAAYENDK", + "NPFGGASHAKG", + "NPKESSSSL", + "NTKIGPRR", + "NVDYSKLKK", + "NVINGGSHA", + "NVKIVKVKKE", + "NYTKEHNNL", + "PKSKELVSSSS", + "PPNKKPKV", + "PVEKALRD", + "QAGPINREM(Oxidation)", + "QALKHLKQY", + "QGVM(Oxidation)VGM(Oxidation)GQK", + "QGVM(Oxidation)VGM(Oxidation)GQKD", + "QPAKADKESF", + "QPHKVTQY", + "QTHQPPAPNS", + "QVKPNSNQV", + "QYKKDGADF", + "RADKKAPR", + "RLAEAHAKV", + "RLHEKIQEA", + "RLNNKSAKV", + "RPKKPGQSF", + "RPVPKGATY", + "RQVTGVTRV", + "RSNEHIREL", + "RSTENVNKL", + "RSTQYM(Oxidation)KEY", + "RVAGIHKKV", + "RYDDM(Oxidation)AAAM(Oxidation)", + "RYIDLHSNR", + "RYIDTHNRV", + "RYM(Oxidation)NHM(Oxidation)QSL", + "SAKLERSHY", + "SAM(Oxidation)SNPRAM", + "SAQTTSHEL", + "SARAGETRF", + "SASEAAKKY", + "SASHVSKTV", + "SATGHPRKV", + "SATNALRSM(Oxidation)", + "SATSNKHLL", + "SAVDRQREY", + "SAYANAKKY", + "SEVAHRFK", + "SIVGRPRH", + "SKEYFSKQ", + "SLDKTSHSV", + "SLDTQPKKV", + "SM(Oxidation)LGSPHKV", + "SM(Oxidation)NTHLKAV", + "SPM(Oxidation)EKIKQY", + "SPNYHEEKY", + "SQRFPKAE", + "SVKNDHSAY", + "SVQVFGRKK", + "SYVGDEAQSKR", + "SYVGDEAQSKRG", + "TALAPSTM(Oxidation)K", + "TAPQTQHV", + "TARPGPRAV", + "TDKSFVEK", + "TDRETGKL", + "TEKLVTSK", + "TEKLVTSKG", + "TGYYGKGKP", + "THQPPAPNS", + "THYDPPRK", + "TIGEGQQHHLG", + "TISRPKGVA", + "TKELPSGKKY", + "TLVQTKGT", + "TNNLRPKKKVK", + "TPPGVRKI", + "TRLSRTPGNR", + "TSGPGSRISSSS", + "TSTPNAKTV", + "TTPISEQKG", + "TTTHITKTV", + "TVIGPDGHKE", + "TVKDSRTVY", + "TVQNEANKY", + "VAPPKAHEV", + "VARAGQKGY", + "VASEGIKRY", + "VHLTPEEK", + "VITDKEKAE", + "VPKEGKVV", + "VQKTIAEN", + "VQNGKHFKF", + "VSKGTLVQTKGT", + "VTTSTRTY", + "VYAQKHQQL", + "VYGKTSHL", + "YADEKTKDV", + "YARLHPRAV", + "YGSTVSKRV", + "YLNKHIQKV", + "YPAKAKGTF", + "YTKKLNTQ", + "YTM(Oxidation)KKVHAL", + "YVGDEAQSKR", + "YVGDEAQSKRG" + ] + ] + ] + ], + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.04.8" + }, + "timestamp": "2025-10-28T21:36:13.560396546" + } +} \ No newline at end of file diff --git a/tests/ionannotator.nf.test b/tests/ionannotator.nf.test new file mode 100644 index 00000000..312bd2c0 --- /dev/null +++ b/tests/ionannotator.nf.test @@ -0,0 +1,57 @@ +nextflow_pipeline { + + name "Test pipeline" + script "../main.nf" + tag "pipeline" + tag "test_ionannotator" + profile "test_ionannotator" + + test("-profile test_ionannotator") { + + when { + params { + outdir = "$outputDir" + } + } + + then { + // stable_name: All files + folders in ${params.outdir}/ with a stable name + def stable_name = getAllFilesFromDir(params.outdir, relative: true, includeDir: true, ignore: ['pipeline_info/*.{html,json,txt}']) + // stable_path: All files in ${params.outdir}/ with stable content + def stable_path = getAllFilesFromDir(params.outdir, ignoreFile: 'tests/.nftignore') + // Extract peptidoform column from all TSV files + def peptidoform_data = [] + new File(params.outdir).eachFileRecurse { file -> + if (file.name.endsWith('.tsv')) { + def lines = file.readLines() + if (lines.size() > 0) { + def header = lines[0].split('\t') + def peptidoformIndex = header.findIndexOf { it == 'peptidoform' } + if (peptidoformIndex >= 0) { + def peptidoforms = lines.drop(1).collect { line -> + def fields = line.split('\t') + fields.size() > peptidoformIndex ? fields[peptidoformIndex] : '' + }.findAll { it != '' }.sort() + peptidoform_data.add([file.name, peptidoforms]) + } + } + } + } + assertAll( + { assert workflow.success}, + { assert snapshot( + // Number of successful tasks + workflow.trace.succeeded().size(), + // pipeline versions.yml file for multiqc from which Nextflow version is removed because we test pipelines on multiple Nextflow versions + removeNextflowVersion("$outputDir/pipeline_info/nf_core_mhcquant_software_mqc_versions.yml"), + // All stable path name, with a relative path + stable_name, + // All files with stable contents + stable_path, + // Peptidoform data from TSV files + peptidoform_data + ).match() } + ) + } + } +} diff --git a/tests/ionannotator.nf.test.snap b/tests/ionannotator.nf.test.snap new file mode 100644 index 00000000..b0fd3915 --- /dev/null +++ b/tests/ionannotator.nf.test.snap @@ -0,0 +1,410 @@ +{ + "-profile test_ionannotator": { + "content": [ + 22, + { + "MS2RESCORE": { + "MS\u00b2Rescore": "3.1.5)" + }, + "OPENMSTHIRDPARTY_COMETADAPTER": { + "CometAdapter": "3.4.1", + "Comet": "2024.01 rev. 1" + }, + "OPENMS_DECOYDATABASE": { + "openms": "3.4.1" + }, + "OPENMS_IDFILTER_Q_VALUE": { + "openms": "3.4.1" + }, + "OPENMS_IDMASSACCURACY": { + "OpenMS": "3.4.1" + }, + "OPENMS_IDMERGER": { + "openms": "3.4.1" + }, + "OPENMS_PEPTIDEINDEXER": { + "openms": "3.4.1" + }, + "OPENMS_PERCOLATORADAPTER": { + "PercolatorAdapter": "3.4.1-pre-exported-20250822", + "percolator": "3.07.1, Build Date Mar 13 2025 17:19:27" + }, + "OPENMS_PSMFEATUREEXTRACTOR": { + "openms": "3.4.1" + }, + "OPENMS_TEXTEXPORTER": { + "openms": "3.4.1" + }, + "PYOPENMS_CHROMATOGRAMEXTRACTOR": { + "pyopenms": "3.4.1" + }, + "PYOPENMS_IONANNOTATOR": { + "pyopenms": "3.4.1" + }, + "SUMMARIZE_RESULTS": { + "pyopenms": "3.4.1" + }, + "Workflow": { + "nf-core/mhcquant": "v3.1.0" + } + }, + [ + "HepG2_A.tsv", + "intermediate_results", + "intermediate_results/comet", + "intermediate_results/comet/HepG2_rep1_small_pin.tsv", + "intermediate_results/comet/HepG2_rep2_small_pin.tsv", + "intermediate_results/comet/HepG2_rep3_small_pin.tsv", + "intermediate_results/ion_annotations", + "intermediate_results/ion_annotations/HepG2_A_all_peaks.tsv", + "intermediate_results/ion_annotations/HepG2_A_matching_ions.tsv", + "intermediate_results/rescoring", + "intermediate_results/rescoring/HepG2_A_ms2rescore.idXML", + "intermediate_results/rescoring/HepG2_A_pout.idXML", + "intermediate_results/rescoring/HepG2_A_pout_filtered.idXML", + "intermediate_results/rescoring/HepG2_A_psm.idXML", + "multiqc", + "multiqc/ms2rescore", + "multiqc/multiqc_data", + "multiqc/multiqc_data/llms-full.txt", + "multiqc/multiqc_data/multiqc.log", + "multiqc/multiqc_data/multiqc.parquet", + "multiqc/multiqc_data/multiqc_chromatogram.txt", + "multiqc/multiqc_data/multiqc_citations.txt", + "multiqc/multiqc_data/multiqc_data.json", + "multiqc/multiqc_data/multiqc_general_stats.txt", + "multiqc/multiqc_data/multiqc_histogram_mz.txt", + "multiqc/multiqc_data/multiqc_histogram_rt.txt", + "multiqc/multiqc_data/multiqc_histogram_scores.txt", + "multiqc/multiqc_data/multiqc_length_dist.txt", + "multiqc/multiqc_data/multiqc_mass_error.txt", + "multiqc/multiqc_data/multiqc_percolator_barplot.txt", + "multiqc/multiqc_data/multiqc_scores_xcorr.txt", + "multiqc/multiqc_data/multiqc_software_versions.txt", + "multiqc/multiqc_data/multiqc_sources.txt", + "multiqc/multiqc_data/percolator_plot.txt", + "multiqc/multiqc_plots", + "multiqc/multiqc_plots/pdf", + "multiqc/multiqc_plots/pdf/chromatogram-cnt.pdf", + "multiqc/multiqc_plots/pdf/chromatogram-log.pdf", + "multiqc/multiqc_plots/pdf/general_stats.pdf", + "multiqc/multiqc_plots/pdf/histogram_mz.pdf", + "multiqc/multiqc_plots/pdf/histogram_rt.pdf", + "multiqc/multiqc_plots/pdf/histogram_scores.pdf", + "multiqc/multiqc_plots/pdf/length_dist.pdf", + "multiqc/multiqc_plots/pdf/mass_error.pdf", + "multiqc/multiqc_plots/pdf/percolator_plot-cnt.pdf", + "multiqc/multiqc_plots/pdf/percolator_plot-pct.pdf", + "multiqc/multiqc_plots/pdf/scores_xcorr.pdf", + "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/chromatogram-cnt.png", + "multiqc/multiqc_plots/png/chromatogram-log.png", + "multiqc/multiqc_plots/png/general_stats.png", + "multiqc/multiqc_plots/png/histogram_mz.png", + "multiqc/multiqc_plots/png/histogram_rt.png", + "multiqc/multiqc_plots/png/histogram_scores.png", + "multiqc/multiqc_plots/png/length_dist.png", + "multiqc/multiqc_plots/png/mass_error.png", + "multiqc/multiqc_plots/png/percolator_plot-cnt.png", + "multiqc/multiqc_plots/png/percolator_plot-pct.png", + "multiqc/multiqc_plots/png/scores_xcorr.png", + "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/chromatogram-cnt.svg", + "multiqc/multiqc_plots/svg/chromatogram-log.svg", + "multiqc/multiqc_plots/svg/general_stats.svg", + "multiqc/multiqc_plots/svg/histogram_mz.svg", + "multiqc/multiqc_plots/svg/histogram_rt.svg", + "multiqc/multiqc_plots/svg/histogram_scores.svg", + "multiqc/multiqc_plots/svg/length_dist.svg", + "multiqc/multiqc_plots/svg/mass_error.svg", + "multiqc/multiqc_plots/svg/percolator_plot-cnt.svg", + "multiqc/multiqc_plots/svg/percolator_plot-pct.svg", + "multiqc/multiqc_plots/svg/scores_xcorr.svg", + "multiqc/multiqc_report.html", + "pipeline_info", + "pipeline_info/nf_core_mhcquant_software_mqc_versions.yml" + ], + [ + + ], + [ + [ + "HepG2_A.tsv", + [ + "AAAAAAHRL", + "AAATVTKKV", + "AAHPNVQKV", + "AAM(Oxidation)SVAKRV", + "AANAQPHKL", + "AANDKLKKM", + "AANPDPKKL", + "AAPPPPAHA", + "AAPRPPPKPM(Oxidation)", + "AAQAHTREL", + "AAQSEAKVV", + "AARAEAREI", + "AASPVGKRL", + "AASSLKKQY", + "AATDHSNQL", + "AATPAKKTV", + "AATRWAKKI", + "AATSNLKKL", + "AATVTKKTY", + "AKDVKFGAD", + "ALKDKIEKA", + "ALKDSVQRA", + "ALKENGGARLA", + "ALKKALAAA", + "ALSDLHAHK", + "AM(Oxidation)AARPHSI", + "AM(Oxidation)AASPHAV", + "AM(Oxidation)ASHLTST", + "AM(Oxidation)HGHVEVV", + "AM(Oxidation)NARPHKV", + "AMNARPHKV", + "APAPRRLP", + "APRPPPKPM(Oxidation)", + "ATWSDPHKA", + "AVM(Oxidation)GNPKVKA", + "AVM(Oxidation)GNPKVKAH", + "AVVVKKIETRDG", + "DAAVHQRI", + "DAKKQIKQV", + "DAPAGRKV", + "DGKKKISTV", + "DHVITNM(Oxidation)N", + "DPM(Oxidation)KARVV", + "DPPKTHVT", + "DPPRDSKGL", + "DSKKSQPKI", + "EAKTHEAQI", + "EYSKQM(Oxidation)QRF", + "FADPHSKRV", + "FPHSAHQKY", + "FPSRGKSSSY", + "GKVGAHAGEY", + "GKVGAHAGEYG", + "GLAKSIHHA", + "GMAKKVTKA", + "GNVAEGETKPD", + "GPNKKPRF", + "GPRVVERH", + "GRVVEPKR", + "GVM(Oxidation)VGM(Oxidation)GQKD", + "HAAENPGKY", + "HAANPNGRYY", + "HAASRIKTI", + "HAATYTKKV", + "HAFGGNKASY", + "HAGPTAHEL", + "HAHVDKVTY", + "HAIGKSQSF", + "HAKEKLTAL", + "HAM(Oxidation)EEVKKF", + "HAPELTKKV", + "HLKEDQTEY", + "HPAENGKSNF", + "HPESERISM(Oxidation)", + "HPNKVKVY", + "HPSQPQGTY", + "HPYQPDPKM(Oxidation)", + "HSRNEGVATY", + "HSSPASSNY", + "HVKDANGNSF", + "HVSTHQHNY", + "IASQTVKKV", + "IKTVETRD", + "ILDKKVEKV", + "IPKKHISQI", + "IPQKFHRSV", + "ISSEAHREV", + "IVGRPRHQ", + "IYTEHAHQV", + "KAAAFEKQV", + "KAAKPKVV", + "KAAQPKSL", + "KAASHIKSI", + "KAATVTKEL", + "KAISGVHTV", + "KAKPGTYKV", + "KALVKPKEV", + "KASEQAKVV", + "KASGTLREY", + "KAYGKAKSI", + "KAYSEAHEI", + "KGTGASGSF", + "KLAESVEKA", + "KLAPPPKKA", + "KLDNQVSKV", + "KLM(Oxidation)QQQQEV", + "KLQPGSVKKV", + "KLSPKAEEV", + "KM(Oxidation)DESKHEI", + "KM(Oxidation)LDHEYTT", + "KMDESKHEI", + "KMNESTRSV", + "KMQEHSDQV", + "KSKEFVQKV", + "KTKEGVREV", + "KVAQPKEV", + "KVIDTQQKV", + "KVSNSGITRV", + "KVVNPTQK", + "KYKERGTVL", + "KYNRQSM(Oxidation)TL", + "KYQPKPKQI", + "KYTPPPHHI", + "LAKTGVHHY", + "LDKKVEKV", + "LLKSEKSSY", + "LPPKDGKVA", + "LPSENHKEM(Oxidation)", + "M(Oxidation)LSEHTSKL", + "M(Oxidation)PNKVRKI", + "M(Oxidation)PPEHVRKI", + "M(Oxidation)PQGGGQHY", + "M(Oxidation)PQKERESI", + "M(Oxidation)PRNLREY", + "MPKAEKNAV", + "MPNKVRKI", + "MPPEHVRKI", + "MPQKERESI", + "NAHGEPRNY", + "NALAHKYH", + "NAM(Oxidation)KIRDV", + "NATAVVRHM(Oxidation)", + "NATNAVKRL", + "NGTHVVRHY", + "NIQKITKS", + "NLAEKPKTV", + "NLKVKGPVR", + "NLRPKKKV", + "NLRPKKKVK", + "NLSSLSKK", + "NLTEEEEKSKS", + "NNLSSLSKK", + "NPAAYENDK", + "NPFGGASHAKG", + "NPKESSSSL", + "NSHSTTSSF", + "NTKIGPRR", + "NVDYSKLKK", + "NVINGGSHA", + "NVKIVKVKKE", + "PKSKELVSSSS", + "PPNKKPKV", + "PVEKALRD", + "QAGPINREM(Oxidation)", + "QALKHLKQY", + "QGVM(Oxidation)VGM(Oxidation)GQK", + "QGVM(Oxidation)VGM(Oxidation)GQKD", + "QPAKADKESF", + "QPHKVTQY", + "QTHQPPAPNS", + "QYKKDGADF", + "RAQEKVHEM", + "RFYARYSL", + "RLAEAHAKV", + "RLGPTGKEV", + "RLHEKIQEA", + "RLNNKSAKV", + "RMARTPQTV", + "RPKKPGQSF", + "RPVPKGATY", + "RQVTGVTRV", + "RSNEHIREL", + "RSTENVNKL", + "RSTQYM(Oxidation)KEY", + "RVAGIHKKV", + "RYDDM(Oxidation)AAAM(Oxidation)", + "RYIDTHNRV", + "RYM(Oxidation)NHM(Oxidation)QSL", + "SAKLERSHY", + "SALSHVRKI", + "SAMSNPRAM(Oxidation)", + "SAQTTSHEL", + "SARAGETRF", + "SASEAAKKY", + "SASHVSKTV", + "SATGHPRKV", + "SATNALRSM(Oxidation)", + "SATSNKHLL", + "SAVDRQREY", + "SAYANAKKY", + "SEVAHRFK", + "SIVGRPRH", + "SKEYFSKQ", + "SLDKTSHSV", + "SLDTQPKKV", + "SLNKHVEAV", + "SM(Oxidation)LGSPHKV", + "SM(Oxidation)NTHLKAV", + "SM(Oxidation)PEQAHKV", + "SPM(Oxidation)EKIKQY", + "SPNKHNRLY", + "SPNYHEEKY", + "SQRFPKAE", + "SRPETGRPRPKG", + "SSRSYTSGPG", + "SVKNDHSAY", + "SVQVFGRKK", + "SYGSGRRF", + "SYVGDEAQSKR", + "SYVGDEAQSKRG", + "TALAPSTM(Oxidation)K", + "TAPQTQHV", + "TARPGPRAV", + "TDKSFVEK", + "TDRETGKLKG", + "TEKLVTSK", + "TEKLVTSKG", + "TGYYGKGKP", + "THQPPAPNS", + "THYDPPRK", + "TIGEGQQHHLG", + "TISRPKGVA", + "TKELPSGKKY", + "TKKVPQVS", + "TLSGHSQEV", + "TLVQTKGT", + "TNNLRPKKKVK", + "TPKM(Oxidation)PGQSV", + "TPPGVRKI", + "TRLSRTPGNR", + "TSGPGSRISSSS", + "TSVSRPGRG", + "TTTHITKTV", + "TVIGPDGHKE", + "TVKDSRTVY", + "TVQNEANKY", + "VAPPKAHEV", + "VARAGQKGY", + "VASEGIKRY", + "VHLTPEEK", + "VITDKEKAE", + "VPKEGKVV", + "VQKTIAEN", + "VQNGKHFKF", + "VSKGTLVQTKGT", + "VTTSTRTY", + "VYAQKHQQL", + "VYGKTSHL", + "YADEKTKDV", + "YARLHPRAV", + "YGSTVSKRV", + "YLNKHIQKV", + "YPAKAKGTF", + "YTKKLNTQ", + "YTM(Oxidation)KKVHAL", + "YVGDEAQSKR" + ] + ] + ] + ], + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.04.8" + }, + "timestamp": "2025-10-28T21:53:36.826911285" + } +} \ No newline at end of file diff --git a/tests/mokapot.nf.test b/tests/mokapot.nf.test new file mode 100644 index 00000000..128dc8a4 --- /dev/null +++ b/tests/mokapot.nf.test @@ -0,0 +1,38 @@ +nextflow_pipeline { + + name "Test pipeline" + script "../main.nf" + tag "pipeline" + tag "test_mokapot" + profile "test_mokapot" + + test("-profile test_mokapot") { + + when { + params { + outdir = "$outputDir" + } + } + + then { + // stable_name: All files + folders in ${params.outdir}/ with a stable name + def stable_name = getAllFilesFromDir(params.outdir, relative: true, includeDir: true, ignore: ['pipeline_info/*.{html,json,txt}']) + // stable_path: All files in ${params.outdir}/ with stable content + // Mokapot seems to return non-deterministic results eventhough the random number generator (rng) is fixed + def stable_path = getAllFilesFromDir(params.outdir, ignoreFile: 'tests/.nftignore', ignore: ['*.tsv']) + assertAll( + { assert workflow.success}, + { assert snapshot( + // Number of successful tasks + workflow.trace.succeeded().size(), + // pipeline versions.yml file for multiqc from which Nextflow version is removed because we test pipelines on multiple Nextflow versions + removeNextflowVersion("$outputDir/pipeline_info/nf_core_mhcquant_software_mqc_versions.yml"), + // All stable path name, with a relative path + stable_name, + // All files with stable contents + stable_path + ).match() } + ) + } + } +} diff --git a/tests/mokapot.nf.test.snap b/tests/mokapot.nf.test.snap new file mode 100644 index 00000000..4acd6735 --- /dev/null +++ b/tests/mokapot.nf.test.snap @@ -0,0 +1,117 @@ +{ + "-profile test_mokapot": { + "content": [ + 20, + { + "MS2RESCORE": { + "MS\u00b2Rescore": "3.1.5)" + }, + "OPENMSTHIRDPARTY_COMETADAPTER": { + "CometAdapter": "3.4.1", + "Comet": "2024.01 rev. 1" + }, + "OPENMS_DECOYDATABASE": { + "openms": "3.4.1" + }, + "OPENMS_IDFILTER_Q_VALUE": { + "openms": "3.4.1" + }, + "OPENMS_IDMASSACCURACY": { + "OpenMS": "3.4.1" + }, + "OPENMS_IDMERGER": { + "openms": "3.4.1" + }, + "OPENMS_IDSCORESWITCHER": { + "openms": "3.4.1" + }, + "OPENMS_PEPTIDEINDEXER": { + "openms": "3.4.1" + }, + "OPENMS_TEXTEXPORTER": { + "openms": "3.4.1" + }, + "PYOPENMS_CHROMATOGRAMEXTRACTOR": { + "pyopenms": "3.4.1" + }, + "SUMMARIZE_RESULTS": { + "pyopenms": "3.4.1" + }, + "Workflow": { + "nf-core/mhcquant": "v3.1.0" + } + }, + [ + "HepG2_A.tsv", + "intermediate_results", + "intermediate_results/comet", + "intermediate_results/comet/HepG2_rep1_small_pin.tsv", + "intermediate_results/comet/HepG2_rep2_small_pin.tsv", + "intermediate_results/comet/HepG2_rep3_small_pin.tsv", + "intermediate_results/rescoring", + "intermediate_results/rescoring/HepG2_A_ms2rescore.idXML", + "intermediate_results/rescoring/HepG2_A_pout_filtered.idXML", + "multiqc", + "multiqc/ms2rescore", + "multiqc/multiqc_data", + "multiqc/multiqc_data/llms-full.txt", + "multiqc/multiqc_data/multiqc.log", + "multiqc/multiqc_data/multiqc.parquet", + "multiqc/multiqc_data/multiqc_chromatogram.txt", + "multiqc/multiqc_data/multiqc_citations.txt", + "multiqc/multiqc_data/multiqc_data.json", + "multiqc/multiqc_data/multiqc_general_stats.txt", + "multiqc/multiqc_data/multiqc_histogram_mz.txt", + "multiqc/multiqc_data/multiqc_histogram_rt.txt", + "multiqc/multiqc_data/multiqc_histogram_scores.txt", + "multiqc/multiqc_data/multiqc_length_dist.txt", + "multiqc/multiqc_data/multiqc_mass_error.txt", + "multiqc/multiqc_data/multiqc_scores_xcorr.txt", + "multiqc/multiqc_data/multiqc_software_versions.txt", + "multiqc/multiqc_data/multiqc_sources.txt", + "multiqc/multiqc_plots", + "multiqc/multiqc_plots/pdf", + "multiqc/multiqc_plots/pdf/chromatogram-cnt.pdf", + "multiqc/multiqc_plots/pdf/chromatogram-log.pdf", + "multiqc/multiqc_plots/pdf/general_stats.pdf", + "multiqc/multiqc_plots/pdf/histogram_mz.pdf", + "multiqc/multiqc_plots/pdf/histogram_rt.pdf", + "multiqc/multiqc_plots/pdf/histogram_scores.pdf", + "multiqc/multiqc_plots/pdf/length_dist.pdf", + "multiqc/multiqc_plots/pdf/mass_error.pdf", + "multiqc/multiqc_plots/pdf/scores_xcorr.pdf", + "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/chromatogram-cnt.png", + "multiqc/multiqc_plots/png/chromatogram-log.png", + "multiqc/multiqc_plots/png/general_stats.png", + "multiqc/multiqc_plots/png/histogram_mz.png", + "multiqc/multiqc_plots/png/histogram_rt.png", + "multiqc/multiqc_plots/png/histogram_scores.png", + "multiqc/multiqc_plots/png/length_dist.png", + "multiqc/multiqc_plots/png/mass_error.png", + "multiqc/multiqc_plots/png/scores_xcorr.png", + "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/chromatogram-cnt.svg", + "multiqc/multiqc_plots/svg/chromatogram-log.svg", + "multiqc/multiqc_plots/svg/general_stats.svg", + "multiqc/multiqc_plots/svg/histogram_mz.svg", + "multiqc/multiqc_plots/svg/histogram_rt.svg", + "multiqc/multiqc_plots/svg/histogram_scores.svg", + "multiqc/multiqc_plots/svg/length_dist.svg", + "multiqc/multiqc_plots/svg/mass_error.svg", + "multiqc/multiqc_plots/svg/scores_xcorr.svg", + "multiqc/multiqc_report.html", + "pipeline_info", + "pipeline_info/nf_core_mhcquant_software_mqc_versions.yml" + ], + [ + + ] + ], + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.04.8" + }, + "timestamp": "2025-10-28T22:04:22.998726246" + } +} \ No newline at end of file diff --git a/tests/nextflow.config b/tests/nextflow.config new file mode 100644 index 00000000..1c65d6d3 --- /dev/null +++ b/tests/nextflow.config @@ -0,0 +1,15 @@ +/* +======================================================================================== + Nextflow config file for running nf-test tests +======================================================================================== +*/ + +// TODO nf-core: Specify any additional parameters here +// Or any resources requirements +params { + modules_testdata_base_path = 'https://raw.githubusercontent.com/nf-core/test-datasets/modules/data/' + pipelines_testdata_base_path = 'https://raw.githubusercontent.com/nf-core/test-datasets/refs/heads/mhcquant' +} + +// fixes S3 access issues on self-hosted runners +aws.client.anonymous = true diff --git a/tests/speclib.nf.test b/tests/speclib.nf.test new file mode 100644 index 00000000..feaf3e81 --- /dev/null +++ b/tests/speclib.nf.test @@ -0,0 +1,57 @@ +nextflow_pipeline { + + name "Test pipeline" + script "../main.nf" + tag "pipeline" + tag "test_speclib" + profile "test_speclib" + + test("-profile test_speclib") { + + when { + params { + outdir = "$outputDir" + } + } + + then { + // stable_name: All files + folders in ${params.outdir}/ with a stable name + def stable_name = getAllFilesFromDir(params.outdir, relative: true, includeDir: true, ignore: ['pipeline_info/*.{html,json,txt}']) + // stable_path: All files in ${params.outdir}/ with stable content + def stable_path = getAllFilesFromDir(params.outdir, ignoreFile: 'tests/.nftignore') + // Extract peptidoform column from all TSV files + def peptidoform_data = [] + new File(params.outdir).eachFileRecurse { file -> + if (file.name.endsWith('.tsv')) { + def lines = file.readLines() + if (lines.size() > 0) { + def header = lines[0].split('\t') + def peptidoformIndex = header.findIndexOf { it == 'peptidoform' } + if (peptidoformIndex >= 0) { + def peptidoforms = lines.drop(1).collect { line -> + def fields = line.split('\t') + fields.size() > peptidoformIndex ? fields[peptidoformIndex] : '' + }.findAll { it != '' }.sort() + peptidoform_data.add([file.name, peptidoforms]) + } + } + } + } + assertAll( + { assert workflow.success}, + { assert snapshot( + // Number of successful tasks + workflow.trace.succeeded().size(), + // pipeline versions.yml file for multiqc from which Nextflow version is removed because we test pipelines on multiple Nextflow versions + removeNextflowVersion("$outputDir/pipeline_info/nf_core_mhcquant_software_mqc_versions.yml"), + // All stable path name, with a relative path + stable_name, + // All files with stable contents + stable_path, + // Peptidoform data from TSV files + peptidoform_data + ).match() } + ) + } + } +} diff --git a/tests/speclib.nf.test.snap b/tests/speclib.nf.test.snap new file mode 100644 index 00000000..4864a01a --- /dev/null +++ b/tests/speclib.nf.test.snap @@ -0,0 +1,398 @@ +{ + "-profile test_speclib": { + "content": [ + 28, + { + "EASYPQP_CONVERT": { + "easypqp": "0.1.53" + }, + "EASYPQP_LIBRARY": { + "easypqp": "0.1.53" + }, + "MS2RESCORE": { + "MS\u00b2Rescore": "3.1.5)" + }, + "OPENMSTHIRDPARTY_COMETADAPTER": { + "CometAdapter": "3.4.1", + "Comet": "2024.01 rev. 1" + }, + "OPENMS_DECOYDATABASE": { + "openms": "3.4.1" + }, + "OPENMS_IDFILTER_Q_VALUE": { + "openms": "3.4.1" + }, + "OPENMS_IDMASSACCURACY": { + "OpenMS": "3.4.1" + }, + "OPENMS_IDMERGER": { + "openms": "3.4.1" + }, + "OPENMS_PEPTIDEINDEXER": { + "openms": "3.4.1" + }, + "OPENMS_PERCOLATORADAPTER": { + "PercolatorAdapter": "3.4.1-pre-exported-20250822", + "percolator": "3.07.1, Build Date Mar 13 2025 17:19:27" + }, + "OPENMS_PSMFEATUREEXTRACTOR": { + "openms": "3.4.1" + }, + "OPENMS_TEXTEXPORTER": { + "openms": "3.4.1" + }, + "PYOPENMS_CHROMATOGRAMEXTRACTOR": { + "pyopenms": "3.4.1" + }, + "SUMMARIZE_RESULTS": { + "pyopenms": "3.4.1" + }, + "Workflow": { + "nf-core/mhcquant": "v3.1.0" + } + }, + [ + "HepG2_A.tsv", + "intermediate_results", + "intermediate_results/comet", + "intermediate_results/comet/HepG2_rep1_small_pin.tsv", + "intermediate_results/comet/HepG2_rep2_small_pin.tsv", + "intermediate_results/comet/HepG2_rep3_small_pin.tsv", + "intermediate_results/rescoring", + "intermediate_results/rescoring/HepG2_A_ms2rescore.idXML", + "intermediate_results/rescoring/HepG2_A_pout.idXML", + "intermediate_results/rescoring/HepG2_A_pout_filtered.idXML", + "intermediate_results/rescoring/HepG2_A_psm.idXML", + "multiqc", + "multiqc/ms2rescore", + "multiqc/multiqc_data", + "multiqc/multiqc_data/llms-full.txt", + "multiqc/multiqc_data/multiqc.log", + "multiqc/multiqc_data/multiqc.parquet", + "multiqc/multiqc_data/multiqc_chromatogram.txt", + "multiqc/multiqc_data/multiqc_citations.txt", + "multiqc/multiqc_data/multiqc_data.json", + "multiqc/multiqc_data/multiqc_general_stats.txt", + "multiqc/multiqc_data/multiqc_histogram_mz.txt", + "multiqc/multiqc_data/multiqc_histogram_rt.txt", + "multiqc/multiqc_data/multiqc_histogram_scores.txt", + "multiqc/multiqc_data/multiqc_length_dist.txt", + "multiqc/multiqc_data/multiqc_mass_error.txt", + "multiqc/multiqc_data/multiqc_percolator_barplot.txt", + "multiqc/multiqc_data/multiqc_scores_xcorr.txt", + "multiqc/multiqc_data/multiqc_software_versions.txt", + "multiqc/multiqc_data/multiqc_sources.txt", + "multiqc/multiqc_data/percolator_plot.txt", + "multiqc/multiqc_plots", + "multiqc/multiqc_plots/pdf", + "multiqc/multiqc_plots/pdf/chromatogram-cnt.pdf", + "multiqc/multiqc_plots/pdf/chromatogram-log.pdf", + "multiqc/multiqc_plots/pdf/general_stats.pdf", + "multiqc/multiqc_plots/pdf/histogram_mz.pdf", + "multiqc/multiqc_plots/pdf/histogram_rt.pdf", + "multiqc/multiqc_plots/pdf/histogram_scores.pdf", + "multiqc/multiqc_plots/pdf/length_dist.pdf", + "multiqc/multiqc_plots/pdf/mass_error.pdf", + "multiqc/multiqc_plots/pdf/percolator_plot-cnt.pdf", + "multiqc/multiqc_plots/pdf/percolator_plot-pct.pdf", + "multiqc/multiqc_plots/pdf/scores_xcorr.pdf", + "multiqc/multiqc_plots/png", + "multiqc/multiqc_plots/png/chromatogram-cnt.png", + "multiqc/multiqc_plots/png/chromatogram-log.png", + "multiqc/multiqc_plots/png/general_stats.png", + "multiqc/multiqc_plots/png/histogram_mz.png", + "multiqc/multiqc_plots/png/histogram_rt.png", + "multiqc/multiqc_plots/png/histogram_scores.png", + "multiqc/multiqc_plots/png/length_dist.png", + "multiqc/multiqc_plots/png/mass_error.png", + "multiqc/multiqc_plots/png/percolator_plot-cnt.png", + "multiqc/multiqc_plots/png/percolator_plot-pct.png", + "multiqc/multiqc_plots/png/scores_xcorr.png", + "multiqc/multiqc_plots/svg", + "multiqc/multiqc_plots/svg/chromatogram-cnt.svg", + "multiqc/multiqc_plots/svg/chromatogram-log.svg", + "multiqc/multiqc_plots/svg/general_stats.svg", + "multiqc/multiqc_plots/svg/histogram_mz.svg", + "multiqc/multiqc_plots/svg/histogram_rt.svg", + "multiqc/multiqc_plots/svg/histogram_scores.svg", + "multiqc/multiqc_plots/svg/length_dist.svg", + "multiqc/multiqc_plots/svg/mass_error.svg", + "multiqc/multiqc_plots/svg/percolator_plot-cnt.svg", + "multiqc/multiqc_plots/svg/percolator_plot-pct.svg", + "multiqc/multiqc_plots/svg/scores_xcorr.svg", + "multiqc/multiqc_report.html", + "pipeline_info", + "pipeline_info/nf_core_mhcquant_software_mqc_versions.yml", + "spectrum_library", + "spectrum_library/HepG2_A_speclib.tsv" + ], + [ + + ], + [ + [ + "HepG2_A.tsv", + [ + "AAAAAAHRL", + "AAATVTKKV", + "AAHPNVQKV", + "AAKDPSPSV", + "AAM(Oxidation)SVAKRV", + "AANAQPHKL", + "AANDKLKKM", + "AANPDPKKL", + "AAPPPPAHA", + "AAPRPPPKPM(Oxidation)", + "AAQAHTREL", + "AAQSEAKVV", + "AARAEAREI", + "AASPVGKRL", + "AASSLKKQY", + "AATDHSNQL", + "AATPAKKTV", + "AATRWAKKI", + "AATSNLKKL", + "AATVTKKTY", + "AKDVKFGAD", + "ALKDKIEKA", + "ALKDSVQRA", + "ALKENGGARLA", + "ALSDLHAHK", + "AM(Oxidation)AARPHSI", + "AM(Oxidation)AASPHAV", + "AM(Oxidation)ASHLTST", + "AM(Oxidation)HGHVEVV", + "AM(Oxidation)NARPHKV", + "AMNARPHKV", + "APRPPPKPM(Oxidation)", + "ATWSDPHKA", + "AVM(Oxidation)GNPKVKA", + "AVVVKKIETRDG", + "DAAVHQRI", + "DAKKQIKQV", + "DAPAGRKV", + "DGKKKISTV", + "DHVITNM(Oxidation)N", + "DPM(Oxidation)KARVV", + "DPPKTHVT", + "DPPRDSKGL", + "DSKKSQPKI", + "EAKTHEAQI", + "EDRDDNKVY", + "EYSKQM(Oxidation)QRF", + "FADPHSKRV", + "FPHSAHQKY", + "FPSRGKSSSY", + "GKVGAHAGEY", + "GKVGAHAGEYG", + "GLAKSIHHA", + "GMAKKVTKA", + "GNVAEGETKPD", + "GPNKKPRF", + "GRPM(Oxidation)PPSRR", + "GRVVEPKR", + "GVM(Oxidation)VGM(Oxidation)GQKD", + "HAAENPGKY", + "HAANPNGRYY", + "HAATYTKKV", + "HAFGGNKASY", + "HAGPTAHEL", + "HAIGKSQSF", + "HAKEKLTAL", + "HAM(Oxidation)EEVKKF", + "HAPELTKKV", + "HLKEDQTEY", + "HPAENGKSNF", + "HPESERISM(Oxidation)", + "HPNKVKVY", + "HPSQPQGTY", + "HPYQPDPKM(Oxidation)", + "HSRNEGVATY", + "HSSPASSNY", + "HVKDANGNSF", + "HVSTHQHNY", + "IASQTVKKV", + "IKTVETRD", + "ILDKKVEKV", + "IPKKHISQI", + "IPQKFHRSV", + "ISSEAHREV", + "IVGRPRHQ", + "IYTEHAHQV", + "KAAAFEKQV", + "KAAKPKVV", + "KAASHIKSI", + "KAATVTKEL", + "KAISGVHTV", + "KAKPGTYKV", + "KALVKPKEV", + "KASEQAKVV", + "KASGTLREY", + "KAYGKAKSI", + "KAYSEAHEI", + "KHANQVLSL", + "KLAESVEKA", + "KLAPPPKKA", + "KLDNQVSKV", + "KLM(Oxidation)QQQQEV", + "KLQPGSVKKV", + "KLSPKAEEV", + "KM(Oxidation)DESKHEI", + "KM(Oxidation)LDHEYTT", + "KMDESKHEI", + "KMQEHSDQV", + "KSKEFVQKV", + "KTKEGVREV", + "KVAQPKEV", + "KVIDTQQKV", + "KVSNSGITRV", + "KVVNPTQK", + "KYLGKTHNL", + "KYNRQSM(Oxidation)TL", + "KYQPKPKQI", + "KYTPPPHHI", + "LAKTGVHHY", + "LDKKVEKV", + "LLKSEKSSY", + "LPSENHKEM", + "LPSENHKEM(Oxidation)", + "M(Oxidation)LSEHTSKL", + "M(Oxidation)PPEHVRKI", + "M(Oxidation)PQGGGQHY", + "M(Oxidation)PQKERESI", + "M(Oxidation)PRNLREY", + "MPKAEKNAV", + "MPNKVRKI", + "MPPEHVRKI", + "MPQKERESI", + "NAAEGRSF", + "NAHGEPRNY", + "NALAHKYH", + "NAM(Oxidation)KIRDV", + "NASARDNTI", + "NATAVVRHM(Oxidation)", + "NATNAVKRL", + "NGTHVVRHY", + "NIQKITKS", + "NLAEKPKTV", + "NLKVKGPVR", + "NLRPKKKV", + "NLRPKKKVK", + "NLTEEEEKSKS", + "NNLSSLSKK", + "NPAAYENDK", + "NPFGGASHAKG", + "NPKESSSSL", + "NTKIGPRR", + "NVDYSKLKK", + "NVINGGSHA", + "NVKIVKVKKE", + "NYTKEHNNL", + "PKSKELVSSSS", + "PPNKKPKV", + "PVEKALRD", + "QAGPINREM(Oxidation)", + "QALKHLKQY", + "QGVM(Oxidation)VGM(Oxidation)GQK", + "QGVM(Oxidation)VGM(Oxidation)GQKD", + "QPAKADKESF", + "QPHKVTQY", + "QTHQPPAPNS", + "QVKPNSNQV", + "QYKKDGADF", + "RADKKAPR", + "RLAEAHAKV", + "RLHEKIQEA", + "RLNNKSAKV", + "RPKKPGQSF", + "RPVPKGATY", + "RQVTGVTRV", + "RSNEHIREL", + "RSTENVNKL", + "RSTQYM(Oxidation)KEY", + "RVAGIHKKV", + "RYDDM(Oxidation)AAAM(Oxidation)", + "RYIDLHSNR", + "RYIDTHNRV", + "RYM(Oxidation)NHM(Oxidation)QSL", + "SAKLERSHY", + "SAM(Oxidation)SNPRAM", + "SAQTTSHEL", + "SARAGETRF", + "SASEAAKKY", + "SASHVSKTV", + "SATGHPRKV", + "SATNALRSM(Oxidation)", + "SATSNKHLL", + "SAVDRQREY", + "SAYANAKKY", + "SEVAHRFK", + "SIVGRPRH", + "SKEYFSKQ", + "SLDKTSHSV", + "SLDTQPKKV", + "SM(Oxidation)LGSPHKV", + "SM(Oxidation)NTHLKAV", + "SPM(Oxidation)EKIKQY", + "SPNYHEEKY", + "SQRFPKAE", + "SVKNDHSAY", + "SVQVFGRKK", + "SYVGDEAQSKR", + "SYVGDEAQSKRG", + "TALAPSTM(Oxidation)K", + "TAPQTQHV", + "TARPGPRAV", + "TDKSFVEK", + "TDRETGKL", + "TEKLVTSK", + "TEKLVTSKG", + "TGYYGKGKP", + "THQPPAPNS", + "THYDPPRK", + "TIGEGQQHHLG", + "TISRPKGVA", + "TKELPSGKKY", + "TLVQTKGT", + "TNNLRPKKKVK", + "TPPGVRKI", + "TRLSRTPGNR", + "TSGPGSRISSSS", + "TSTPNAKTV", + "TTPISEQKG", + "TTTHITKTV", + "TVIGPDGHKE", + "TVKDSRTVY", + "TVQNEANKY", + "VAPPKAHEV", + "VARAGQKGY", + "VASEGIKRY", + "VHLTPEEK", + "VITDKEKAE", + "VPKEGKVV", + "VQKTIAEN", + "VQNGKHFKF", + "VSKGTLVQTKGT", + "VTTSTRTY", + "VYAQKHQQL", + "VYGKTSHL", + "YADEKTKDV", + "YARLHPRAV", + "YGSTVSKRV", + "YLNKHIQKV", + "YPAKAKGTF", + "YTKKLNTQ", + "YTM(Oxidation)KKVHAL", + "YVGDEAQSKR", + "YVGDEAQSKRG" + ] + ] + ] + ], + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.04.8" + }, + "timestamp": "2025-10-28T22:13:30.098880662" + } +} \ No newline at end of file diff --git a/workflows/mhcquant.nf b/workflows/mhcquant.nf index 14f3be99..dad8d043 100644 --- a/workflows/mhcquant.nf +++ b/workflows/mhcquant.nf @@ -9,10 +9,10 @@ // include { PYOPENMS_CHROMATOGRAMEXTRACTOR } from '../modules/local/pyopenms/chromatogramextractor' -include { DATAMASH_HISTOGRAM } from '../modules/local/datamash_histogram' include { PYOPENMS_IONANNOTATOR } from '../modules/local/pyopenms/ionannotator' include { OPENMS_TEXTEXPORTER } from '../modules/local/openms/textexporter' include { SUMMARIZE_RESULTS } from '../modules/local/pyopenms/summarize_results' +include { EPICORE } from '../modules/local/epicore' // // SUBWORKFLOW: Loaded from subworkflows/local/ @@ -69,9 +69,9 @@ workflow MHCQUANT { // Generate reversed decoy database OPENMS_DECOYDATABASE(ch_fasta) ch_versions = ch_versions.mix(OPENMS_DECOYDATABASE.out.versions) - ch_decoy_db = OPENMS_DECOYDATABASE.out.decoy_fasta.map{ meta, fasta -> [fasta] } + ch_decoy_db = OPENMS_DECOYDATABASE.out.decoy_fasta } else { - ch_decoy_db = ch_fasta.map{ meta, fasta -> [fasta] } + ch_decoy_db = ch_fasta } // Optionally clean up mzML files @@ -88,21 +88,33 @@ workflow MHCQUANT { ch_versions = ch_versions.mix(PYOPENMS_CHROMATOGRAMEXTRACTOR.out.versions) ch_multiqc_files = ch_multiqc_files.mix(PYOPENMS_CHROMATOGRAMEXTRACTOR.out.csv.map{ meta, mzml -> mzml }) - // Run comet database search - OPENMSTHIRDPARTY_COMETADAPTER(ch_clean_mzml_file.combine(ch_decoy_db)) + // Prepare the comet input channel with global fasta or per-sample_condition fasta + ch_comet_in = params.fasta ? + ch_clean_mzml_file.combine(ch_decoy_db.map{ meta, fasta -> [fasta] }) : + ch_clean_mzml_file + .map { meta, mzml -> [ groupKey([id: "${meta.sample}_${meta.condition}"], meta.group_count), meta, mzml] } + .combine(ch_decoy_db, by: 0) + .map { groupKey, meta, mzml, fasta -> [meta, mzml, fasta] } + + // Run comet database search and index decoy and target hits + OPENMSTHIRDPARTY_COMETADAPTER(ch_comet_in) ch_versions = ch_versions.mix(OPENMSTHIRDPARTY_COMETADAPTER.out.versions) - // Index decoy and target hits - OPENMS_PEPTIDEINDEXER(OPENMSTHIRDPARTY_COMETADAPTER.out.idxml.combine(ch_decoy_db)) + // Prepare the peptideindexer channel with global fasta or per-sample_condition fasta + ch_peptideindexer_in = params.fasta ? + OPENMSTHIRDPARTY_COMETADAPTER.out.idxml.combine(ch_decoy_db.map{ meta, fasta -> [fasta] }) : + OPENMSTHIRDPARTY_COMETADAPTER.out.idxml + .map { meta, idxml -> [ groupKey([id: "${meta.sample}_${meta.condition}"], meta.group_count), meta, idxml] } + .combine(ch_decoy_db, by: 0) + .map { groupKey, meta, idxml, fasta -> [meta, idxml, fasta] } + + OPENMS_PEPTIDEINDEXER(ch_peptideindexer_in) ch_versions = ch_versions.mix(OPENMS_PEPTIDEINDEXER.out.versions) // Compute mass errors for multiQC report OPENMS_IDMASSACCURACY(PREPARE_SPECTRA.out.mzml.join(OPENMS_PEPTIDEINDEXER.out.indexed_idxml)) ch_versions = ch_versions.mix(OPENMS_IDMASSACCURACY.out.versions) - // Bin and count mass errors for multiQC report - DATAMASH_HISTOGRAM(OPENMS_IDMASSACCURACY.out.frag_err) - ch_versions = ch_versions.mix(DATAMASH_HISTOGRAM.out.versions) - ch_multiqc_files = ch_multiqc_files.mix(DATAMASH_HISTOGRAM.out.binned_tsv.map{ meta, frag_err_hist -> frag_err_hist }) + ch_multiqc_files = ch_multiqc_files.mix(OPENMS_IDMASSACCURACY.out.frag_err.map{ meta, frag_err -> frag_err }) // Save indexed runs for later use to keep meta-run information. Sort based on file id OPENMS_PEPTIDEINDEXER.out.indexed_idxml @@ -193,13 +205,29 @@ workflow MHCQUANT { SUMMARIZE_RESULTS(OPENMS_TEXTEXPORTER.out.tsv) ch_versions = ch_versions.mix(SUMMARIZE_RESULTS.out.versions) + // + // EPICORE + // + if (params.epicore) { + EPICORE(ch_fasta.map{ it.last()}, SUMMARIZE_RESULTS.out.epicore_input) + ch_versions = ch_versions.mix(EPICORE.out.versions) + ch_multiqc_files = ch_multiqc_files.mix( + EPICORE.out.length_dist, + EPICORE.out.intensity_hist + ) + } + + // + // Collate MultiQC files + // ch_multiqc_files = ch_multiqc_files.mix( SUMMARIZE_RESULTS.out.hist_mz, SUMMARIZE_RESULTS.out.hist_rt, SUMMARIZE_RESULTS.out.hist_scores, - SUMMARIZE_RESULTS.out.hist_xcorr, + SUMMARIZE_RESULTS.out.xcorr, SUMMARIZE_RESULTS.out.lengths, - SUMMARIZE_RESULTS.out.stats + SUMMARIZE_RESULTS.out.intensities, + params.epicore ? EPICORE.out.stats : SUMMARIZE_RESULTS.out.epicore_input.map { meta, tsv, stats -> stats } ) // @@ -213,7 +241,6 @@ workflow MHCQUANT { newLine: true ).set { ch_collated_versions } - // // MODULE: MultiQC //