diff --git a/.github/workflows/awsfulltest.yml b/.github/workflows/awsfulltest.yml index 3ab7364a..b26c8df0 100644 --- a/.github/workflows/awsfulltest.yml +++ b/.github/workflows/awsfulltest.yml @@ -37,7 +37,7 @@ jobs: } profiles: test_full - - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: Seqera Platform debug log file path: | diff --git a/.github/workflows/awstest.yml b/.github/workflows/awstest.yml index d747d13c..b1f77e32 100644 --- a/.github/workflows/awstest.yml +++ b/.github/workflows/awstest.yml @@ -25,7 +25,7 @@ jobs: } profiles: test - - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + - uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: Seqera Platform debug log file path: | diff --git a/.github/workflows/download_pipeline.yml b/.github/workflows/download_pipeline.yml index 6d94bcbf..45884ff9 100644 --- a/.github/workflows/download_pipeline.yml +++ b/.github/workflows/download_pipeline.yml @@ -127,7 +127,7 @@ jobs: fi - name: Upload Nextflow logfile for debugging purposes - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: nextflow_logfile.txt path: .nextflow.log* diff --git a/.github/workflows/fix_linting.yml b/.github/workflows/fix_linting.yml index b67a297c..6a1fef59 100644 --- a/.github/workflows/fix_linting.yml +++ b/.github/workflows/fix_linting.yml @@ -13,7 +13,7 @@ jobs: runs-on: ubuntu-latest steps: # Use the @nf-core-bot token to check out so we can push later - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5 + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5 with: token: ${{ secrets.nf_core_bot_auth_token }} diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index 30e66026..7a527a34 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -11,7 +11,7 @@ jobs: pre-commit: runs-on: ubuntu-latest steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5 + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5 - name: Set up Python 3.14 uses: actions/setup-python@e797f83bcb11b83ae66e0230d6156d7c80228e7c # v6 @@ -28,7 +28,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out pipeline code - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5 + uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5 - name: Install Nextflow uses: nf-core/setup-nextflow@v2 @@ -71,7 +71,7 @@ jobs: - name: Upload linting log file artifact if: ${{ always() }} - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5 with: name: linting-logs path: | diff --git a/.github/workflows/nf-test.yml b/.github/workflows/nf-test.yml index cb4db1d2..121dd70a 100644 --- a/.github/workflows/nf-test.yml +++ b/.github/workflows/nf-test.yml @@ -40,7 +40,7 @@ jobs: rm -rf ./* || true rm -rf ./.??* || true ls -la ./ - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5 + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5 with: fetch-depth: 0 @@ -86,7 +86,7 @@ jobs: TOTAL_SHARDS: ${{ needs.nf-test-changes.outputs.total_shards }} steps: - - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5 + - uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5 with: fetch-depth: 0 diff --git a/.github/workflows/template-version-comment.yml b/.github/workflows/template-version-comment.yml index c5988af9..e8560fc7 100644 --- a/.github/workflows/template-version-comment.yml +++ b/.github/workflows/template-version-comment.yml @@ -9,7 +9,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Check out pipeline code - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5 + uses: actions/checkout@93cb6efe18208431cddfb8368fd83d5badbf9bfd # v5 with: ref: ${{ github.event.pull_request.head.sha }} diff --git a/.gitignore b/.gitignore index a42ce016..d49d554f 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,5 @@ testing/ testing* *.pyc null/ +CLAUDE.md +.claude/ diff --git a/.nf-core.yml b/.nf-core.yml index a38a857f..1a7fed6b 100644 --- a/.nf-core.yml +++ b/.nf-core.yml @@ -2,7 +2,7 @@ lint: files_unchanged: - .github/CONTRIBUTING.md - .vscode/settings.json -nf_core_version: 3.4.1 +nf_core_version: 3.5.1 repository_type: pipeline template: author: Jonas Scheid, Steffen Lemke, Leon Bichmann, Marissa Dubbelaar @@ -12,7 +12,7 @@ template: name: mhcquant org: nf-core outdir: . - version: 3.1.0 skip_features: - fastqc - igenomes + version: 3.2.0dev diff --git a/.prettierignore b/.prettierignore index ceb1e1ca..dd749d43 100644 --- a/.prettierignore +++ b/.prettierignore @@ -12,4 +12,5 @@ testing* bin/ .nf-test/ ro-crate-metadata.json -.nf-test/ +modules/nf-core/ +subworkflows/nf-core/ diff --git a/CHANGELOG.md b/CHANGELOG.md index 363fe483..bb435261 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,33 @@ 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.2.0dev - [release name] - [date] + +### `Added` + +- Added support for single run quantification [#438](https://github.com/nf-core/mhcquant/pull/438) +- Added per-sample search parameter support via samplesheet with SearchPreset column and individual parameter overrides [#439](https://github.com/nf-core/mhcquant/pull/439) +- Added ion mobility export and MultiQC distribution plot for timsTOF data [#441](https://github.com/nf-core/mhcquant/pull/441) + +### `Fixed` + +- Fixed `EPICORE` running only once instead of per sample when `--fasta` is used, by broadcasting `ch_fasta` to `EPICORE` via `.first()` [#446](https://github.com/nf-core/mhcquant/pull/446) +- Fixed `SUMMARIZE_RESULTS` crash with `--quantify` caused by OpenMS 3.5.0 TextExporter phantom column bug ([OpenMS/OpenMS#9120](https://github.com/OpenMS/OpenMS/issues/9120)) [#444](https://github.com/nf-core/mhcquant/pull/444) +- Fixed an issue where stripping the sequence in `SUMMARIZE_RESULTS` did not work for complex modifications [#436](https://github.com/nf-core/mhcquant/pull/436) + +### `Changed` + +- Migrate to topic channels [#431](https://github.com/nf-core/mhcquant/pull/431) + +### `Dependencies` + +| Dependency | Old version | New version | +| ---------- | ----------- | ----------- | +| `easypqp` | 0.1.53 | 0.1.57 | +| `MultiQC` | 1.31.0 | 1.33.0 | +| `Nf-core` | 3.4.1 | 3.5.1 | +| `openms` | 3.4.1 | 3.5.0 | + ## 3.1.0 - BlüBa - 07/01/26 ### `Added` diff --git a/README.md b/README.md index dab675dc..5f5030cf 100644 --- a/README.md +++ b/README.md @@ -5,13 +5,13 @@ -[![Open in GitHub Codespaces](https://github.com/codespaces/badge.svg)](https://github.com/codespaces/new/nf-core/mhcquant) +[![Open in GitHub Codespaces](https://img.shields.io/badge/Open_In_GitHub_Codespaces-black?labelColor=grey&logo=github)](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/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) +[![nf-core template version](https://img.shields.io/badge/nf--core_template-3.5.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.5.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/) diff --git a/assets/multiqc_config.yml b/assets/multiqc_config.yml index 6db209cc..43d2b7f2 100644 --- a/assets/multiqc_config.yml +++ b/assets/multiqc_config.yml @@ -3,9 +3,7 @@ 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 - analysis pipeline. For information about how to interpret these results, please see the - documentation. + This report has been generated by the nf-core/mhcquant analysis pipeline. For information about how to interpret these results, please see the documentation. report_section_order: "nf-core-mhcquant-methods-description": order: -1000 @@ -104,6 +102,19 @@ custom_data: xlab: "Retention time" ylab: "Frequency" + im_plot: + plot_type: "linegraph" + file_format: "csv" + section_name: "Ion Mobility" + description: | + This plot shows the distribution of ion mobility (1/K0) values for identified peptides. + Ion mobility data is available when using instruments with ion mobility separation (e.g., timsTOF). + pconfig: + id: "histogram_im" + title: "Ion Mobility Distribution" + xlab: "Ion Mobility (1/K0) [V·s/cm²]" + ylab: "Frequency" + qvalue_plot: plot_type: "linegraph" file_format: "csv" @@ -166,6 +177,8 @@ sp: fn: "*_histogram_mz.csv" rt_plot: fn: "*_histogram_rt.csv" + im_plot: + fn: "*_histogram_im.csv" qvalue_plot: fn: "*_histogram_scores.csv" scores_plot_xcorr: diff --git a/assets/schema_input.json b/assets/schema_input.json index 253b30dd..4b66bcf1 100644 --- a/assets/schema_input.json +++ b/assets/schema_input.json @@ -13,14 +13,14 @@ "meta": ["id"] }, "Sample": { - "type": "string", - "pattern": "^\\S+$", + "type": ["string", "integer"], + "anyOf": [{ "type": "string", "pattern": "^\\S+$" }, { "type": "integer" }], "errorMessage": "Sample name must be provided and cannot contain spaces", "meta": ["sample"] }, "Condition": { - "type": "string", - "pattern": "^\\S+-?", + "type": ["string", "integer"], + "anyOf": [{ "type": "string", "pattern": "^\\S+-?" }, { "type": "integer" }], "errorMessage": "Sample condition must be provided and cannot contain spaces", "meta": ["condition"] }, @@ -37,6 +37,12 @@ "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" + }, + "SearchPreset": { + "type": "string", + "pattern": "^[a-zA-Z0-9_]+$", + "errorMessage": "SearchPreset must contain only alphanumeric characters and underscores", + "meta": ["search_preset"] } }, "required": ["ID", "Sample", "Condition", "ReplicateFileName"] diff --git a/assets/schema_search_presets.json b/assets/schema_search_presets.json new file mode 100644 index 00000000..91b85fc2 --- /dev/null +++ b/assets/schema_search_presets.json @@ -0,0 +1,125 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://raw.githubusercontent.com/nf-core/mhcquant/master/assets/schema_search_presets.json", + "title": "nf-core/mhcquant pipeline - params.search_presets schema", + "description": "Schema for the search parameter presets file provided with params.search_presets", + "type": "array", + "items": { + "type": "object", + "properties": { + "PresetName": { + "type": "string", + "pattern": "^[a-zA-Z0-9_]+$", + "errorMessage": "PresetName must contain only alphanumeric characters and underscores", + "meta": ["preset_name"] + }, + "PeptideMinLength": { + "type": "integer", + "minimum": 1, + "errorMessage": "PeptideMinLength must be a positive integer", + "meta": ["peptide_min_length"] + }, + "PeptideMaxLength": { + "type": "integer", + "minimum": 1, + "errorMessage": "PeptideMaxLength must be a positive integer", + "meta": ["peptide_max_length"] + }, + "PrecursorMassRange": { + "type": "string", + "pattern": "^\\d+:\\d+$", + "errorMessage": "PrecursorMassRange must be in format 'min:max' (e.g., '800:2500')", + "meta": ["digest_mass_range"] + }, + "PrecursorCharge": { + "type": "string", + "pattern": "^\\d+:\\d+$", + "errorMessage": "PrecursorCharge must be in format 'min:max' (e.g., '2:3')", + "meta": ["prec_charge"] + }, + "PrecursorMassTolerance": { + "type": "number", + "minimum": 0, + "errorMessage": "PrecursorMassTolerance must be a non-negative number", + "meta": ["precursor_mass_tolerance"] + }, + "PrecursorErrorUnit": { + "type": "string", + "enum": ["ppm", "Da"], + "errorMessage": "PrecursorErrorUnit must be either 'ppm' or 'Da'", + "meta": ["precursor_error_units"] + }, + "FragmentMassTolerance": { + "type": "number", + "minimum": 0, + "errorMessage": "FragmentMassTolerance must be a non-negative number", + "meta": ["fragment_mass_tolerance"] + }, + "FragmentBinOffset": { + "type": "number", + "minimum": 0, + "errorMessage": "FragmentBinOffset must be a non-negative number", + "meta": ["fragment_bin_offset"] + }, + "MS2PIPModel": { + "type": "string", + "enum": [ + "Immuno-HCD", + "timsTOF", + "CIDch2", + "HCD", + "CID", + "ITMS", + "iTRAQ", + "iTRAQphospho", + "TMT", + "HCDch2" + ], + "errorMessage": "MS2PIPModel must be a valid MS2PIP model name", + "meta": ["ms2pip_model"] + }, + "ActivationMethod": { + "type": "string", + "enum": ["ALL", "CID", "HCD", "ETD", "ECD", "EThcD", "ETciD"], + "errorMessage": "ActivationMethod must be one of: ALL, CID, HCD, ETD, ECD, EThcD, ETciD", + "meta": ["activation_method"] + }, + "Instrument": { + "type": "string", + "enum": ["high_res", "low_res"], + "errorMessage": "Instrument must be either 'high_res' or 'low_res'", + "meta": ["instrument"] + }, + "NumberMods": { + "type": "integer", + "minimum": 0, + "errorMessage": "NumberMods must be a non-negative integer", + "meta": ["number_mods"] + }, + "FixedMods": { + "type": "string", + "errorMessage": "FixedMods must be a comma-separated list of UNIMOD modification names", + "meta": ["fixed_mods"] + }, + "VariableMods": { + "type": "string", + "errorMessage": "VariableMods must be a comma-separated list of UNIMOD modification names", + "meta": ["variable_mods"] + } + }, + "required": [ + "PresetName", + "PeptideMinLength", + "PeptideMaxLength", + "PrecursorMassRange", + "PrecursorCharge", + "PrecursorMassTolerance", + "FragmentMassTolerance", + "FragmentBinOffset", + "MS2PIPModel", + "ActivationMethod", + "Instrument", + "NumberMods" + ] + } +} diff --git a/assets/search_presets.tsv b/assets/search_presets.tsv new file mode 100644 index 00000000..1f49d97e --- /dev/null +++ b/assets/search_presets.tsv @@ -0,0 +1,11 @@ +PresetName PeptideMinLength PeptideMaxLength PrecursorMassRange PrecursorCharge PrecursorMassTolerance PrecursorErrorUnit FragmentMassTolerance FragmentBinOffset MS2PIPModel ActivationMethod Instrument NumberMods FixedMods VariableMods +lumos_class1 8 14 800:2500 2:3 5 ppm 0.01 0.0 Immuno-HCD HCD high_res 3 Oxidation (M) +lumos_class2 8 30 800:5000 2:5 5 ppm 0.01 0.0 Immuno-HCD HCD high_res 5 Oxidation (M) +qe_class1 8 14 800:2500 2:3 5 ppm 0.01 0.0 Immuno-HCD HCD high_res 3 Oxidation (M) +qe_class2 8 30 800:5000 2:5 5 ppm 0.01 0.0 Immuno-HCD HCD high_res 5 Oxidation (M) +timstof_class1 8 14 800:2500 1:4 20 ppm 0.01 0.0 timsTOF CID high_res 3 Oxidation (M) +timstof_class2 8 30 800:5000 1:5 20 ppm 0.01 0.0 timsTOF CID high_res 5 Oxidation (M) +astral_class1 8 14 800:2500 2:3 5 ppm 0.01 0.0 Immuno-HCD HCD high_res 3 Oxidation (M) +astral_class2 8 30 800:5000 2:5 5 ppm 0.01 0.0 Immuno-HCD HCD high_res 5 Oxidation (M) +xl_class1 8 14 800:2500 2:3 5 ppm 0.50025 0.4 CIDch2 CID low_res 3 Oxidation (M) +xl_class2 8 30 800:5000 2:5 5 ppm 0.50025 0.4 CIDch2 CID low_res 5 Oxidation (M) diff --git a/bin/summarize_results.py b/bin/summarize_results.py index c63d5b83..6b8a692f 100755 --- a/bin/summarize_results.py +++ b/bin/summarize_results.py @@ -4,6 +4,7 @@ import pandas as pd import numpy as np +from pyopenms import AASequence from argparse import ArgumentParser import re from collections import Counter @@ -77,6 +78,15 @@ def parse_multiTSV(file_path): elif line.startswith("#UNASSIGNEDPEPTIDE"): unassigned_peptide_cols = line.strip().split('\t')[1:] + # Workaround for OpenMS 3.5.0 TextExporter bug (https://github.com/OpenMS/OpenMS/issues/9120): + # consensusXML export writes a phantom column in data rows between 'end' and 'FFId_category' + # that is missing from the header. Remove it to realign columns. + for rows, cols in [(peptide_rows, peptide_cols), (unassigned_peptide_rows, unassigned_peptide_cols)]: + if rows and len(rows[0]) > len(cols) and 'end' in cols: + extra_idx = cols.index('end') + 1 + for i, row in enumerate(rows): + rows[i] = row[:extra_idx] + row[extra_idx + 1:] + peptide_df = pd.DataFrame(peptide_rows, columns=peptide_cols) consensus_df = pd.DataFrame(consensus_rows, columns=consensus_cols) # Concatenate CONSENSUS and PEPTIDE columns @@ -87,6 +97,13 @@ def parse_multiTSV(file_path): df["psm"] = df["sequence"].map(psm) return df +def strip_modifications(seq_with_mods: str) -> str: + try: + aa_seq = AASequence.fromString(seq_with_mods) + return aa_seq.toUnmodifiedString() + except Exception as e: + logging.warning(f"Could not parse sequence {seq_with_mods}: {e}") + return seq_with_mods def process_file(file, prefix, quantify, keep_cols): """Extract all the relevant information and write it to a TSV file for the MultiQC report @@ -122,7 +139,7 @@ def process_file(file, prefix, quantify, keep_cols): # Remove modification information from the sequence column data["peptidoform"] = data["sequence"] - data["sequence"] = data["sequence"].apply(lambda seq: re.sub(r'\(.*?\)', '', seq)) + data["sequence"] = data["sequence"].apply(strip_modifications) # --------------------------------- # Length distribution plot @@ -150,6 +167,10 @@ def process_file(file, prefix, quantify, keep_cols): # Histograms # --------------------------------- + # Rename IM column to ion_mobility for readability + if "IM" in data.columns: + data.rename(columns={"IM": "ion_mobility"}, inplace=True) + histograms = [[data["mz"].astype(float), f"{prefix}_histogram_mz.csv"], [data["rt"].astype(float), f"{prefix}_histogram_rt.csv"], [data["score"].astype(float), f"{prefix}_histogram_scores.csv"]] @@ -161,6 +182,15 @@ 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') + # Generate ion mobility histogram if IM data is available (e.g., timsTOF) + if "ion_mobility" in data.columns: + im_values = data["ion_mobility"].astype(float) + hist, bin_edges = np.histogram(im_values, bins='auto') + with open(f"{prefix}_histogram_im.csv", "w") as f: + for i in range(len(bin_edges) - 1): + bin_midpoint = (bin_edges[i] + bin_edges[i + 1]) / 2 + f.write(f'{bin_midpoint},{hist[i]}\n') + # --------------------------------- # Box plots # --------------------------------- @@ -174,6 +204,10 @@ def process_file(file, prefix, quantify, keep_cols): header=False ) + # Add a column with unique protein accessions next to accessions + data.insert(data.columns.get_loc('accessions') + 1, 'unique_accessions', + data['accessions'].map(lambda x: ';'.join(dict.fromkeys(x.split(';'))))) + # Filter the columns down to a user-defined subset of columns if keep_cols: missing_columns = set(keep_cols) - set(data.columns) @@ -184,6 +218,10 @@ def process_file(file, prefix, quantify, keep_cols): regex_patterns = [r'^rt_', r'^mz_', r'^intensity_', r'^charge_'] for pattern in regex_patterns: keep_cols.extend([col for col in data.columns if re.match(pattern, col)]) + # Always include unique_accessions next to accessions + if 'accessions' in keep_cols and 'unique_accessions' not in keep_cols: + idx = keep_cols.index('accessions') + 1 + keep_cols.insert(idx, 'unique_accessions') # Remove duplicates while retaining order keep_cols = list(dict.fromkeys(keep_cols)) data = data.loc[:, keep_cols] @@ -192,9 +230,6 @@ def process_file(file, prefix, quantify, keep_cols): 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 9d0500d2..3c351c0f 100644 --- a/conf/base.config +++ b/conf/base.config @@ -63,6 +63,15 @@ process { memory = { 10.GB * task.attempt, 'memory' } time = { 16.h * task.attempt, 'time' } } + withName: 'PRIDEPY_FETCH_SDRF' { + errorStrategy = 'retry' + maxRetries = 3 + } + withName: 'PRIDEPY_DOWNLOAD_FILE' { + errorStrategy = 'retry' + maxRetries = 3 + maxForks = 5 + } withLabel: process_gpu { ext.use_gpu = { workflow.profile.contains('gpu') } accelerator = { workflow.profile.contains('gpu') ? 1 : null } diff --git a/conf/igenomes.config b/conf/igenomes.config deleted file mode 100644 index 3f114377..00000000 --- a/conf/igenomes.config +++ /dev/null @@ -1,440 +0,0 @@ -/* -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Nextflow config file for iGenomes paths -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Defines reference genomes using iGenome paths. - Can be used by any config that customises the base path using: - $params.igenomes_base / --igenomes_base ----------------------------------------------------------------------------------------- -*/ - -params { - // illumina iGenomes reference file paths - genomes { - 'GRCh37' { - fasta = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Homo_sapiens/Ensembl/GRCh37/Annotation/README.txt" - mito_name = "MT" - macs_gsize = "2.7e9" - blacklist = "${projectDir}/assets/blacklists/GRCh37-blacklist.bed" - } - 'GRCh38' { - fasta = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Homo_sapiens/NCBI/GRCh38/Annotation/Genes/genes.bed" - mito_name = "chrM" - macs_gsize = "2.7e9" - blacklist = "${projectDir}/assets/blacklists/hg38-blacklist.bed" - } - 'CHM13' { - fasta = "${params.igenomes_base}/Homo_sapiens/UCSC/CHM13/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Homo_sapiens/UCSC/CHM13/Sequence/BWAIndex/" - bwamem2 = "${params.igenomes_base}/Homo_sapiens/UCSC/CHM13/Sequence/BWAmem2Index/" - gtf = "${params.igenomes_base}/Homo_sapiens/NCBI/CHM13/Annotation/Genes/genes.gtf" - gff = "ftp://ftp.ncbi.nlm.nih.gov/genomes/all/GCF/009/914/755/GCF_009914755.1_T2T-CHM13v2.0/GCF_009914755.1_T2T-CHM13v2.0_genomic.gff.gz" - mito_name = "chrM" - } - 'GRCm38' { - fasta = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Mus_musculus/Ensembl/GRCm38/Annotation/README.txt" - mito_name = "MT" - macs_gsize = "1.87e9" - blacklist = "${projectDir}/assets/blacklists/GRCm38-blacklist.bed" - } - 'TAIR10' { - fasta = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Arabidopsis_thaliana/Ensembl/TAIR10/Annotation/README.txt" - mito_name = "Mt" - } - 'EB2' { - fasta = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Bacillus_subtilis_168/Ensembl/EB2/Annotation/README.txt" - } - 'UMD3.1' { - fasta = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Bos_taurus/Ensembl/UMD3.1/Annotation/README.txt" - mito_name = "MT" - } - 'WBcel235' { - fasta = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Caenorhabditis_elegans/Ensembl/WBcel235/Annotation/Genes/genes.bed" - mito_name = "MtDNA" - macs_gsize = "9e7" - } - 'CanFam3.1' { - fasta = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Canis_familiaris/Ensembl/CanFam3.1/Annotation/README.txt" - mito_name = "MT" - } - 'GRCz10' { - fasta = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Danio_rerio/Ensembl/GRCz10/Annotation/Genes/genes.bed" - mito_name = "MT" - } - 'BDGP6' { - fasta = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Drosophila_melanogaster/Ensembl/BDGP6/Annotation/Genes/genes.bed" - mito_name = "M" - macs_gsize = "1.2e8" - } - 'EquCab2' { - fasta = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Equus_caballus/Ensembl/EquCab2/Annotation/README.txt" - mito_name = "MT" - } - 'EB1' { - fasta = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Escherichia_coli_K_12_DH10B/Ensembl/EB1/Annotation/README.txt" - } - 'Galgal4' { - fasta = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Gallus_gallus/Ensembl/Galgal4/Annotation/Genes/genes.bed" - mito_name = "MT" - } - 'Gm01' { - fasta = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Glycine_max/Ensembl/Gm01/Annotation/README.txt" - } - 'Mmul_1' { - fasta = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Macaca_mulatta/Ensembl/Mmul_1/Annotation/README.txt" - mito_name = "MT" - } - 'IRGSP-1.0' { - fasta = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Oryza_sativa_japonica/Ensembl/IRGSP-1.0/Annotation/Genes/genes.bed" - mito_name = "Mt" - } - 'CHIMP2.1.4' { - fasta = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Pan_troglodytes/Ensembl/CHIMP2.1.4/Annotation/README.txt" - mito_name = "MT" - } - 'Rnor_5.0' { - fasta = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_5.0/Annotation/Genes/genes.bed" - mito_name = "MT" - } - 'Rnor_6.0' { - fasta = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Rattus_norvegicus/Ensembl/Rnor_6.0/Annotation/Genes/genes.bed" - mito_name = "MT" - } - 'R64-1-1' { - fasta = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Saccharomyces_cerevisiae/Ensembl/R64-1-1/Annotation/Genes/genes.bed" - mito_name = "MT" - macs_gsize = "1.2e7" - } - 'EF2' { - fasta = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Schizosaccharomyces_pombe/Ensembl/EF2/Annotation/README.txt" - mito_name = "MT" - macs_gsize = "1.21e7" - } - 'Sbi1' { - fasta = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Sorghum_bicolor/Ensembl/Sbi1/Annotation/README.txt" - } - 'Sscrofa10.2' { - fasta = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Sus_scrofa/Ensembl/Sscrofa10.2/Annotation/README.txt" - mito_name = "MT" - } - 'AGPv3' { - fasta = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Zea_mays/Ensembl/AGPv3/Annotation/Genes/genes.bed" - mito_name = "Mt" - } - 'hg38' { - fasta = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Homo_sapiens/UCSC/hg38/Annotation/Genes/genes.bed" - mito_name = "chrM" - macs_gsize = "2.7e9" - blacklist = "${projectDir}/assets/blacklists/hg38-blacklist.bed" - } - 'hg19' { - fasta = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Homo_sapiens/UCSC/hg19/Annotation/README.txt" - mito_name = "chrM" - macs_gsize = "2.7e9" - blacklist = "${projectDir}/assets/blacklists/hg19-blacklist.bed" - } - 'mm10' { - fasta = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Mus_musculus/UCSC/mm10/Annotation/README.txt" - mito_name = "chrM" - macs_gsize = "1.87e9" - blacklist = "${projectDir}/assets/blacklists/mm10-blacklist.bed" - } - 'bosTau8' { - fasta = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Bos_taurus/UCSC/bosTau8/Annotation/Genes/genes.bed" - mito_name = "chrM" - } - 'ce10' { - fasta = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Caenorhabditis_elegans/UCSC/ce10/Annotation/README.txt" - mito_name = "chrM" - macs_gsize = "9e7" - } - 'canFam3' { - fasta = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Canis_familiaris/UCSC/canFam3/Annotation/README.txt" - mito_name = "chrM" - } - 'danRer10' { - fasta = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Danio_rerio/UCSC/danRer10/Annotation/Genes/genes.bed" - mito_name = "chrM" - macs_gsize = "1.37e9" - } - 'dm6' { - fasta = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Drosophila_melanogaster/UCSC/dm6/Annotation/Genes/genes.bed" - mito_name = "chrM" - macs_gsize = "1.2e8" - } - 'equCab2' { - fasta = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Equus_caballus/UCSC/equCab2/Annotation/README.txt" - mito_name = "chrM" - } - 'galGal4' { - fasta = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Gallus_gallus/UCSC/galGal4/Annotation/README.txt" - mito_name = "chrM" - } - 'panTro4' { - fasta = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Pan_troglodytes/UCSC/panTro4/Annotation/README.txt" - mito_name = "chrM" - } - 'rn6' { - fasta = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Rattus_norvegicus/UCSC/rn6/Annotation/Genes/genes.bed" - mito_name = "chrM" - } - 'sacCer3' { - fasta = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Sequence/BismarkIndex/" - readme = "${params.igenomes_base}/Saccharomyces_cerevisiae/UCSC/sacCer3/Annotation/README.txt" - mito_name = "chrM" - macs_gsize = "1.2e7" - } - 'susScr3' { - fasta = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/WholeGenomeFasta/genome.fa" - bwa = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/BWAIndex/version0.6.0/" - bowtie2 = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/Bowtie2Index/" - star = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/STARIndex/" - bismark = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Sequence/BismarkIndex/" - gtf = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Annotation/Genes/genes.gtf" - bed12 = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Annotation/Genes/genes.bed" - readme = "${params.igenomes_base}/Sus_scrofa/UCSC/susScr3/Annotation/README.txt" - mito_name = "chrM" - } - } -} diff --git a/conf/igenomes_ignored.config b/conf/igenomes_ignored.config deleted file mode 100644 index b4034d82..00000000 --- a/conf/igenomes_ignored.config +++ /dev/null @@ -1,9 +0,0 @@ -/* -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Nextflow config file for iGenomes paths -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - Empty genomes dictionary to use when igenomes is ignored. ----------------------------------------------------------------------------------------- -*/ - -params.genomes = [:] diff --git a/conf/modules.config b/conf/modules.config index c5b93fae..c1121e11 100644 --- a/conf/modules.config +++ b/conf/modules.config @@ -94,20 +94,20 @@ process { ext.args = { [ (params.default_params_file_comet != " ") ? "-default_params_file ${params.default_params_file_comet}" : "", "-pin_out ${mzml.baseName}_pin.tsv", - "-instrument ${params.instrument}", + "-instrument ${meta.instrument}", "-spectrum_batch_size ${params.spectrum_batch_size}", - "-activation_method ${params.activation_method}", - "-precursor_mass_tolerance ${params.precursor_mass_tolerance}", - "-precursor_error_units ${params.precursor_error_units}", - "-fragment_mass_tolerance ${params.fragment_mass_tolerance}", - "-fragment_bin_offset ${params.fragment_bin_offset}", + "-activation_method ${meta.activation_method}", + "-precursor_mass_tolerance ${meta.precursor_mass_tolerance}", + "-precursor_error_units ${meta.precursor_error_units}", + "-fragment_mass_tolerance ${meta.fragment_mass_tolerance}", + "-fragment_bin_offset ${meta.fragment_bin_offset}", "-num_hits ${params.num_hits}", - "-digest_mass_range ${params.digest_mass_range}", - "-max_variable_mods_in_peptide ${params.number_mods}", + "-digest_mass_range ${meta.digest_mass_range}", + "-max_variable_mods_in_peptide ${meta.number_mods}", "-missed_cleavages 0", - "-precursor_charge ${params.prec_charge}", - "-fixed_modifications ${params.fixed_mods.tokenize(',').collect {"'${it}'"}.join(" ")}", - "-variable_modifications ${params.variable_mods.tokenize(',').collect {"'${it}'"}.join(" ")}", + "-precursor_charge ${meta.prec_charge}", + "-fixed_modifications ${meta.fixed_mods.trim() ? meta.fixed_mods.tokenize(',').collect { "'${it.trim()}'" }.join(' ') : ''}", + meta.variable_mods.trim() ? "-variable_modifications ${meta.variable_mods.tokenize(',').collect { "'${it.trim()}'" }.join(' ')}" : "", "-enzyme '${params.enzyme}'", "-use_X_ions ${params.use_x_ions}", "-use_Z_ions ${params.use_z_ions}", @@ -156,12 +156,12 @@ process { withName: 'OPENMS_IDFILTER_Q_VALUE' { ext.prefix = {"${meta.id}_pout_filtered"} - ext.args = [ + ext.args = { [ "-remove_decoys", - "-precursor:length '${params.peptide_min_length}:${params.peptide_max_length}'", + "-precursor:length '${meta.peptide_min_length}:${meta.peptide_max_length}'", "-delete_unreferenced_peptide_hits", (params.fdr_threshold == '0.01') ? "-score:peptide 0.05" : "-score:peptide " + params.fdr_threshold - ].join(' ').trim() + ].join(' ').trim() } publishDir = [ path: {"${params.outdir}/intermediate_results/rescoring"}, mode: params.publish_dir_mode, @@ -172,12 +172,12 @@ process { withName: 'OPENMS_IDFILTER_Q_VALUE_GLOBAL' { label = 'process_high_memory' ext.prefix = {"${meta.id}_pout_filtered"} - ext.args = [ + ext.args = { [ "-remove_decoys", - "-precursor:length '${params.peptide_min_length}:${params.peptide_max_length}'", + "-precursor:length '${meta.peptide_min_length}:${meta.peptide_max_length}'", "-delete_unreferenced_peptide_hits", (params.fdr_threshold == '0.01') ? "-score:peptide 0.05" : "-score:peptide " + params.fdr_threshold - ].join(' ').trim() + ].join(' ').trim() } publishDir = [ enabled: false ] @@ -186,12 +186,12 @@ process { withName: 'OPENMS_IDFILTER_GLOBAL' { label = 'process_medium' ext.prefix = {"${meta.id}_pout_filtered"} - ext.args = [ + ext.args = { [ "-remove_decoys", - "-precursor:length '${params.peptide_min_length}:${params.peptide_max_length}'", + "-precursor:length '${meta.peptide_min_length}:${meta.peptide_max_length}'", "-delete_unreferenced_peptide_hits", (params.fdr_threshold == '0.01') ? "-score:peptide 0.05" : "-score:peptide " + params.fdr_threshold - ].join(' ').trim() + ].join(' ').trim() } publishDir = [ path: {"${params.outdir}/intermediate_results/rescoring"}, mode: params.publish_dir_mode, @@ -255,6 +255,12 @@ process { ] } + withName: 'OPENMS_FILECONVERTER' { + publishDir = [ + enabled: false + ] + } + withName: 'MULTIQC' { ext.args = { params.multiqc_title ? "--title \"$params.multiqc_title\"" : '' } publishDir = [ @@ -309,6 +315,27 @@ process { process { + withName: 'SDRF_PIPELINES_PARSE_SDRF' { + publishDir = [ + path: {"${params.outdir}/sdrf"}, + mode: params.publish_dir_mode, + pattern: '*.tsv' + ] + } + + withName: 'PRIDEPY_FETCH_SDRF' { + publishDir = [ + path: {"${params.outdir}/sdrf"}, + mode: params.publish_dir_mode, + pattern: '*.sdrf.tsv' + ] + } + + withName: 'PRIDEPY_DOWNLOAD_FILE' { + ext.args = '-p ftp' + publishDir = [enabled: false] + } + withName: 'TDF2MZML' { publishDir = [ enabled: false @@ -342,23 +369,23 @@ process { withName: 'OPENMS_IDMASSACCURACY' { ext.prefix = {"${meta.spectra}"} - ext.args = [ + ext.args = { [ (params.precursor_error_units == 'ppm') ? "-precursor_error_ppm": "", - "-fragment_mass_tolerance ${params.fragment_mass_tolerance}" - ].join(' ').trim() + "-fragment_mass_tolerance ${meta.fragment_mass_tolerance}" + ].join(' ').trim() } publishDir = [ enabled: false ] } withName: 'MS2RESCORE' { - ext.args = [ - "--ms2_tolerance ${2 * params.fragment_mass_tolerance}", - "--ms2pip_model ${params.ms2pip_model}", + ext.args = { [ + "--ms2_tolerance ${2 * (meta.fragment_mass_tolerance as double)}", + "--ms2pip_model ${meta.ms2pip_model}", "--ms2pip_model_dir ${params.ms2pip_model_dir}", "--rescoring_engine ${params.rescoring_engine}", params.feature_generators.trim() ? "--feature_generators ${params.feature_generators}" : '' - ].join(' ').trim() + ].join(' ').trim() } publishDir = [ [path: "${params.outdir}/intermediate_results/rescoring", mode: params.publish_dir_mode, @@ -389,15 +416,16 @@ process { withName: 'OPENMS_PERCOLATORADAPTER_GLOBAL' { label = 'process_high_mem_high_cpu' - ext.args = [ + ext.args = { [ "-seed 4711", "-trainFDR 0.05", "-testFDR 0.05", "-enzyme no_enzyme", "-subset_max_train ${params.subset_max_train}", "-post_processing_tdc", + "-weights ${meta.id}_percolator_feature_weights.tsv", (params.fdr_level != 'psm_level_fdrs') ? "-" + params.fdr_level : "" - ].join(' ').trim() + ].join(' ').trim() } publishDir = [ enabled: false ] @@ -442,6 +470,7 @@ process { } withName: 'OPENMS_TEXTEXPORTER' { + ext.args = '-id:peptides_only -id:add_hit_metavalues 0 -id:add_metavalues 0' publishDir = [ enabled: false ] @@ -466,7 +495,7 @@ process { "observed_retention_time_best", "predicted_retention_time_best", "spec_pearson", "std_abs_diff", - "ccs_observed_im2deep", "ccs_predicted_im2deep", "ccs_error_im2deep" + "ccs_predicted_im2deep", "ccs_error_im2deep", "ion_mobility" ].join(',').trim(), ].join(' ').trim() publishDir = [ @@ -520,11 +549,11 @@ process { if (params.annotate_ions) { withName: 'PYOPENMS_IONANNOTATOR' { - ext.args = [ - "--precursor_charge ${params.prec_charge}", - "--fragment_mass_tolerance ${params.fragment_mass_tolerance}", + ext.args = { [ + "--precursor_charge ${meta.prec_charge}", + "--fragment_mass_tolerance ${meta.fragment_mass_tolerance}", "--remove_precursor_peak ${params.remove_precursor_peak}" - ].join(' ').trim() + ].join(' ').trim() } publishDir = [ path: {"${params.outdir}/intermediate_results/ion_annotations"}, mode: params.publish_dir_mode, diff --git a/conf/test_full.config b/conf/test_full.config index 4fc59bc5..e9215ae2 100644 --- a/conf/test_full.config +++ b/conf/test_full.config @@ -25,5 +25,4 @@ params { quantify = true generate_speclib = true annotate_ions = true - epicore = true } diff --git a/conf/test_sdrf.config b/conf/test_sdrf.config new file mode 100644 index 00000000..0b8a98ac --- /dev/null +++ b/conf/test_sdrf.config @@ -0,0 +1,33 @@ +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Nextflow config file for running SDRF/PRIDE input tests +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Defines input files and everything required to run a minimal test using an SDRF + sheet as --input. The pipeline fetches the RAW files from PRIDE and converts the + SDRF to a samplesheet + search presets before running the standard workflow. + + Use as follows: + nextflow run nf-core/mhcquant -profile test_sdrf, --outdir + +---------------------------------------------------------------------------------------- +*/ + +process { + resourceLimits = [ + cpus: 2, + memory: '6.GB', + time: '2.h' + ] +} + +params { + config_profile_name = 'SDRF test profile' + config_profile_description = 'Minimal SDRF input test dataset to check pipeline function' + + // Input data + input = params.pipelines_testdata_base_path + 'mhcquant/testdata/PXD009752.sdrf.tsv' + fasta = params.pipelines_testdata_base_path + 'mhcquant/testdata/UP000005640_9606_500prot.fasta' + + // Batch spectra during Comet search to fit within CI memory limits + spectrum_batch_size = 20000 +} diff --git a/conf/test_search_presets.config b/conf/test_search_presets.config new file mode 100644 index 00000000..1dff0844 --- /dev/null +++ b/conf/test_search_presets.config @@ -0,0 +1,29 @@ +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Nextflow config file for running tests with search parameter presets +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + Defines input files and everything required to run a test with different + search parameter presets specified per sample in the samplesheet. + + Use as follows: + nextflow run main.nf -profile test_search_presets, --outdir + +---------------------------------------------------------------------------------------- +*/ + +process { + resourceLimits = [ + cpus: 4, + memory: '15.GB', + time: '6.h' + ] +} + +params { + config_profile_name = 'Test search presets profile' + config_profile_description = 'Minimal test dataset with search parameter presets' + + // Input data + input = 'https://raw.githubusercontent.com/nf-core/test-datasets/mhcquant/testdata/sample_sheet_presets.tsv' + fasta = params.pipelines_testdata_base_path + 'mhcquant/testdata/UP000005640_9606.fasta' +} diff --git a/conf/test_single_quant.config b/conf/test_single_quant.config new file mode 100644 index 00000000..f9033cfd --- /dev/null +++ b/conf/test_single_quant.config @@ -0,0 +1,24 @@ +/* + * ---------------------------------------------------------------------------- + * Nextflow config file for running tests + * ---------------------------------------------------------------------------- + * Defines bundled input files and everything required to run a fast and simple + * pipeline test. Use as follows: + * nextflow run main.nf -profile test_single_quant, + * */ + +params { + config_profile_name = 'Test single replicate profile' + config_profile_description = 'Test dataset to check pipeline function for single replicate' + + // Limit resources so that this can run on GitHub Actions + max_cpus = 2 + max_memory = '6.GB' + max_time = '6.h' + + // Input data + input = params.pipelines_testdata_base_path + 'mhcquant/testdata/sample_sheet_single_quant.tsv' + + // Pipeline settings + quantify = true +} diff --git a/docs/usage.md b/docs/usage.md index b90afdba..993f0b5b 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -4,6 +4,21 @@ > _Documentation of pipeline parameters is generated automatically from the pipeline schema and can no longer be found in markdown files._ +## Input modes + +The `--input` parameter accepts three formats: + +| Mode | Example | Description | +| ------------------- | ----------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| **Samplesheet TSV** | `--input samplesheet.tsv` | A local TSV file listing your MS runs (see [Samplesheet input](#samplesheet-input)). | +| **SDRF file** | `--input experiment.sdrf.tsv` | A local [SDRF-Proteomics](https://github.com/bigbio/proteomics-sample-metadata) file following the [immunopeptidomics template](https://github.com/bigbio/proteomics-sample-metadata/tree/master/templates). Raw files are fetched from PRIDE, search settings and sample metadata are parsed from the SDRF. Requires `--fasta`. | +| **PRIDE accession** | `--input PXD009752` | A PRIDE project accession. The project must include an SDRF file following the [immunopeptidomics template](https://github.com/bigbio/proteomics-sample-metadata/tree/master/templates); both the SDRF and raw files are fetched from PRIDE. Requires `--fasta`. | + +For the SDRF and PRIDE accession modes, the pipeline uses [sdrf-pipelines](https://github.com/bigbio/sdrf-pipelines) to translate the SDRF into an mhcquant samplesheet and a search-preset table, then downloads the raw files with [pridepy](https://github.com/bigbio/py-pride-archive-client). The generated samplesheet and presets are published under `/sdrf/` for transparency. + +> [!NOTE] +> SDRF files must follow the immunopeptidomics template from [bigbio/proteomics-sample-metadata](https://github.com/bigbio/proteomics-sample-metadata/tree/master/templates), and PRIDE accessions must point to a project that contains such an SDRF file — otherwise sample metadata and search parameters cannot be derived. When providing a local `.sdrf.tsv`, the PRIDE accession is inferred from the filename (e.g. `PXD009752.sdrf.tsv`); if your SDRF is named differently, pass the accession via `--input PXD...` instead. + ## 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 at least four columns, and a header row as shown in the examples below. @@ -14,13 +29,14 @@ You will need to create a samplesheet with information about the samples you wou ### Samplesheet columns -| Column | Description | -| ------------------- | ----------------------------------------------------------------------------------------------------- | -| `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 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 | +| Column | Required | Description | +| ------------------- | -------- | ----------------------------------------------------------------------------------------------------- | +| `ID` | Yes | An incrementing value which acts as a unique number for the given sample | +| `Sample` | Yes | Custom sample name. This entry will be identical for multiple MS runs from the same sample. | +| `Condition` | Yes | Additional information of the sample can be defined here. | +| `ReplicateFileName` | Yes | Full path to the MS file. These files have the extensions .raw, .mzML, mzML.gz, .d, .d.tar.gz, .d.zip | +| `Fasta` | No | Full path to the FASTA file. These files have the extensions .fasta, .fa, .fas, .fna, .faa, .ffn | +| `SearchPreset` | No | Name of a search parameter preset (see [Search presets](#search-presets)) | > [!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. @@ -45,6 +61,46 @@ ID Sample Condition ReplicateFileName 8 control untreated /path/to/msrun8.raw|mzML|d ``` +### Search presets + +When processing data from different instruments or MHC classes in a single run, you can use the `SearchPreset` column to assign a named set of search parameters to each sample. This avoids having to specify each parameter individually per row. + +Available presets: + +| Preset | Instrument | MHC Class | Peptide Length | Mass Range | Charge | Precursor Tol. | Fragment Tol. | MS2PIP Model | +| ---------------- | --------------------- | --------- | -------------- | ---------- | ------ | -------------- | ------------- | ------------ | +| `lumos_class1` | Orbitrap Fusion Lumos | I | 8-14 | 800:2500 | 2:3 | 5 ppm | 0.01 Da | Immuno-HCD | +| `lumos_class2` | Orbitrap Fusion Lumos | II | 8-30 | 800:5000 | 2:5 | 5 ppm | 0.01 Da | Immuno-HCD | +| `qe_class1` | Q Exactive | I | 8-14 | 800:2500 | 2:3 | 5 ppm | 0.01 Da | Immuno-HCD | +| `qe_class2` | Q Exactive | II | 8-30 | 800:5000 | 2:5 | 5 ppm | 0.01 Da | Immuno-HCD | +| `timstof_class1` | timsTOF | I | 8-14 | 800:2500 | 1:4 | 20 ppm | 0.01 Da | timsTOF | +| `timstof_class2` | timsTOF | II | 8-30 | 800:5000 | 1:5 | 20 ppm | 0.01 Da | timsTOF | +| `xl_class1` | LTQ Orbitrap XL | I | 8-14 | 800:2500 | 2:3 | 5 ppm | 0.50025 Da | CIDch2 | +| `xl_class2` | LTQ Orbitrap XL | II | 8-30 | 800:5000 | 2:5 | 5 ppm | 0.50025 Da | CIDch2 | + +Example samplesheet with presets: + +```tsv title="samplesheet.tsv" +ID Sample Condition ReplicateFileName SearchPreset +1 lumos_sample A /path/to/lumos_run1.raw lumos_class1 +2 lumos_sample A /path/to/lumos_run2.raw lumos_class1 +3 timstof_sample B /path/to/timstof_run1.d timstof_class2 +4 timstof_sample B /path/to/timstof_run2.d timstof_class2 +``` + +### Parameter precedence + +Search parameters are resolved with the following precedence (highest to lowest): + +1. **Command-line parameters** (e.g. `--fragment_mass_tolerance 0.05`) -- CLI overrides take highest priority and apply to all samples +2. **Search preset** (e.g. `SearchPreset: lumos_class1`) -- preset values fill in any parameters not specified via CLI +3. **Config defaults** (`nextflow.config`) -- built-in defaults are used as a final fallback + +This means a CLI flag like `--fragment_mass_tolerance 0.05` will override all presets for that parameter. + +> [!NOTE] +> When using `--global_fdr`, samples sharing the same `SearchPreset` value are grouped together for global FDR estimation. Samples without a preset are grouped under a common `global` group. + ## Recommended search settings Fine-tuning search settings is important to obtain the most optimal results for your MS data. _These settings heavily depend on the MS instrument settings used to generate the data_. If you want to reprocess public data, make sure you use the settings mentioned in the methods section! The following table acts as an orientation of commonly used search settings for instruments: @@ -59,7 +115,7 @@ Fine-tuning search settings is important to obtain the most optimal results for | precursor_error_units | ppm | ppm | ppm | ppm | ppm | ppm | ppm | ppm | | number_mods | 3 | 5 | 3 | 5 | 3 | 5 | 3 | 5 | | precursor_mass_tolerance | 20 | 20 | 5 | 5 | 5 | 5 | 5 | 5 | -| fragment_mass_tolerance | 0.02 | 0.02 | 0.02 | 0.02 | 0.02 | 0.02 | 0.50025 | 0.50025 | +| fragment_mass_tolerance | 0.01 | 0.01 | 0.01 | 0.01 | 0.01 | 0.01 | 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.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)'`. diff --git a/main.nf b/main.nf index 5067acde..8c309076 100644 --- a/main.nf +++ b/main.nf @@ -18,7 +18,6 @@ include { MHCQUANT } from './workflows/mhcquant' include { PIPELINE_INITIALISATION } from './subworkflows/local/utils_nfcore_mhcquant_pipeline' include { PIPELINE_COMPLETION } from './subworkflows/local/utils_nfcore_mhcquant_pipeline' - /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ NAMED WORKFLOWS FOR PIPELINE diff --git a/modules.json b/modules.json index 32f6f4c5..4d2cd03e 100644 --- a/modules.json +++ b/modules.json @@ -7,67 +7,62 @@ "nf-core": { "gunzip": { "branch": "master", - "git_sha": "41dfa3f7c0ffabb96a6a813fe321c6d1cc5b6e46", + "git_sha": "96c57dfd98a0641886a67bd449fe33ee2ec0e374", "installed_by": ["modules"] }, "multiqc": { "branch": "master", - "git_sha": "e10b76ca0c66213581bec2833e30d31f239dec0b", + "git_sha": "5bdb098216aaf5df9c3b6343e6204cd932503c16", "installed_by": ["modules"] }, "openms/decoydatabase": { "branch": "master", - "git_sha": "0c47e4193ddde2c5edbc206b5420cbcbee5c9797", + "git_sha": "ca1cd2456f36c913fb3cfb6bdfbf9d1794fd493b", "installed_by": ["modules"] }, "openms/filefilter": { "branch": "master", - "git_sha": "0c47e4193ddde2c5edbc206b5420cbcbee5c9797", + "git_sha": "ca1cd2456f36c913fb3cfb6bdfbf9d1794fd493b", "installed_by": ["modules"] }, "openms/idfilter": { "branch": "master", - "git_sha": "0c47e4193ddde2c5edbc206b5420cbcbee5c9797", - "installed_by": ["modules"] - }, - "openms/idmassaccuracy": { - "branch": "master", - "git_sha": "0c47e4193ddde2c5edbc206b5420cbcbee5c9797", + "git_sha": "ca1cd2456f36c913fb3cfb6bdfbf9d1794fd493b", "installed_by": ["modules"] }, "openms/idmerger": { "branch": "master", - "git_sha": "0c47e4193ddde2c5edbc206b5420cbcbee5c9797", + "git_sha": "ca1cd2456f36c913fb3cfb6bdfbf9d1794fd493b", "installed_by": ["modules"] }, "openms/idripper": { "branch": "master", - "git_sha": "0c47e4193ddde2c5edbc206b5420cbcbee5c9797", + "git_sha": "ca1cd2456f36c913fb3cfb6bdfbf9d1794fd493b", "installed_by": ["modules"] }, "openms/idscoreswitcher": { "branch": "master", - "git_sha": "0c47e4193ddde2c5edbc206b5420cbcbee5c9797", + "git_sha": "ca1cd2456f36c913fb3cfb6bdfbf9d1794fd493b", "installed_by": ["modules"] }, "openms/peakpickerhires": { "branch": "master", - "git_sha": "0c47e4193ddde2c5edbc206b5420cbcbee5c9797", + "git_sha": "ca1cd2456f36c913fb3cfb6bdfbf9d1794fd493b", "installed_by": ["modules"] }, "openms/peptideindexer": { "branch": "master", - "git_sha": "0c47e4193ddde2c5edbc206b5420cbcbee5c9797", + "git_sha": "ca1cd2456f36c913fb3cfb6bdfbf9d1794fd493b", "installed_by": ["modules"] }, "openmsthirdparty/cometadapter": { "branch": "master", - "git_sha": "0c47e4193ddde2c5edbc206b5420cbcbee5c9797", + "git_sha": "ca1cd2456f36c913fb3cfb6bdfbf9d1794fd493b", "installed_by": ["modules"] }, "thermorawfileparser": { "branch": "master", - "git_sha": "41dfa3f7c0ffabb96a6a813fe321c6d1cc5b6e46", + "git_sha": "daaecc3478d6f6ad9cb8f48ec7d657ab6c67877f", "installed_by": ["modules"] } } @@ -81,7 +76,7 @@ }, "utils_nfcore_pipeline": { "branch": "master", - "git_sha": "05954dab2ff481bcb999f24455da29a5828af08d", + "git_sha": "271e7fc14eb1320364416d996fb077421f3faed2", "installed_by": ["subworkflows"] }, "utils_nfschema_plugin": { diff --git a/modules/local/easypqp/convert/environment.yml b/modules/local/easypqp/convert/environment.yml index a4d3cedd..4600dae6 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.53 + - bioconda::easypqp=0.1.57 diff --git a/modules/local/easypqp/convert/main.nf b/modules/local/easypqp/convert/main.nf index 45387cdc..927e7523 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.53--pyhdfd78af_0' : - 'biocontainers/easypqp:0.1.53--pyhdfd78af_0' }" + 'https://depot.galaxyproject.org/singularity/easypqp:0.1.57--pyhdfd78af_1' : + 'biocontainers/easypqp:0.1.57--pyhdfd78af_1' }" input: tuple val(meta), path(pepxml), path(spectra) @@ -14,7 +14,7 @@ process EASYPQP_CONVERT { output: tuple val(meta), path("*.psmpkl") , emit: psmpkl tuple val(meta), path("*.peakpkl"), emit: peakpkl - path "versions.yml" , emit: versions + tuple val("${task.process}"), val('easypqp'), eval("easypqp --version 2>&1 | grep -oP '(?<=easypqp, version )\\d+\\.\\d+\\.\\d+'"), topic: versions when: task.ext.when == null || task.ext.when @@ -32,11 +32,6 @@ process EASYPQP_CONVERT { --spectra $spectra \\ --unimod $unimod \\ $args - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - easypqp: \$(easypqp --version 2>&1 | grep -oP '(?<=easypqp, version )\\d+\\.\\d+\\.\\d+') - END_VERSIONS """ stub: @@ -49,10 +44,5 @@ process EASYPQP_CONVERT { touch "${prefix}.psmpkl" touch "${prefix}.peakpkl" - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - easypqp: \$(easypqp --version 2>&1 | grep -oP '(?<=easypqp, version )\\d+\\.\\d+\\.\\d+') - END_VERSIONS """ } diff --git a/modules/local/easypqp/library/environment.yml b/modules/local/easypqp/library/environment.yml index a4d3cedd..4600dae6 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.53 + - bioconda::easypqp=0.1.57 diff --git a/modules/local/easypqp/library/main.nf b/modules/local/easypqp/library/main.nf index 6f720fb1..f20b3940 100644 --- a/modules/local/easypqp/library/main.nf +++ b/modules/local/easypqp/library/main.nf @@ -4,15 +4,15 @@ 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.53--pyhdfd78af_0' : - 'biocontainers/easypqp:0.1.53--pyhdfd78af_0' }" + 'https://depot.galaxyproject.org/singularity/easypqp:0.1.57--pyhdfd78af_1' : + 'biocontainers/easypqp:0.1.57--pyhdfd78af_1' }" input: tuple val(meta), path(psmpkl), path(peakpkl) output: tuple val(meta), path("*.tsv") , emit: tsv - path "versions.yml" , emit: versions + tuple val("${task.process}"), val('easypqp'), eval("easypqp --version 2>&1 | grep -oP '(?<=easypqp, version )\\d+\\.\\d+\\.\\d+'"), topic: versions when: task.ext.when == null || task.ext.when @@ -30,11 +30,6 @@ process EASYPQP_LIBRARY { --out ${prefix}_speclib.tsv \ $args \ $psmpkl $peakpkl - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - easypqp: \$(easypqp --version 2>&1 | grep -oP '(?<=easypqp, version )\\d+\\.\\d+\\.\\d+') - END_VERSIONS """ stub: @@ -46,10 +41,5 @@ process EASYPQP_LIBRARY { mkdir -p \$MPLCONFIGDIR \$XDG_CACHE_HOME touch "${prefix}_speclib.tsv" - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - easypqp: \$(easypqp --version 2>&1 | grep -oP '(?<=easypqp, version )\\d+\\.\\d+\\.\\d+') - END_VERSIONS """ } diff --git a/modules/local/epicore/main.nf b/modules/local/epicore/main.nf index a04efff9..8ffb729e 100644 --- a/modules/local/epicore/main.nf +++ b/modules/local/epicore/main.nf @@ -16,7 +16,7 @@ process EPICORE { 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 + tuple val("${task.process}"), val('epicore'), eval("echo \$(epicore --version) | grep 'epicore' | cut -d ' ' -f3 | cut -c2-"), topic: versions script: def args = task.ext.args ?: '' @@ -32,11 +32,6 @@ process EPICORE { # 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: @@ -47,10 +42,5 @@ process EPICORE { 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/main.nf b/modules/local/ms2rescore/main.nf index 06fcb72a..75f4c2c0 100644 --- a/modules/local/ms2rescore/main.nf +++ b/modules/local/ms2rescore/main.nf @@ -17,7 +17,7 @@ process MS2RESCORE { tuple val(meta), path("*ms2rescore.idXML") , emit: idxml tuple val(meta), path("*feature_names.tsv"), emit: feature_names tuple val(meta), path("*.html" ) , optional:true, emit: html - path "versions.yml" , emit: versions + tuple val("${task.process}"), val('MS2Rescore'), eval("echo \"\$(ms2rescore --version 2>&1)\" | grep -oP 'MS²Rescore \\(v\\K[^\\)]+'"), topic: versions when: task.ext.when == null || task.ext.when @@ -33,11 +33,6 @@ process MS2RESCORE { --output_path ${prefix}.idXML \\ --processes $task.cpus \\ $args - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - MS²Rescore: \$(echo \$(ms2rescore --version 2>&1) | grep -oP 'MS²Rescore \\(v\\K[^\\)]+' )) - END_VERSIONS """ stub: @@ -47,10 +42,5 @@ process MS2RESCORE { touch ${prefix}.idXML touch ${meta.id}_feature_names.tsv touch ${meta.id}.html - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - MS²Rescore: \$(echo \$(ms2rescore --version 2>&1) | grep -oP 'MS²Rescore \\(v\\K[^\\)]+' )) - END_VERSIONS """ } diff --git a/modules/local/openms/featurefinderidentification/main.nf b/modules/local/openms/featurefinderidentification/main.nf index 794455ec..9630331d 100644 --- a/modules/local/openms/featurefinderidentification/main.nf +++ b/modules/local/openms/featurefinderidentification/main.nf @@ -13,27 +13,23 @@ process OPENMS_FEATUREFINDERIDENTIFICATION { output: tuple val(meta), path("*.featureXML"), emit: featurexml - path "versions.yml" , emit: versions + tuple val("${task.process}"), val('openms'), eval("FileInfo --help 2>&1 | grep -E '^Version' | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//'"), topic: versions when: task.ext.when == null || task.ext.when script: def prefix = task.ext.prefix ?: "${meta.id}_${meta.sample}_${meta.condition}" - def args = task.ext.args ?: '' def quant_fdr = params.quantification_fdr ? "-id $id_int -id_ext $id_ext -svm:min_prob ${params.quantification_min_prob}" : "-id $id_ext" - args = args + " $quant_fdr" + def args = quant_fdr + args = args + (task.ext.args ? " ${task.ext.args}" : '') """ - FeatureFinderIdentification -in $mzml \\ + FeatureFinderIdentification \\ + -in $mzml \\ -out ${prefix}.featureXML \\ -threads $task.cpus \\ $args - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') - END_VERSIONS """ stub: @@ -41,10 +37,5 @@ process OPENMS_FEATUREFINDERIDENTIFICATION { """ touch ${prefix}.featureXML - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') - END_VERSIONS """ } diff --git a/modules/local/openms/fileconverter/environment.yml b/modules/local/openms/fileconverter/environment.yml new file mode 100644 index 00000000..e9ab2df5 --- /dev/null +++ b/modules/local/openms/fileconverter/environment.yml @@ -0,0 +1,7 @@ +name: openms_fileconverter +channels: + - conda-forge + - bioconda + - defaults +dependencies: + - bioconda::openms=3.4.1 diff --git a/modules/local/openms/fileconverter/main.nf b/modules/local/openms/fileconverter/main.nf new file mode 100644 index 00000000..f4a5a885 --- /dev/null +++ b/modules/local/openms/fileconverter/main.nf @@ -0,0 +1,36 @@ +process OPENMS_FILECONVERTER { + 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/openms:3.4.1--h81ffffe_1' : + 'biocontainers/openms:3.4.1--h81ffffe_1' }" + + input: + tuple val(meta), path(file), val(suffix) + + output: + tuple val(meta), path("*.${suffix}"), emit: consensusxml + tuple val("${task.process}"), val('openms'), eval("FileInfo --help 2>&1 | sed -nE 's/^Version: ([0-9.]+).*/\1/p'"), topic: versions + + when: + task.ext.when == null || task.ext.when + + script: + def prefix = task.ext.prefix ?: "${meta.id}" + + """ + FileConverter \\ + -in $file \\ + -out ${prefix}.${suffix} \\ + -threads $task.cpus + """ + + stub: + def prefix = task.ext.prefix ?: "${meta.id}" + + """ + touch ${prefix}.${suffix} + """ +} diff --git a/modules/local/openms/idconflictresolver/main.nf b/modules/local/openms/idconflictresolver/main.nf index 9228ee81..4a77cfbd 100644 --- a/modules/local/openms/idconflictresolver/main.nf +++ b/modules/local/openms/idconflictresolver/main.nf @@ -12,7 +12,7 @@ process OPENMS_IDCONFLICTRESOLVER { output: tuple val(meta), path("*.consensusXML"), emit: consensusxml - path "versions.yml" , emit: versions + tuple val("${task.process}"), val('openms'), eval("FileInfo --help 2>&1 | grep -E '^Version' | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//'"), topic: versions when: task.ext.when == null || task.ext.when @@ -25,11 +25,6 @@ process OPENMS_IDCONFLICTRESOLVER { -in $consensus \\ -out ${prefix}.consensusXML \\ -threads $task.cpus - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') - END_VERSIONS """ stub: @@ -37,10 +32,5 @@ process OPENMS_IDCONFLICTRESOLVER { """ touch ${prefix}.consensusXML - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') - END_VERSIONS """ } diff --git a/modules/nf-core/openms/idmassaccuracy/environment.yml b/modules/local/openms/idmassaccuracy/environment.yml similarity index 100% rename from modules/nf-core/openms/idmassaccuracy/environment.yml rename to modules/local/openms/idmassaccuracy/environment.yml diff --git a/modules/nf-core/openms/idmassaccuracy/main.nf b/modules/local/openms/idmassaccuracy/main.nf similarity index 72% rename from modules/nf-core/openms/idmassaccuracy/main.nf rename to modules/local/openms/idmassaccuracy/main.nf index 819720e2..d601ead7 100644 --- a/modules/nf-core/openms/idmassaccuracy/main.nf +++ b/modules/local/openms/idmassaccuracy/main.nf @@ -13,7 +13,7 @@ process OPENMS_IDMASSACCURACY { output: tuple val(meta), path("*frag_mass_err.tsv") , emit: frag_err tuple val(meta), path("*prec_mass_err.tsv") , emit: prec_err, optional: true - path "versions.yml" , emit: versions + tuple val("${task.process}"), val('openms'), eval("FileInfo --help 2>&1 | sed -nE 's/^Version: ([0-9.]+).*/\\1/p'"), topic: versions when: task.ext.when == null || task.ext.when @@ -29,11 +29,6 @@ process OPENMS_IDMASSACCURACY { -out_fragment ${prefix}_frag_mass_err.tsv \\ -threads $task.cpus \\ $args - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - OpenMS: \$(FileInfo 2>&1 | grep -E '^Version(.*)' | cut -d ' ' -f 2 | cut -d '-' -f 1) - END_VERSIONS """ stub: @@ -43,10 +38,5 @@ process OPENMS_IDMASSACCURACY { """ touch ${prefix}_frag_mass_err.tsv touch ${prefix}_prec_mass_err.tsv - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - OpenMS: \$(FileInfo 2>&1 | grep -E '^Version(.*)' | cut -d ' ' -f 2 | cut -d '-' -f 1) - END_VERSIONS """ } diff --git a/modules/local/openms/idmassaccuracy/meta.yml b/modules/local/openms/idmassaccuracy/meta.yml new file mode 100644 index 00000000..ce2eeb82 --- /dev/null +++ b/modules/local/openms/idmassaccuracy/meta.yml @@ -0,0 +1,63 @@ +name: "openms_idfilter" +description: Filters peptide/protein identification results by different + criteria. +keywords: + - filter + - idXML + - openms + - proteomics +tools: + - "openms": + description: "OpenMS is an open-source software C++ library for LC-MS data management + and analyses" + homepage: "https://openms.de" + documentation: "https://openms.readthedocs.io/en/latest/index.html" + tool_dev_url: "https://github.com/OpenMS/OpenMS" + doi: "10.1038/s41592-024-02197-7" + licence: ["BSD"] + identifier: "" + +input: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'test', single_end:false ]` + - id_file: + 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: + type: map + description: | + Groovy Map containing sample information + e.g. `[ id:'test', single_end:false ]` + - "*.{idXML,consensusXML}": + type: file + description: Filtered peptide-spectrum matches. + pattern: "*.{idXML,consensusXML}" + ontologies: [] +topics: + versions: + - - ${task.process}: + type: string + description: The name of the process + - openms: + type: string + description: The name of the tool + - "FileInfo --help 2>&1 | sed -nE 's/^Version: ([0-9.]+).*/\\1/p'": + type: eval + description: The expression to obtain the version of the tool + +authors: + - "@jonasscheid" +maintainers: + - "@jonasscheid" diff --git a/modules/local/openms/mapaligneridentification/environment.yml b/modules/local/openms/mapaligneridentification/environment.yml index d85a93ef..c8bad1b9 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.1 + - bioconda::openms=3.5.0 diff --git a/modules/local/openms/mapaligneridentification/main.nf b/modules/local/openms/mapaligneridentification/main.nf index fd19d5c3..9325eb44 100644 --- a/modules/local/openms/mapaligneridentification/main.nf +++ b/modules/local/openms/mapaligneridentification/main.nf @@ -4,15 +4,15 @@ 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.1--h81ffffe_1' : - 'biocontainers/openms:3.4.1--h81ffffe_1' }" + 'https://depot.galaxyproject.org/singularity/openms:3.5.0--h78fb946_0' : + 'biocontainers/openms:3.5.0--h78fb946_0' }" input: tuple val(meta), path(idxmls) output: tuple val(meta), path("*.trafoXML"), emit: trafoxml - path "versions.yml" , emit: versions + tuple val("${task.process}"), val('openms'), eval("FileInfo --help 2>&1 | sed -nE 's/^Version: ([0-9.]+).*/\\1/p'"), topic: versions when: task.ext.when == null || task.ext.when @@ -26,11 +26,6 @@ process OPENMS_MAPALIGNERIDENTIFICATION { -in $idxmls \\ -trafo_out ${out_names} \\ $args - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') - END_VERSIONS """ stub: @@ -38,10 +33,5 @@ process OPENMS_MAPALIGNERIDENTIFICATION { """ touch test1.consensusXML touch test2.consensusXML - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') - END_VERSIONS """ } diff --git a/modules/local/openms/maprttransformer/environment.yml b/modules/local/openms/maprttransformer/environment.yml index d85a93ef..c8bad1b9 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.1 + - bioconda::openms=3.5.0 diff --git a/modules/local/openms/maprttransformer/main.nf b/modules/local/openms/maprttransformer/main.nf index a2889e35..7a74e7f2 100644 --- a/modules/local/openms/maprttransformer/main.nf +++ b/modules/local/openms/maprttransformer/main.nf @@ -4,22 +4,22 @@ 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.1--h81ffffe_1' : - 'biocontainers/openms:3.4.1--h81ffffe_1' }" + 'https://depot.galaxyproject.org/singularity/openms:3.5.0--h78fb946_0' : + 'biocontainers/openms:3.5.0--h78fb946_0' }" input: tuple val(meta), path(alignment_file), path(trafoxml) output: tuple val(meta), path("*_aligned.*"), emit: aligned - path "versions.yml" , emit: versions + tuple val("${task.process}"), val('openms'), eval("FileInfo --help 2>&1 | sed -nE 's/^Version: ([0-9.]+).*/\\1/p'"), topic: versions when: task.ext.when == null || task.ext.when script: - def args = task.ext.args ?: '' - def prefix = task.ext.prefix ?: "${meta.id}" + def args = task.ext.args ?: '' + def prefix = task.ext.prefix ?: "${meta.id}_aligned" def fileExt = alignment_file.collect { it.name.tokenize("\\.")[1] }.join(' ') """ @@ -29,11 +29,6 @@ process OPENMS_MAPRTTRANSFORMER { -out ${prefix}.${fileExt} \\ -threads $task.cpus \\ $args - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') - END_VERSIONS """ stub: @@ -42,10 +37,5 @@ process OPENMS_MAPRTTRANSFORMER { """ touch ${prefix}.${fileExt} - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') - END_VERSIONS """ } diff --git a/modules/local/openms/mztabexporter/environment.yml b/modules/local/openms/mztabexporter/environment.yml index d85a93ef..c8bad1b9 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.1 + - bioconda::openms=3.5.0 diff --git a/modules/local/openms/mztabexporter/main.nf b/modules/local/openms/mztabexporter/main.nf index ee5500b4..86844f46 100644 --- a/modules/local/openms/mztabexporter/main.nf +++ b/modules/local/openms/mztabexporter/main.nf @@ -4,15 +4,15 @@ 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.1--h81ffffe_1' : - 'biocontainers/openms:3.4.1--h81ffffe_1' }" + 'https://depot.galaxyproject.org/singularity/openms:3.5.0--h78fb946_0' : + 'biocontainers/openms:3.5.0--h78fb946_0' }" input: tuple val(meta), path(in_file) output: tuple val(meta), path("*.mzTab"), emit: mztab - path "versions.yml" , emit: versions + tuple val("${task.process}"), val('openms'), eval("FileInfo --help 2>&1 | sed -nE 's/^Version: ([0-9.]+).*/\\1/p'"), topic: versions when: task.ext.when == null || task.ext.when @@ -27,11 +27,6 @@ process OPENMS_MZTABEXPORTER { -out ${prefix}.mzTab \\ -threads $task.cpus \\ $args - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') - END_VERSIONS """ stub: @@ -39,10 +34,5 @@ process OPENMS_MZTABEXPORTER { """ touch ${prefix}.mzTab - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') - END_VERSIONS """ } diff --git a/modules/local/openms/psmfeatureextractor/environment.yml b/modules/local/openms/psmfeatureextractor/environment.yml index d85a93ef..c8bad1b9 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.1 + - bioconda::openms=3.5.0 diff --git a/modules/local/openms/psmfeatureextractor/main.nf b/modules/local/openms/psmfeatureextractor/main.nf index 870e6519..57ace075 100644 --- a/modules/local/openms/psmfeatureextractor/main.nf +++ b/modules/local/openms/psmfeatureextractor/main.nf @@ -4,15 +4,15 @@ 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.1--h81ffffe_1' : - 'biocontainers/openms:3.4.1--h81ffffe_1' }" + 'https://depot.galaxyproject.org/singularity/openms:3.5.0--h78fb946_0' : + 'biocontainers/openms:3.5.0--h78fb946_0' }" input: tuple val(meta), path(idxml), path(feature_file) output: tuple val(meta), path("*.idXML"), emit: idxml - path "versions.yml" , emit: versions + tuple val("${task.process}"), val('openms'), eval("FileInfo --help 2>&1 | sed -nE 's/^Version: ([0-9.]+).*/\\1/p'"), topic: versions when: task.ext.when == null || task.ext.when @@ -31,11 +31,6 @@ process OPENMS_PSMFEATUREEXTRACTOR { -threads $task.cpus \\ -extra \$extra_features \\ $args - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') - END_VERSIONS """ stub: @@ -43,10 +38,5 @@ process OPENMS_PSMFEATUREEXTRACTOR { """ touch ${prefix}.idXML - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') - END_VERSIONS """ } diff --git a/modules/local/openms/textexporter/environment.yml b/modules/local/openms/textexporter/environment.yml index d85a93ef..c8bad1b9 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.1 + - bioconda::openms=3.5.0 diff --git a/modules/local/openms/textexporter/main.nf b/modules/local/openms/textexporter/main.nf index 46dd8f33..21b9aa04 100644 --- a/modules/local/openms/textexporter/main.nf +++ b/modules/local/openms/textexporter/main.nf @@ -4,15 +4,15 @@ 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.1--h81ffffe_1' : - 'biocontainers/openms:3.4.1--h81ffffe_1' }" + 'https://depot.galaxyproject.org/singularity/openms:3.5.0--h78fb946_0' : + 'biocontainers/openms:3.5.0--h78fb946_0' }" input: tuple val(meta), path(file) output: tuple val(meta), path("*.tsv"), emit: tsv - path "versions.yml" , emit: versions + tuple val("${task.process}"), val('openms'), eval("FileInfo --help 2>&1 | sed -nE 's/^Version: ([0-9.]+).*/\\1/p'"), topic: versions when: task.ext.when == null || task.ext.when @@ -26,14 +26,7 @@ process OPENMS_TEXTEXPORTER { -in $file \\ -out ${prefix}_exported.tsv \\ -threads $task.cpus \\ - -id:add_hit_metavalues 0 \\ - -id:peptides_only \\ $args - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') - END_VERSIONS """ stub: @@ -41,10 +34,5 @@ process OPENMS_TEXTEXPORTER { """ touch ${prefix}.tsv - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') - END_VERSIONS """ } diff --git a/modules/local/openmsthirdparty/featurelinkerunlabeledkd/environment.yml b/modules/local/openmsthirdparty/featurelinkerunlabeledkd/environment.yml index dde2f844..9255b744 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.1 + - bioconda::openms-thirdparty=3.5.0 diff --git a/modules/local/openmsthirdparty/featurelinkerunlabeledkd/main.nf b/modules/local/openmsthirdparty/featurelinkerunlabeledkd/main.nf index 96ce7b37..07675829 100644 --- a/modules/local/openmsthirdparty/featurelinkerunlabeledkd/main.nf +++ b/modules/local/openmsthirdparty/featurelinkerunlabeledkd/main.nf @@ -4,15 +4,15 @@ 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.1--h9ee0642_1' : - 'biocontainers/openms-thirdparty:3.4.1--h9ee0642_1' }" + 'https://depot.galaxyproject.org/singularity/openms-thirdparty:3.5.0--h9ee0642_0' : + 'biocontainers/openms-thirdparty:3.5.0--h9ee0642_0' }" input: tuple val(meta), path(features) output: tuple val(meta), path("*.consensusXML"), emit: consensusxml - path "versions.yml" , emit: versions + tuple val("${task.process}"), val('openms'), eval("FileInfo --help 2>&1 | sed -nE 's/^Version: ([0-9.]+).*/\\1/p'"), topic: versions when: task.ext.when == null || task.ext.when @@ -21,14 +21,10 @@ process OPENMS_FEATURELINKERUNLABELEDKD { def prefix = task.ext.prefix ?: "${meta.id}_all_features_merged" """ - FeatureLinkerUnlabeledKD -in $features \\ + FeatureLinkerUnlabeledKD \\ + -in $features \\ -out ${prefix}.consensusXML \\ -threads $task.cpus - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - openms-thirdparty: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') - END_VERSIONS """ stub: @@ -36,10 +32,5 @@ process OPENMS_FEATURELINKERUNLABELEDKD { """ touch ${prefix}.consensusXML - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - openms-thirdparty: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') - END_VERSIONS """ } diff --git a/modules/local/openmsthirdparty/percolatoradapter/environment.yml b/modules/local/openmsthirdparty/percolatoradapter/environment.yml index dde2f844..9255b744 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.1 + - bioconda::openms-thirdparty=3.5.0 diff --git a/modules/local/openmsthirdparty/percolatoradapter/main.nf b/modules/local/openmsthirdparty/percolatoradapter/main.nf index 8199ce17..a3f20178 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.1--h9ee0642_1' : - 'biocontainers/openms-thirdparty:3.4.1--h9ee0642_1' }" + 'https://depot.galaxyproject.org/singularity/openms-thirdparty:3.5.0--h9ee0642_0' : + 'biocontainers/openms-thirdparty:3.5.0--h9ee0642_0' }" input: tuple val(meta), path(merged_with_features) @@ -13,7 +13,8 @@ process OPENMS_PERCOLATORADAPTER { output: tuple val(meta), path("*.idXML") , emit: idxml tuple val(meta), path("*_percolator_feature_weights.tsv"), emit: feature_weights, optional: true - path "versions.yml" , emit: versions + tuple val("${task.process}"), val('PercolatorAdapter'), eval("PercolatorAdapter 2>&1 | grep -E '^Version(.*)' | sed 's/Version: //g' | cut -d ' ' -f 1"), topic: versions + tuple val("${task.process}"), val('percolator'), eval("percolator -h 2>&1 | grep -E '^Percolator version(.*)' | sed 's/Percolator version //g' | cut -d',' -f1"), topic: versions when: task.ext.when == null || task.ext.when @@ -28,12 +29,6 @@ process OPENMS_PERCOLATORADAPTER { -out ${prefix}.idXML \\ -threads $task.cpus \\ $args - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - PercolatorAdapter: \$(PercolatorAdapter 2>&1 | grep -E '^Version(.*)' | sed 's/Version: //g' | cut -d ' ' -f 1) - percolator: \$(percolator -h 2>&1 | grep -E '^Percolator version(.*)' | sed 's/Percolator version //g') - END_VERSIONS """ stub: @@ -41,11 +36,5 @@ process OPENMS_PERCOLATORADAPTER { """ touch ${prefix}.idXML - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - PercolatorAdapter: \$(PercolatorAdapter 2>&1 | grep -E '^Version(.*)' | sed 's/Version: //g' | cut -d ' ' -f 1) - percolator: \$(percolator -h 2>&1 | grep -E '^Percolator version(.*)' | sed 's/Percolator version //g') - END_VERSIONS """ } diff --git a/modules/local/pridepy/download_file/environment.yml b/modules/local/pridepy/download_file/environment.yml new file mode 100644 index 00000000..9a956eb8 --- /dev/null +++ b/modules/local/pridepy/download_file/environment.yml @@ -0,0 +1,5 @@ +channels: + - conda-forge + - bioconda +dependencies: + - bioconda::pridepy=0.0.12 diff --git a/modules/local/pridepy/download_file/main.nf b/modules/local/pridepy/download_file/main.nf new file mode 100644 index 00000000..9548f382 --- /dev/null +++ b/modules/local/pridepy/download_file/main.nf @@ -0,0 +1,37 @@ +process PRIDEPY_DOWNLOAD_FILE { + label 'process_single' + tag "${file_name}" + + conda "${moduleDir}/environment.yml" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/pridepy:0.0.12--pyhdfd78af_0' : + 'quay.io/biocontainers/pridepy:0.0.12--pyhdfd78af_0' }" + + input: + tuple val(meta), val(file_name), val(pride_accession) + + output: + tuple val(meta), path("${file_name}"), emit: downloaded_file + tuple val("${task.process}"), val('pridepy'), eval("pip show pridepy 2>/dev/null | grep Version | cut -d' ' -f2"), topic: versions + + when: + task.ext.when == null || task.ext.when + + script: + def args = task.ext.args ?: '' + """ + pridepy download-file-by-name \\ + -a "${pride_accession}" \\ + -f "${file_name}" \\ + -o . \\ + ${args} + + # pridepy exits 0 even on download failure — validate file is non-empty + [ -s "${file_name}" ] || { echo "ERROR: Downloaded file ${file_name} is empty"; exit 1; } + """ + + stub: + """ + touch "${file_name}" + """ +} diff --git a/modules/local/pridepy/download_file/meta.yml b/modules/local/pridepy/download_file/meta.yml new file mode 100644 index 00000000..56749bf7 --- /dev/null +++ b/modules/local/pridepy/download_file/meta.yml @@ -0,0 +1,54 @@ +name: pridepy_download_file +description: Download a single file from the PRIDE Archive by name using pridepy. +keywords: + - pride + - download + - proteomics + - mass spectrometry +tools: + - pridepy: + description: | + Python client library and command line tool for the PRIDE Archive REST API. + Supports downloading files from PRIDE datasets by accession and file name. + homepage: https://github.com/PRIDE-Utilities/pridepy + documentation: https://github.com/PRIDE-Utilities/pridepy + licence: ["Apache-2.0"] +input: + - - meta: + type: map + description: | + Groovy Map containing sample information. + e.g. [ id:'test', sample:'sample1', condition:'A', search_preset:'default' ] + - file_name: + type: string + description: Name of the file to download from the PRIDE Archive dataset. + - pride_accession: + type: string + description: PRIDE Archive accession number (e.g. PXD000001) identifying the dataset. +output: + downloaded_file: + - - meta: + type: map + description: | + Groovy Map containing sample information. + e.g. [ id:'test', sample:'sample1', condition:'A', search_preset:'default' ] + - "${file_name}": + type: file + description: The file downloaded from the PRIDE Archive. + pattern: "*" +topics: + versions: + - - ${task.process}: + type: string + description: The process the versions were collected from + - pridepy: + type: string + description: The tool name + - "pip show pridepy 2>/dev/null | grep Version | cut -d' ' -f2": + type: eval + description: The expression to obtain the version of pridepy + +authors: + - "@jonasscheid" +maintainers: + - "@jonasscheid" diff --git a/modules/local/pridepy/fetch_sdrf/environment.yml b/modules/local/pridepy/fetch_sdrf/environment.yml new file mode 100644 index 00000000..9a956eb8 --- /dev/null +++ b/modules/local/pridepy/fetch_sdrf/environment.yml @@ -0,0 +1,5 @@ +channels: + - conda-forge + - bioconda +dependencies: + - bioconda::pridepy=0.0.12 diff --git a/modules/local/pridepy/fetch_sdrf/main.nf b/modules/local/pridepy/fetch_sdrf/main.nf new file mode 100644 index 00000000..2165650a --- /dev/null +++ b/modules/local/pridepy/fetch_sdrf/main.nf @@ -0,0 +1,31 @@ +process PRIDEPY_FETCH_SDRF { + label 'process_single' + tag "$pride_id" + + conda "${moduleDir}/environment.yml" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/pridepy:0.0.12--pyhdfd78af_0' : + 'quay.io/biocontainers/pridepy:0.0.12--pyhdfd78af_0' }" + + input: + val pride_id + + output: + path "*.sdrf.tsv" , emit: sdrf + tuple val("${task.process}"), val('pridepy'), eval("pip show pridepy 2>/dev/null | grep Version | cut -d' ' -f2"), topic: versions + + when: + task.ext.when == null || task.ext.when + + script: + """ + pridepy stream-files-metadata -a "${pride_id}" -o files_metadata.json + sdrf_name=\$(python3 -c "import json,sys; sdrfs=[f['fileName'] for f in json.load(open('files_metadata.json')) if f['fileName'].endswith('.sdrf.tsv')]; print(sdrfs[0]) if sdrfs else sys.exit('ERROR: No SDRF file found for ${pride_id}')") + pridepy download-file-by-name -a "${pride_id}" -f "\$sdrf_name" -o . -p ftp + """ + + stub: + """ + touch ${pride_id}.sdrf.tsv + """ +} diff --git a/modules/local/pridepy/fetch_sdrf/meta.yml b/modules/local/pridepy/fetch_sdrf/meta.yml new file mode 100644 index 00000000..b1e0e7be --- /dev/null +++ b/modules/local/pridepy/fetch_sdrf/meta.yml @@ -0,0 +1,41 @@ +name: pridepy_fetch_sdrf +description: Fetch an SDRF file from the PRIDE Archive for a given project accession. +keywords: + - pride + - sdrf + - proteomics + - download +tools: + - pridepy: + description: | + Python package to access PRIDE Archive data programmatically, + including downloading files and metadata for public proteomics datasets. + homepage: https://github.com/PRIDE-Archive/pridepy + documentation: https://github.com/PRIDE-Archive/pridepy + licence: ["Apache-2.0"] +input: + - - pride_id: + type: string + description: PRIDE Archive project accession (e.g. PXD009752) +output: + sdrf: + - - "*.sdrf.tsv": + type: file + description: SDRF (Sample and Data Relationship Format) file describing the experimental design of the PRIDE project + pattern: "*.sdrf.tsv" +topics: + versions: + - - ${task.process}: + type: string + description: The process the versions were collected from + - pridepy: + type: string + description: The tool name + - "pip show pridepy 2>/dev/null | grep Version | cut -d' ' -f2": + type: eval + description: The expression to obtain the version of the tool + +authors: + - "@jonasscheid" +maintainers: + - "@jonasscheid" diff --git a/modules/local/pyopenms/chromatogramextractor/main.nf b/modules/local/pyopenms/chromatogramextractor/main.nf index 33f138e0..8f7456fd 100644 --- a/modules/local/pyopenms/chromatogramextractor/main.nf +++ b/modules/local/pyopenms/chromatogramextractor/main.nf @@ -12,7 +12,7 @@ process PYOPENMS_CHROMATOGRAMEXTRACTOR { output: tuple val(meta), path("*.csv") , emit: csv - path "versions.yml" , emit: versions + tuple val("${task.process}"), val('pyopenms'), eval("pip show pyopenms | grep Version | sed 's/Version: //'"), topic: versions when: task.ext.when == null || task.ext.when @@ -25,11 +25,6 @@ process PYOPENMS_CHROMATOGRAMEXTRACTOR { chromatogram_extractor.py \\ -in $mzml \\ -out ${prefix}_chrom.csv \\ - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - pyopenms: \$(pip show pyopenms | grep Version | sed 's/Version: //') - END_VERSIONS """ stub: @@ -37,10 +32,5 @@ process PYOPENMS_CHROMATOGRAMEXTRACTOR { """ touch ${prefix}_chrom.csv - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - pyopenms: \$(pip show pyopenms | grep Version | sed 's/Version: //') - END_VERSIONS """ } diff --git a/modules/local/pyopenms/ionannotator/main.nf b/modules/local/pyopenms/ionannotator/main.nf index cb5f06a6..b178fa5d 100644 --- a/modules/local/pyopenms/ionannotator/main.nf +++ b/modules/local/pyopenms/ionannotator/main.nf @@ -12,7 +12,7 @@ process PYOPENMS_IONANNOTATOR { output: tuple val(meta), path("*.tsv") , emit: tsv - path "versions.yml" , emit: versions + tuple val("${task.process}"), val('pyopenms'), eval("pip show pyopenms | grep Version | sed 's/Version: //'"), topic: versions when: task.ext.when == null || task.ext.when @@ -35,12 +35,6 @@ process PYOPENMS_IONANNOTATOR { $zions \\ $aions \\ $cions - - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - pyopenms: \$(pip show pyopenms | grep Version | sed 's/Version: //') - END_VERSIONS """ stub: @@ -49,10 +43,5 @@ process PYOPENMS_IONANNOTATOR { """ touch ${prefix}_all_peaks.tsv touch ${prefix}_matching_ions.tsv - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - pyopenms: \$(pip show pyopenms | grep Version | sed 's/Version: //') - END_VERSIONS """ } diff --git a/modules/local/pyopenms/summarize_results/main.nf b/modules/local/pyopenms/summarize_results/main.nf index e92edd38..7ecc9472 100644 --- a/modules/local/pyopenms/summarize_results/main.nf +++ b/modules/local/pyopenms/summarize_results/main.nf @@ -15,8 +15,9 @@ process SUMMARIZE_RESULTS { path '*_xcorr_scores.csv' , emit: xcorr, optional: true path '*_peptide_length.csv' , emit: lengths, optional: true path '*_peptide_intensity.csv' , emit: intensities, optional: true + path '*_histogram_im.csv' , emit: hist_im, optional: true tuple val(meta), path('*.tsv'), path('*_general_stats.csv') , emit: epicore_input - path 'versions.yml' , emit: versions + tuple val("${task.process}"), val('pyopenms'), eval("pip show pyopenms | grep Version | sed 's/Version: //'"), topic: versions script: def args = task.ext.args ?: '' @@ -29,11 +30,6 @@ process SUMMARIZE_RESULTS { --out_prefix $prefix \\ $quantify \\ $args - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - pyopenms: \$(pip show pyopenms | grep Version | sed 's/Version: //') - END_VERSIONS """ stub: @@ -46,12 +42,8 @@ process SUMMARIZE_RESULTS { touch ${prefix}_xcorr_scores.csv touch ${prefix}_peptide_length.csv touch ${prefix}_peptide_intensity.csv + touch ${prefix}_histogram_im.csv touch ${prefix}_general_stats.csv touch ${prefix}.tsv - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - pyopenms: \$(pip show pyopenms | grep Version | sed 's/Version: //') - END_VERSIONS """ } diff --git a/modules/local/sdrf_pipelines/parse_sdrf/environment.yml b/modules/local/sdrf_pipelines/parse_sdrf/environment.yml new file mode 100644 index 00000000..725912b3 --- /dev/null +++ b/modules/local/sdrf_pipelines/parse_sdrf/environment.yml @@ -0,0 +1,5 @@ +channels: + - conda-forge + - bioconda +dependencies: + - bioconda::sdrf-pipelines=0.1.2 diff --git a/modules/local/sdrf_pipelines/parse_sdrf/main.nf b/modules/local/sdrf_pipelines/parse_sdrf/main.nf new file mode 100644 index 00000000..4f48ef2c --- /dev/null +++ b/modules/local/sdrf_pipelines/parse_sdrf/main.nf @@ -0,0 +1,34 @@ +process SDRF_PIPELINES_PARSE_SDRF { + label 'process_single' + tag "${sdrf.baseName}" + + conda "${moduleDir}/environment.yml" + container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? + 'https://depot.galaxyproject.org/singularity/sdrf-pipelines:0.1.2--pyhdfd78af_0' : + 'quay.io/biocontainers/sdrf-pipelines:0.1.2--pyhdfd78af_0' }" + + input: + path sdrf + + output: + path "samplesheet.tsv" , emit: samplesheet + path "search_presets.tsv" , emit: search_presets + tuple val("${task.process}"), val('sdrf-pipelines'), eval("parse_sdrf --version | cut -d ' ' -f 2"), topic: versions + + when: + task.ext.when == null || task.ext.when + + script: + """ + parse_sdrf convert-mhcquant \\ + -s ${sdrf} \\ + -os samplesheet.tsv \\ + -op search_presets.tsv + """ + + stub: + """ + touch samplesheet.tsv + touch search_presets.tsv + """ +} diff --git a/modules/local/sdrf_pipelines/parse_sdrf/meta.yml b/modules/local/sdrf_pipelines/parse_sdrf/meta.yml new file mode 100644 index 00000000..86de3306 --- /dev/null +++ b/modules/local/sdrf_pipelines/parse_sdrf/meta.yml @@ -0,0 +1,57 @@ +name: sdrf_pipelines_parse_sdrf +description: Converts an SDRF (Sample and Data Relationship Format) file into an + mhcquant-compatible samplesheet and search presets TSV files using sdrf-pipelines. +keywords: + - sdrf + - samplesheet + - proteomics + - immunopeptidomics + - mhcquant +tools: + - "sdrf-pipelines": + description: "A set of tools to validate and convert SDRF files for proteomics + pipelines." + homepage: "https://github.com/bigbio/sdrf-pipelines" + documentation: "https://github.com/bigbio/sdrf-pipelines" + tool_dev_url: "https://github.com/bigbio/sdrf-pipelines" + doi: "10.1021/acs.jproteome.1c00505" + licence: ["Apache-2.0"] + identifier: "" + +input: + - - sdrf: + type: file + description: SDRF file describing the experimental design and sample metadata. + pattern: "*.{tsv,sdrf.tsv}" + ontologies: [] + +output: + samplesheet: + - - "samplesheet.tsv": + type: file + description: mhcquant-compatible samplesheet derived from the SDRF file. + pattern: "samplesheet.tsv" + ontologies: [] + search_presets: + - - "search_presets.tsv": + type: file + description: Search parameter presets derived from the SDRF file, one row + per unique search configuration. + pattern: "search_presets.tsv" + ontologies: [] +topics: + versions: + - - ${task.process}: + type: string + description: The name of the process + - sdrf-pipelines: + type: string + description: The name of the tool + - "parse_sdrf --version | cut -d ' ' -f 2": + type: eval + description: The expression to obtain the version of the tool + +authors: + - "@jonasscheid" +maintainers: + - "@jonasscheid" diff --git a/modules/local/tdf2mzml/main.nf b/modules/local/tdf2mzml/main.nf index b900b81a..de677d4e 100644 --- a/modules/local/tdf2mzml/main.nf +++ b/modules/local/tdf2mzml/main.nf @@ -1,26 +1,21 @@ process TDF2MZML { tag "$meta.id" - container "docker.io/mfreitas/tdf2mzml" + container "docker.io/mfreitas/tdf2mzml:0.4_noentry" input: tuple val(meta), path(tdf) output: tuple val(meta), path("*.mzML"), emit: mzml - path "versions.yml" , emit: versions + tuple val("${task.process}"), val('python'), eval("python3 --version | cut -d ' ' -f2"), topic: versions + tuple val("${task.process}"), val('tdf2mzml'), eval("tdf2mzml --version | cut -d' ' -f2"), topic: versions script: def prefix = task.ext.prefix ?: "${tdf.simpleName}" """ - tdf2mzml.py -i $tdf -o ${prefix}.mzML - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - python: \$(python3 --version | cut -d ' ' -f2) - tdf2mzml: \$(echo 0.3.0) - END_VERSIONS + tdf2mzml -i $tdf -o ${prefix}.mzML """ stub: @@ -28,11 +23,5 @@ process TDF2MZML { """ touch ${prefix}.mzML - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - python: \$(python3 --version | cut -d ' ' -f2) - tdf2mzml: \$(echo 0.3.0) - END_VERSIONS """ } diff --git a/modules/local/untar/main.nf b/modules/local/untar/main.nf index 35c364b1..ed25bfe2 100644 --- a/modules/local/untar/main.nf +++ b/modules/local/untar/main.nf @@ -12,7 +12,7 @@ process UNTAR { output: tuple val(meta), path("*.d"), emit: untar - path "versions.yml" , emit: versions + tuple val("${task.process}"), val('untar'), eval("echo \$(tar --version 2>&1) | sed 's/^.*(GNU tar) //; s/ Copyright.*\$//'"), topic: versions when: task.ext.when == null || task.ext.when @@ -33,11 +33,6 @@ process UNTAR { $archive \\ --strip-components=\$depth \\ $args2 - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - untar: \$(echo \$(tar --version 2>&1) | sed 's/^.*(GNU tar) //; s/ Copyright.*\$//') - END_VERSIONS """ stub: @@ -46,10 +41,5 @@ process UNTAR { """ mkdir $prefix touch ${prefix}/file.txt - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - untar: \$(echo \$(tar --version 2>&1) | sed 's/^.*(GNU tar) //; s/ Copyright.*\$//') - END_VERSIONS """ } diff --git a/modules/local/untar/meta.yml b/modules/local/untar/meta.yml index a9a2110f..d5c15cdb 100644 --- a/modules/local/untar/meta.yml +++ b/modules/local/untar/meta.yml @@ -11,29 +11,38 @@ tools: documentation: https://www.gnu.org/software/tar/manual/ licence: ["GPL-3.0-or-later"] input: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - archive: - type: file - description: File to be untar - pattern: "*.{tar}.{gz}" + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - archive: + type: file + description: File to be untar + pattern: "*.{tar}.{gz}" output: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - untar: - type: directory - description: Directory containing contents of archive - pattern: "*/" - - versions: - type: file - description: File containing software versions - pattern: "versions.yml" + untar: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - "*.d": + type: directory + description: Directory containing contents of archive + pattern: "*/" +topics: + versions: + - - ${task.process}: + type: string + description: The process the versions were collected from + - untar: + type: string + description: The tool name + - "echo $(tar --version 2>&1) | sed 's/^.*(GNU tar) //; s/ Copyright.*$//'": + type: eval + description: The expression to obtain the version of the tool + authors: - "@joseespinosa" - "@drpatelh" diff --git a/modules/local/unzip/main.nf b/modules/local/unzip/main.nf index 5405ef0f..80f10a37 100644 --- a/modules/local/unzip/main.nf +++ b/modules/local/unzip/main.nf @@ -12,7 +12,7 @@ process UNZIP { output: tuple val(meta), path("*.d"), emit: unzipped_archive - path "versions.yml" , emit: versions + tuple val("${task.process}"), val('7za'), eval("echo \$(7za --help) | sed 's/.*p7zip Version //; s/(.*//'"), topic: versions when: task.ext.when == null || task.ext.when @@ -28,11 +28,6 @@ process UNZIP { -o"." \\ $args \\ $archive - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - 7za: \$(echo \$(7za --help) | sed 's/.*p7zip Version //; s/(.*//') - END_VERSIONS """ stub: @@ -40,10 +35,5 @@ process UNZIP { """ touch ${prefix}.d - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - 7za: \$(echo \$(7za --help) | sed 's/.*p7zip Version //; s/(.*//') - END_VERSIONS """ } diff --git a/modules/local/unzip/meta.yml b/modules/local/unzip/meta.yml index e8e377e2..2c952111 100644 --- a/modules/local/unzip/meta.yml +++ b/modules/local/unzip/meta.yml @@ -13,29 +13,38 @@ tools: tool_dev_url: https://sourceforge.net/projects/p7zip" licence: ["LGPL-2.1-or-later"] input: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - archive: - type: file - description: ZIP file - pattern: "*.zip" + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - archive: + type: file + description: ZIP file + pattern: "*.zip" output: - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. [ id:'test', single_end:false ] - - unzipped_archive: - type: directory - description: Directory contents of the unzipped archive - pattern: "${archive.baseName}/" - - versions: - type: file - description: File containing software versions - pattern: "versions.yml" + unzipped_archive: + - - meta: + type: map + description: | + Groovy Map containing sample information + e.g. [ id:'test', single_end:false ] + - unzipped_archive: + type: directory + description: Directory contents of the unzipped archive + pattern: "${archive.baseName}/" +topics: + versions: + - - ${task.process}: + type: string + description: The process the versions were collected from + - 7za: + type: string + description: The tool name + - "echo $(7za --help) | sed 's/.*p7zip Version //; s/(.*//'": + type: eval + description: The expression to obtain the version of the tool + authors: - "@jfy133" maintainers: diff --git a/modules/nf-core/gunzip/main.nf b/modules/nf-core/gunzip/main.nf index 3ffc8e92..a8533e74 100644 --- a/modules/nf-core/gunzip/main.nf +++ b/modules/nf-core/gunzip/main.nf @@ -12,7 +12,7 @@ process GUNZIP { output: tuple val(meta), path("${gunzip}"), emit: gunzip - path "versions.yml", emit: versions + tuple val("${task.process}"), val('gunzip'), eval('gunzip --version 2>&1 | head -1 | sed "s/^.*(gzip) //; s/ Copyright.*//"'), topic: versions, emit: versions_gunzip when: task.ext.when == null || task.ext.when @@ -32,24 +32,14 @@ process GUNZIP { ${args} \\ ${archive} \\ > ${gunzip} - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - gunzip: \$(echo \$(gunzip --version 2>&1) | sed 's/^.*(gzip) //; s/ Copyright.*\$//') - END_VERSIONS """ stub: - 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} - cat <<-END_VERSIONS > versions.yml - "${task.process}": - gunzip: \$(echo \$(gunzip --version 2>&1) | sed 's/^.*(gzip) //; s/ Copyright.*\$//') - END_VERSIONS """ } diff --git a/modules/nf-core/gunzip/meta.yml b/modules/nf-core/gunzip/meta.yml index 926bb22a..bba6b3ba 100644 --- a/modules/nf-core/gunzip/meta.yml +++ b/modules/nf-core/gunzip/meta.yml @@ -34,13 +34,29 @@ output: description: Compressed/uncompressed file pattern: "*.*" ontologies: [] + versions_gunzip: + - - ${task.process}: + type: string + description: The process the versions were collected from + - gunzip: + type: string + description: The tool name + - gunzip --version 2>&1 | head -1 | sed "s/^.*(gzip) //; s/ Copyright.*//": + type: eval + description: The expression to obtain the version of the tool + +topics: versions: - - versions.yml: - type: file - description: File containing software versions - pattern: "versions.yml" - ontologies: - - edam: http://edamontology.org/format_3750 # YAML + - - ${task.process}: + type: string + description: The process the versions were collected from + - gunzip: + type: string + description: The tool name + - gunzip --version 2>&1 | head -1 | sed "s/^.*(gzip) //; s/ Copyright.*//": + type: eval + description: The expression to obtain the version of the tool + authors: - "@joseespinosa" - "@drpatelh" diff --git a/modules/nf-core/gunzip/tests/main.nf.test.snap b/modules/nf-core/gunzip/tests/main.nf.test.snap index a0f0e67e..111ba1bc 100644 --- a/modules/nf-core/gunzip/tests/main.nf.test.snap +++ b/modules/nf-core/gunzip/tests/main.nf.test.snap @@ -11,7 +11,11 @@ ] ], "1": [ - "versions.yml:md5,d327e4a19a6d5c5e974136cef8999d8c" + [ + "GUNZIP", + "gunzip", + "1.13" + ] ], "gunzip": [ [ @@ -21,16 +25,20 @@ "test.xyz.fastq:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], - "versions": [ - "versions.yml:md5,d327e4a19a6d5c5e974136cef8999d8c" + "versions_gunzip": [ + [ + "GUNZIP", + "gunzip", + "1.13" + ] ] } ], "meta": { - "nf-test": "0.9.2", - "nextflow": "24.10.2" + "nf-test": "0.9.3", + "nextflow": "25.10.2" }, - "timestamp": "2024-12-13T11:48:22.080222697" + "timestamp": "2026-01-19T17:21:56.633550769" }, "Should run without failures - stub": { "content": [ @@ -44,7 +52,11 @@ ] ], "1": [ - "versions.yml:md5,d327e4a19a6d5c5e974136cef8999d8c" + [ + "GUNZIP", + "gunzip", + "1.13" + ] ], "gunzip": [ [ @@ -54,16 +66,20 @@ "test_1.fastq:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], - "versions": [ - "versions.yml:md5,d327e4a19a6d5c5e974136cef8999d8c" + "versions_gunzip": [ + [ + "GUNZIP", + "gunzip", + "1.13" + ] ] } ], "meta": { - "nf-test": "0.9.2", - "nextflow": "24.10.2" + "nf-test": "0.9.3", + "nextflow": "25.10.2" }, - "timestamp": "2024-12-13T11:48:14.593020264" + "timestamp": "2026-01-19T17:21:51.435621199" }, "Should run without failures": { "content": [ @@ -77,7 +93,11 @@ ] ], "1": [ - "versions.yml:md5,d327e4a19a6d5c5e974136cef8999d8c" + [ + "GUNZIP", + "gunzip", + "1.13" + ] ], "gunzip": [ [ @@ -87,16 +107,20 @@ "test_1.fastq:md5,4161df271f9bfcd25d5845a1e220dbec" ] ], - "versions": [ - "versions.yml:md5,d327e4a19a6d5c5e974136cef8999d8c" + "versions_gunzip": [ + [ + "GUNZIP", + "gunzip", + "1.13" + ] ] } ], "meta": { - "nf-test": "0.9.2", - "nextflow": "24.10.2" + "nf-test": "0.9.3", + "nextflow": "25.10.2" }, - "timestamp": "2024-12-13T11:48:01.295397925" + "timestamp": "2026-01-19T17:21:40.613975821" }, "Should run without failures - prefix": { "content": [ @@ -110,7 +134,11 @@ ] ], "1": [ - "versions.yml:md5,d327e4a19a6d5c5e974136cef8999d8c" + [ + "GUNZIP", + "gunzip", + "1.13" + ] ], "gunzip": [ [ @@ -120,15 +148,19 @@ "test.xyz.fastq:md5,4161df271f9bfcd25d5845a1e220dbec" ] ], - "versions": [ - "versions.yml:md5,d327e4a19a6d5c5e974136cef8999d8c" + "versions_gunzip": [ + [ + "GUNZIP", + "gunzip", + "1.13" + ] ] } ], "meta": { - "nf-test": "0.9.2", - "nextflow": "24.10.2" + "nf-test": "0.9.3", + "nextflow": "25.10.2" }, - "timestamp": "2024-12-13T11:48:07.414271387" + "timestamp": "2026-01-19T17:21:46.086880414" } } \ No newline at end of file diff --git a/modules/nf-core/multiqc/environment.yml b/modules/nf-core/multiqc/environment.yml index dd513cbd..009874d4 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.31 + - bioconda::multiqc=1.33 diff --git a/modules/nf-core/multiqc/main.nf b/modules/nf-core/multiqc/main.nf index 5288f5cc..3b0e975b 100644 --- a/modules/nf-core/multiqc/main.nf +++ b/modules/nf-core/multiqc/main.nf @@ -3,11 +3,11 @@ process MULTIQC { conda "${moduleDir}/environment.yml" container "${ workflow.containerEngine == 'singularity' && !task.ext.singularity_pull_docker_container ? - 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/ef/eff0eafe78d5f3b65a6639265a16b89fdca88d06d18894f90fcdb50142004329/data' : - 'community.wave.seqera.io/library/multiqc:1.31--1efbafd542a23882' }" + 'https://community-cr-prod.seqera.io/docker/registry/v2/blobs/sha256/34/34e733a9ae16a27e80fe00f863ea1479c96416017f24a907996126283e7ecd4d/data' : + 'community.wave.seqera.io/library/multiqc:1.33--ee7739d47738383b' }" input: - path multiqc_files, stageAs: "?/*" + path multiqc_files, stageAs: "?/*" path(multiqc_config) path(extra_multiqc_config) path(multiqc_logo) @@ -15,10 +15,11 @@ process MULTIQC { path(sample_names) output: - path "*multiqc_report.html", emit: report - path "*_data" , emit: data - path "*_plots" , optional:true, emit: plots - path "versions.yml" , emit: versions + path "*.html" , emit: report + path "*_data" , emit: data + path "*_plots" , optional:true, emit: plots + tuple val("${task.process}"), val('multiqc'), eval('multiqc --version | sed "s/.* //g"'), emit: versions + // MultiQC should not push its versions to the `versions` topic. Its input depends on the versions topic to be resolved thus outputting to the topic will let the pipeline hang forever when: task.ext.when == null || task.ext.when @@ -26,38 +27,29 @@ process MULTIQC { script: def args = task.ext.args ?: '' def prefix = task.ext.prefix ? "--filename ${task.ext.prefix}.html" : '' - def config = multiqc_config ? "--config $multiqc_config" : '' - def extra_config = extra_multiqc_config ? "--config $extra_multiqc_config" : '' + def config = multiqc_config ? "--config ${multiqc_config}" : '' + def extra_config = extra_multiqc_config ? "--config ${extra_multiqc_config}" : '' def logo = multiqc_logo ? "--cl-config 'custom_logo: \"${multiqc_logo}\"'" : '' def replace = replace_names ? "--replace-names ${replace_names}" : '' def samples = sample_names ? "--sample-names ${sample_names}" : '' """ multiqc \\ --force \\ - $args \\ - $config \\ - $prefix \\ - $extra_config \\ - $logo \\ - $replace \\ - $samples \\ + ${args} \\ + ${config} \\ + ${prefix} \\ + ${extra_config} \\ + ${logo} \\ + ${replace} \\ + ${samples} \\ . - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - multiqc: \$( multiqc --version | sed -e "s/multiqc, version //g" ) - END_VERSIONS """ stub: """ mkdir multiqc_data + touch multiqc_data/.stub mkdir multiqc_plots touch multiqc_report.html - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - multiqc: \$( multiqc --version | sed -e "s/multiqc, version //g" ) - END_VERSIONS """ } diff --git a/modules/nf-core/multiqc/meta.yml b/modules/nf-core/multiqc/meta.yml index ce30eb73..f790cab0 100644 --- a/modules/nf-core/multiqc/meta.yml +++ b/modules/nf-core/multiqc/meta.yml @@ -57,10 +57,10 @@ input: - edam: http://edamontology.org/format_3475 # TSV output: report: - - "*multiqc_report.html": + - "*.html": type: file description: MultiQC report file - pattern: "multiqc_report.html" + pattern: ".html" ontologies: [] data: - "*_data": @@ -74,12 +74,15 @@ output: pattern: "*_data" ontologies: [] versions: - - versions.yml: - type: file - description: File containing software versions - pattern: "versions.yml" - ontologies: - - edam: http://edamontology.org/format_3750 # YAML + - - ${task.process}: + type: string + description: The process the versions were collected from + - multiqc: + type: string + description: The tool name + - multiqc --version | sed "s/.* //g": + type: eval + description: The expression to obtain the version of the tool authors: - "@abhi18av" - "@bunop" @@ -90,3 +93,27 @@ maintainers: - "@bunop" - "@drpatelh" - "@jfy133" +containers: + conda: + linux_amd64: + lock_file: https://wave.seqera.io/v1alpha1/builds/bd-d58f60e4deb769bf_1/condalock + linux_arm64: + lock_file: https://wave.seqera.io/v1alpha1/builds/bd-193776baee4194db_1/condalock + docker: + linux_amd64: + build_id: bd-d58f60e4deb769bf_1 + name: community.wave.seqera.io/library/multiqc:1.32--d58f60e4deb769bf + scanId: sc-d76ac07493e940b4_6 + linux_arm64: + build_id: bd-193776baee4194db_1 + name: community.wave.seqera.io/library/multiqc:1.32--193776baee4194db + scanId: sc-86caded0bff8246e_3 + singularity: + linux_amd64: + build_id: bd-e649ffa094d1ef4a_1 + name: oras://community.wave.seqera.io/library/multiqc:1.32--e649ffa094d1ef4a + https: https://community.wave.seqera.io/v2/library/multiqc/blobs/sha256:8c6c120d559d7ee04c7442b61ad7cf5a9e8970be5feefb37d68eeaa60c1034eb + linux_arm64: + build_id: bd-aee0064f5570ef22_1 + name: oras://community.wave.seqera.io/library/multiqc:1.32--aee0064f5570ef22 + https: https://community.wave.seqera.io/v2/library/multiqc/blobs/sha256:f02c59ebf6e9a00aa954ee8188a4ecc5c743e18f40b9215a242f67606a00f9cf diff --git a/modules/nf-core/multiqc/tests/main.nf.test b/modules/nf-core/multiqc/tests/main.nf.test index 33316a7d..c3c7297f 100644 --- a/modules/nf-core/multiqc/tests/main.nf.test +++ b/modules/nf-core/multiqc/tests/main.nf.test @@ -15,7 +15,7 @@ nextflow_process { when { process { """ - input[0] = Channel.of(file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastqc/test_fastqc.zip', checkIfExists: true)) + input[0] = channel.of(file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastqc/test_fastqc.zip', checkIfExists: true)) input[1] = [] input[2] = [] input[3] = [] @@ -30,19 +30,45 @@ nextflow_process { { assert process.success }, { assert process.out.report[0] ==~ ".*/multiqc_report.html" }, { assert process.out.data[0] ==~ ".*/multiqc_data" }, - { assert snapshot(process.out.versions).match("multiqc_versions_single") } + { assert snapshot(process.out.findAll { key, val -> key.startsWith("versions")}).match() } ) } } - test("sarscov2 single-end [fastqc] [config]") { + test("sarscov2 single-end [fastqc] - custom prefix") { + config "./custom_prefix.config" when { process { """ input[0] = Channel.of(file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastqc/test_fastqc.zip', checkIfExists: true)) - input[1] = Channel.of(file("https://github.com/nf-core/tools/raw/dev/nf_core/pipeline-template/assets/multiqc_config.yml", checkIfExists: true)) + input[1] = [] + input[2] = [] + input[3] = [] + input[4] = [] + input[5] = [] + """ + } + } + + then { + assertAll( + { assert process.success }, + { assert process.out.report[0] ==~ ".*/custom_prefix.html" }, + { assert process.out.data[0] ==~ ".*/custom_prefix_data" } + ) + } + + } + + test("sarscov2 single-end [fastqc] [config]") { + + when { + process { + """ + input[0] = channel.of(file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastqc/test_fastqc.zip', checkIfExists: true)) + input[1] = channel.of(file("https://github.com/nf-core/tools/raw/dev/nf_core/pipeline-template/assets/multiqc_config.yml", checkIfExists: true)) input[2] = [] input[3] = [] input[4] = [] @@ -56,7 +82,7 @@ nextflow_process { { assert process.success }, { assert process.out.report[0] ==~ ".*/multiqc_report.html" }, { assert process.out.data[0] ==~ ".*/multiqc_data" }, - { assert snapshot(process.out.versions).match("multiqc_versions_config") } + { assert snapshot(process.out.findAll { key, val -> key.startsWith("versions")}).match() } ) } } @@ -68,7 +94,7 @@ nextflow_process { when { process { """ - input[0] = Channel.of(file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastqc/test_fastqc.zip', checkIfExists: true)) + input[0] = channel.of(file(params.modules_testdata_base_path + 'genomics/sarscov2/illumina/fastqc/test_fastqc.zip', checkIfExists: true)) input[1] = [] input[2] = [] input[3] = [] @@ -84,7 +110,7 @@ nextflow_process { { assert snapshot(process.out.report.collect { file(it).getName() } + process.out.data.collect { file(it).getName() } + process.out.plots.collect { file(it).getName() } + - process.out.versions ).match("multiqc_stub") } + process.out.findAll { key, val -> key.startsWith("versions")} ).match() } ) } diff --git a/modules/nf-core/multiqc/tests/main.nf.test.snap b/modules/nf-core/multiqc/tests/main.nf.test.snap index e1f36138..d72d35b7 100644 --- a/modules/nf-core/multiqc/tests/main.nf.test.snap +++ b/modules/nf-core/multiqc/tests/main.nf.test.snap @@ -1,41 +1,61 @@ { - "multiqc_versions_single": { + "sarscov2 single-end [fastqc]": { "content": [ - [ - "versions.yml:md5,8968b114a3e20756d8af2b80713bcc4f" - ] + { + "versions": [ + [ + "MULTIQC", + "multiqc", + "1.33" + ] + ] + } ], "meta": { - "nf-test": "0.9.2", - "nextflow": "25.04.6" + "nf-test": "0.9.3", + "nextflow": "25.10.2" }, - "timestamp": "2025-09-08T20:57:36.139055243" + "timestamp": "2025-12-09T10:10:43.020315838" }, - "multiqc_stub": { + "sarscov2 single-end [fastqc] - stub": { "content": [ [ "multiqc_report.html", "multiqc_data", "multiqc_plots", - "versions.yml:md5,8968b114a3e20756d8af2b80713bcc4f" + { + "versions": [ + [ + "MULTIQC", + "multiqc", + "1.33" + ] + ] + } ] ], "meta": { - "nf-test": "0.9.2", - "nextflow": "25.04.6" + "nf-test": "0.9.3", + "nextflow": "25.10.2" }, - "timestamp": "2025-09-08T20:59:15.142230631" + "timestamp": "2025-12-09T10:11:14.131950776" }, - "multiqc_versions_config": { + "sarscov2 single-end [fastqc] [config]": { "content": [ - [ - "versions.yml:md5,8968b114a3e20756d8af2b80713bcc4f" - ] + { + "versions": [ + [ + "MULTIQC", + "multiqc", + "1.33" + ] + ] + } ], "meta": { - "nf-test": "0.9.2", - "nextflow": "25.04.6" + "nf-test": "0.9.3", + "nextflow": "25.10.2" }, - "timestamp": "2025-09-08T20:58:29.629087066" + "timestamp": "2025-12-09T10:11:07.15692209" } -} +} \ 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 d85a93ef..c8bad1b9 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.1 + - bioconda::openms=3.5.0 diff --git a/modules/nf-core/openms/decoydatabase/main.nf b/modules/nf-core/openms/decoydatabase/main.nf index 42494818..7c5f9b98 100644 --- a/modules/nf-core/openms/decoydatabase/main.nf +++ b/modules/nf-core/openms/decoydatabase/main.nf @@ -4,15 +4,15 @@ 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.1--h81ffffe_1' : - 'biocontainers/openms:3.4.1--h81ffffe_1' }" + 'https://depot.galaxyproject.org/singularity/openms:3.5.0--h78fb946_0' : + 'biocontainers/openms:3.5.0--h78fb946_0' }" input: tuple val(meta), path(fasta) output: tuple val(meta), path("*.fasta"), emit: decoy_fasta - path "versions.yml" , emit: versions + tuple val("${task.process}"), val('openms'), eval("FileInfo --help 2>&1 | sed -nE 's/^Version: ([0-9.]+).*/\\1/p'"), emit: versions_openms, topic: versions when: task.ext.when == null || task.ext.when @@ -27,12 +27,6 @@ process OPENMS_DECOYDATABASE { -out ${prefix}.fasta \\ -threads $task.cpus \\ $args - - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') - END_VERSIONS """ stub: @@ -41,10 +35,5 @@ process OPENMS_DECOYDATABASE { """ touch ${prefix}.fasta - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') - END_VERSIONS """ } diff --git a/modules/nf-core/openms/decoydatabase/meta.yml b/modules/nf-core/openms/decoydatabase/meta.yml index b0c13d16..bf421862 100644 --- a/modules/nf-core/openms/decoydatabase/meta.yml +++ b/modules/nf-core/openms/decoydatabase/meta.yml @@ -39,13 +39,29 @@ output: description: Fasta file containing proteins and decoy proteins pattern: "*.{fasta}" ontologies: [] + versions_openms: + - - ${task.process}: + type: string + description: The process the versions were collected from + - openms: + type: string + description: The tool name + - "FileInfo --help 2>&1 | sed -nE 's/^Version: ([0-9.]+).*/\\1/p'": + type: eval + description: The expression to obtain the version of the tool + +topics: versions: - - versions.yml: - type: file - description: File containing software versions - pattern: "versions.yml" - ontologies: - - edam: http://edamontology.org/format_3750 # YAML + - - ${task.process}: + type: string + description: The process the versions were collected from + - openms: + type: string + description: The tool name + - "FileInfo --help 2>&1 | sed -nE 's/^Version: ([0-9.]+).*/\\1/p'": + type: eval + description: The expression to obtain the version of the tool + 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 d4167208..d2f80c6f 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,11 @@ ] ], "1": [ - "versions.yml:md5,3faa02db1ca8efaa13ffb542d3a418f0" + [ + "OPENMS_DECOYDATABASE", + "openms", + "3.5.0" + ] ], "decoy_fasta": [ [ @@ -21,8 +25,12 @@ "yeast_UPS_decoy.fasta:md5,96c0295f69e0cb92b705ca4c33e6f047" ] ], - "versions": [ - "versions.yml:md5,3faa02db1ca8efaa13ffb542d3a418f0" + "versions_openms": [ + [ + "OPENMS_DECOYDATABASE", + "openms", + "3.5.0" + ] ] } ], @@ -30,6 +38,6 @@ "nf-test": "0.9.3", "nextflow": "25.04.8" }, - "timestamp": "2025-10-28T07:59:28.940912845" + "timestamp": "2026-01-12T13:14:52.51304012" } } \ 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 ad4685c0..fd1026d7 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.1" + - "bioconda::openms=3.5.0" diff --git a/modules/nf-core/openms/filefilter/main.nf b/modules/nf-core/openms/filefilter/main.nf index 55788339..6b6447b8 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.1--h81ffffe_1' : - 'biocontainers/openms:3.4.1--h81ffffe_1' }" + 'https://depot.galaxyproject.org/singularity/openms:3.5.0--h78fb946_0' : + 'biocontainers/openms:3.5.0--h78fb946_0' }" input: tuple val(meta), path(file) @@ -14,7 +14,7 @@ process OPENMS_FILEFILTER { tuple val(meta), path("*.mzML"), emit: mzml, optional: true tuple val(meta), path("*.featureXML"), emit: featurexml, optional: true tuple val(meta), path("*.consensusXML"), emit: consensusxml, optional: true - path "versions.yml" , emit: versions + tuple val("${task.process}"), val('openms'), eval("FileInfo --help 2>&1 | sed -nE 's/^Version: ([0-9.]+).*/\\1/p'"), emit: versions_openms, topic: versions when: task.ext.when == null || task.ext.when @@ -31,11 +31,6 @@ process OPENMS_FILEFILTER { -out ${prefix}.${suffix} \\ -threads $task.cpus \\ $args - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') - END_VERSIONS """ stub: @@ -46,10 +41,5 @@ process OPENMS_FILEFILTER { """ touch ${prefix}.${suffix} - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') - END_VERSIONS """ } diff --git a/modules/nf-core/openms/filefilter/meta.yml b/modules/nf-core/openms/filefilter/meta.yml index 9721f9b3..6c552c7a 100644 --- a/modules/nf-core/openms/filefilter/meta.yml +++ b/modules/nf-core/openms/filefilter/meta.yml @@ -1,5 +1,6 @@ name: "openms_filefilter" -description: Filters peptide/protein identification results by different criteria. +description: Filters peptide/protein identification results by different + criteria. keywords: - filter - mzML @@ -62,14 +63,29 @@ output: description: Filtered consensusXML file. pattern: "*.consensusXML" ontologies: [] + versions_openms: + - - ${task.process}: + type: string + description: The name of the process + - openms: + type: string + description: The name of the tool + - "FileInfo --help 2>&1 | sed -nE 's/^Version: ([0-9.]+).*/\\1/p'": + type: eval + description: The expression to obtain the version of the tool + +topics: versions: - - versions.yml: - type: file - description: File containing software version - pattern: "versions.yml" + - - ${task.process}: + type: string + description: The name of the process + - openms: + type: string + description: The name of the tool + - "FileInfo --help 2>&1 | sed -nE 's/^Version: ([0-9.]+).*/\\1/p'": + type: eval + description: The expression to obtain the version of the tool - ontologies: - - edam: http://edamontology.org/format_3750 # YAML authors: - "@jonasscheid" maintainers: diff --git a/modules/nf-core/openms/filefilter/tests/main.nf.test b/modules/nf-core/openms/filefilter/tests/main.nf.test index fb8334d1..a19a6d88 100644 --- a/modules/nf-core/openms/filefilter/tests/main.nf.test +++ b/modules/nf-core/openms/filefilter/tests/main.nf.test @@ -16,7 +16,7 @@ nextflow_process { script "../../../thermorawfileparser/main.nf" process { """ - input[0] = Channel.of([ + input[0] = channel.of([ [ id:'test'], file(params.modules_testdata_base_path + 'proteomics/msspectra/PXD012083_e005640_II.raw', checkIfExists: true) ]) 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 23a8efdd..1f481bdc 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,11 @@ ], "3": [ - "versions.yml:md5,1ea875205d6d20aea4dabd5e580f4d6a" + [ + "OPENMS_FILEFILTER", + "openms", + "3.5.0" + ] ], "consensusxml": [ @@ -59,8 +63,12 @@ "test_filtered.mzML:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], - "versions": [ - "versions.yml:md5,1ea875205d6d20aea4dabd5e580f4d6a" + "versions_openms": [ + [ + "OPENMS_FILEFILTER", + "openms", + "3.5.0" + ] ] } ], @@ -68,6 +76,6 @@ "nf-test": "0.9.3", "nextflow": "25.04.8" }, - "timestamp": "2025-10-27T13:03:04.483705593" + "timestamp": "2026-01-12T10:02:48.433471741" } } \ 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 ad4685c0..fd1026d7 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.1" + - "bioconda::openms=3.5.0" diff --git a/modules/nf-core/openms/idfilter/main.nf b/modules/nf-core/openms/idfilter/main.nf index c15927bf..e31c9897 100644 --- a/modules/nf-core/openms/idfilter/main.nf +++ b/modules/nf-core/openms/idfilter/main.nf @@ -4,15 +4,15 @@ 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.1--h81ffffe_1' : - 'biocontainers/openms:3.4.1--h81ffffe_1' }" + 'https://depot.galaxyproject.org/singularity/openms:3.5.0--h78fb946_0' : + 'biocontainers/openms:3.5.0--h78fb946_0' }" input: tuple val(meta), path(id_file), path(filter_file) output: tuple val(meta), path("*.{idXML,consensusXML}"), emit: filtered - path "versions.yml" , emit: versions + tuple val("${task.process}"), val('openms'), eval("FileInfo --help 2>&1 | sed -nE 's/^Version: ([0-9.]+).*/\\1/p'"), emit: versions_openms, topic: versions when: task.ext.when == null || task.ext.when @@ -31,12 +31,7 @@ process OPENMS_IDFILTER { -out ${prefix}.${suffix} \\ -threads $task.cpus \\ $filter \\ - $args \\ - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') - END_VERSIONS + $args """ stub: @@ -50,10 +45,5 @@ process OPENMS_IDFILTER { """ touch ${prefix}.${suffix} - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') - END_VERSIONS """ } diff --git a/modules/nf-core/openms/idfilter/meta.yml b/modules/nf-core/openms/idfilter/meta.yml index 2bab8552..4da25896 100644 --- a/modules/nf-core/openms/idfilter/meta.yml +++ b/modules/nf-core/openms/idfilter/meta.yml @@ -1,5 +1,6 @@ name: "openms_idfilter" -description: Filters peptide/protein identification results by different criteria. +description: Filters peptide/protein identification results by different + criteria. keywords: - filter - idXML @@ -44,13 +45,29 @@ output: description: Filtered peptide-spectrum matches. pattern: "*.{idXML,consensusXML}" ontologies: [] + versions_openms: + - - ${task.process}: + type: string + description: The name of the process + - openms: + type: string + description: The name of the tool + - "FileInfo --help 2>&1 | sed -nE 's/^Version: ([0-9.]+).*/\\1/p'": + type: eval + description: The expression to obtain the version of the tool + +topics: versions: - - versions.yml: - type: file - description: File containing software versions - pattern: "versions.yml" - ontologies: - - edam: http://edamontology.org/format_3750 # YAML + - - ${task.process}: + type: string + description: The name of the process + - openms: + type: string + description: The name of the tool + - "FileInfo --help 2>&1 | sed -nE 's/^Version: ([0-9.]+).*/\\1/p'": + type: eval + description: The expression to obtain the version of the tool + 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 b0f4bce3..dea78c77 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,11 @@ ] ], "1": [ - "versions.yml:md5,992aca62fe3990b1ebb21d11e999dd67" + [ + "OPENMS_IDFILTER", + "openms", + "3.5.0" + ] ], "filtered": [ [ @@ -21,8 +25,12 @@ "test.idXML:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], - "versions": [ - "versions.yml:md5,992aca62fe3990b1ebb21d11e999dd67" + "versions_openms": [ + [ + "OPENMS_IDFILTER", + "openms", + "3.5.0" + ] ] } ], @@ -30,7 +38,7 @@ "nf-test": "0.9.3", "nextflow": "25.04.8" }, - "timestamp": "2025-10-28T08:37:44.032335833" + "timestamp": "2026-01-12T10:03:17.056821477" }, "proteomics - filter - idxml": { "content": [ @@ -40,22 +48,30 @@ { "id": "test" }, - "test.idXML:md5,b91c37a92b2d037368cfedde120dc845" + "test.idXML:md5,3231d9c0cd1838db70a576f505ed1a21" ] ], "1": [ - "versions.yml:md5,992aca62fe3990b1ebb21d11e999dd67" + [ + "OPENMS_IDFILTER", + "openms", + "3.5.0" + ] ], "filtered": [ [ { "id": "test" }, - "test.idXML:md5,b91c37a92b2d037368cfedde120dc845" + "test.idXML:md5,3231d9c0cd1838db70a576f505ed1a21" ] ], - "versions": [ - "versions.yml:md5,992aca62fe3990b1ebb21d11e999dd67" + "versions_openms": [ + [ + "OPENMS_IDFILTER", + "openms", + "3.5.0" + ] ] } ], @@ -63,6 +79,6 @@ "nf-test": "0.9.3", "nextflow": "25.04.8" }, - "timestamp": "2025-10-28T08:37:18.617593794" + "timestamp": "2026-01-12T10:03:04.798826665" } } \ No newline at end of file diff --git a/modules/nf-core/openms/idmassaccuracy/meta.yml b/modules/nf-core/openms/idmassaccuracy/meta.yml deleted file mode 100644 index 7417d69d..00000000 --- a/modules/nf-core/openms/idmassaccuracy/meta.yml +++ /dev/null @@ -1,72 +0,0 @@ -name: "openms_idmassaccuracy" -description: Calculates a distribution of the mass error from given mass spectra and - IDs. -keywords: - - mass_error - - openms - - proteomics -tools: - - "openms": - description: "OpenMS is an open-source software C++ library for LC-MS data management - and analyses" - homepage: "https://openms.de" - documentation: "https://openms.readthedocs.io/en/latest/index.html" - tool_dev_url: "https://github.com/OpenMS/OpenMS" - doi: "10.1038/s41592-024-02197-7" - licence: ["BSD"] - identifier: "" - -input: - - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. `[ id:'test' ]` - - mzmls: - type: file - description: | - 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: - type: map - description: | - Groovy Map containing sample information - e.g. `[ id:'test' ]` - - "*frag_mass_err.tsv": - type: file - description: TSV file containing the fragment mass errors - pattern: "*frag_mass_err.{tsv}" - ontologies: - - edam: http://edamontology.org/format_3475 # TSV - prec_err: - - - meta: - type: map - description: | - Groovy Map containing sample information - e.g. `[ id:'test' ]` - - "*prec_mass_err.tsv": - type: file - description: Optional TSV file containing the precursor mass errors - pattern: "*prec_mass_err.{tsv}" - 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 b/modules/nf-core/openms/idmassaccuracy/tests/main.nf.test deleted file mode 100644 index b267fe15..00000000 --- a/modules/nf-core/openms/idmassaccuracy/tests/main.nf.test +++ /dev/null @@ -1,81 +0,0 @@ -nextflow_process { - - name "Test Process OPENMS_IDMASSACCURACY" - script "../main.nf" - process "OPENMS_IDMASSACCURACY" - config "./nextflow.config" - - tag "modules" - tag "modules_nfcore" - tag "openms" - tag "openms/idmassaccuracy" - tag "thermorawfileparser" - tag "openms/decoydatabase" - tag "openmsthirdparty/cometadapter" - - setup { - run("THERMORAWFILEPARSER") { - script "../../../thermorawfileparser/main.nf" - process { - """ - input[0] = Channel.of([ - [ id:'test'], - file(params.modules_testdata_base_path + 'proteomics/msspectra/PXD012083_e005640_II.raw', checkIfExists: true) - ]) - """ - } - } - run("OPENMS_DECOYDATABASE") { - script "../../../openms/decoydatabase/main.nf" - process { - """ - input[0] = Channel.of([ - [ id:'test'], - file(params.modules_testdata_base_path + 'proteomics/database/UP000005640_9606.fasta', checkIfExists: true) - ]) - """ - } - } - run("OPENMSTHIRDPARTY_COMETADAPTER") { - script "../../../openmsthirdparty/cometadapter/main.nf" - process { - """ - input[0] = THERMORAWFILEPARSER.out.spectra.join(OPENMS_DECOYDATABASE.out.decoy_fasta) - """ - } - } - } - - test("proteomics - openms - mass_error") { - when { - process { - """ - input[0] = THERMORAWFILEPARSER.out.spectra.join(OPENMSTHIRDPARTY_COMETADAPTER.out.idxml) - """ - } - } - then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) - } - } - - test("proteomics - openms - mass_error - stub") { - options "-stub" - when { - process { - """ - input[0] = THERMORAWFILEPARSER.out.spectra.join(OPENMSTHIRDPARTY_COMETADAPTER.out.idxml) - """ - } - } - then { - assertAll( - { assert process.success }, - { assert snapshot(process.out).match() } - ) - } - } -} diff --git a/modules/nf-core/openms/idmassaccuracy/tests/main.nf.test.snap b/modules/nf-core/openms/idmassaccuracy/tests/main.nf.test.snap deleted file mode 100644 index 69fce941..00000000 --- a/modules/nf-core/openms/idmassaccuracy/tests/main.nf.test.snap +++ /dev/null @@ -1,90 +0,0 @@ -{ - "proteomics - openms - mass_error - stub": { - "content": [ - { - "0": [ - [ - { - "id": "test" - }, - "test_frag_mass_err.tsv:md5,d41d8cd98f00b204e9800998ecf8427e" - ] - ], - "1": [ - [ - { - "id": "test" - }, - "test_prec_mass_err.tsv:md5,d41d8cd98f00b204e9800998ecf8427e" - ] - ], - "2": [ - "versions.yml:md5,1957953273bbbb30ee405df5972c299a" - ], - "frag_err": [ - [ - { - "id": "test" - }, - "test_frag_mass_err.tsv:md5,d41d8cd98f00b204e9800998ecf8427e" - ] - ], - "prec_err": [ - [ - { - "id": "test" - }, - "test_prec_mass_err.tsv:md5,d41d8cd98f00b204e9800998ecf8427e" - ] - ], - "versions": [ - "versions.yml:md5,1957953273bbbb30ee405df5972c299a" - ] - } - ], - "meta": { - "nf-test": "0.9.3", - "nextflow": "25.04.8" - }, - "timestamp": "2025-10-28T08:11:12.815918913" - }, - "proteomics - openms - mass_error": { - "content": [ - { - "0": [ - [ - { - "id": "test" - }, - "test_frag_mass_err.tsv:md5,b3bf5d66998d83bd69199395843f37e5" - ] - ], - "1": [ - - ], - "2": [ - "versions.yml:md5,1957953273bbbb30ee405df5972c299a" - ], - "frag_err": [ - [ - { - "id": "test" - }, - "test_frag_mass_err.tsv:md5,b3bf5d66998d83bd69199395843f37e5" - ] - ], - "prec_err": [ - - ], - "versions": [ - "versions.yml:md5,1957953273bbbb30ee405df5972c299a" - ] - } - ], - "meta": { - "nf-test": "0.9.3", - "nextflow": "25.04.8" - }, - "timestamp": "2025-10-28T08:10:28.906846753" - } -} \ No newline at end of file diff --git a/modules/nf-core/openms/idmassaccuracy/tests/nextflow.config b/modules/nf-core/openms/idmassaccuracy/tests/nextflow.config deleted file mode 100644 index d104b313..00000000 --- a/modules/nf-core/openms/idmassaccuracy/tests/nextflow.config +++ /dev/null @@ -1,27 +0,0 @@ -process { - - withName:OPENMSTHIRDPARTY_COMETADAPTER { - ext.args = [ - "-instrument low_res", - "-fragment_bin_offset 0.4", - "-precursor_mass_tolerance 5", - "-precursor_error_units 'ppm'", - "-fragment_mass_tolerance 0.50025", - "-digest_mass_range '800:5000'", - "-max_variable_mods_in_peptide 1", - "-precursor_charge '2:5'", - "-activation_method 'CID'", - "-variable_modifications 'Oxidation (M)'", - "-enzyme 'unspecific cleavage'", - "-spectrum_batch_size 0" - ].join(' ').trim() - } - - withName:OPENMS_IDMASSACCURACY { - ext.args = [ - "-precursor_error_ppm", - "-fragment_mass_tolerance 0.50025" - ].join(' ').trim() - } - -} diff --git a/modules/nf-core/openms/idmerger/environment.yml b/modules/nf-core/openms/idmerger/environment.yml index d85a93ef..c8bad1b9 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.1 + - bioconda::openms=3.5.0 diff --git a/modules/nf-core/openms/idmerger/main.nf b/modules/nf-core/openms/idmerger/main.nf index 421a77f8..ff93ee06 100644 --- a/modules/nf-core/openms/idmerger/main.nf +++ b/modules/nf-core/openms/idmerger/main.nf @@ -4,15 +4,15 @@ 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.1--h81ffffe_1' : - 'biocontainers/openms:3.4.1--h81ffffe_1' }" + 'https://depot.galaxyproject.org/singularity/openms:3.5.0--h78fb946_0' : + 'biocontainers/openms:3.5.0--h78fb946_0' }" input: tuple val(meta), path(idxmls) output: tuple val(meta), path("*.idXML"), emit: idxml - path "versions.yml" , emit: versions + tuple val("${task.process}"), val('openms'), eval("FileInfo --help 2>&1 | sed -nE 's/^Version: ([0-9.]+).*/\\1/p'"), emit: versions_openms, topic: versions when: task.ext.when == null || task.ext.when @@ -27,11 +27,6 @@ process OPENMS_IDMERGER { -out ${prefix}.idXML \\ -threads $task.cpus \\ $args - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') - END_VERSIONS """ stub: @@ -40,10 +35,5 @@ process OPENMS_IDMERGER { """ touch ${prefix}.idXML - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') - END_VERSIONS """ } diff --git a/modules/nf-core/openms/idmerger/meta.yml b/modules/nf-core/openms/idmerger/meta.yml index 002fc578..379a5888 100644 --- a/modules/nf-core/openms/idmerger/meta.yml +++ b/modules/nf-core/openms/idmerger/meta.yml @@ -41,12 +41,28 @@ output: description: Merged idXML output file pattern: "*.{idXML}" ontologies: [] + versions_openms: + - - ${task.process}: + type: string + description: The name of the process + - openms: + type: string + description: The name of the tool + - "FileInfo --help 2>&1 | sed -nE 's/^Version: ([0-9.]+).*/\\1/p'": + type: eval + description: The expression to obtain the version of the tool + +topics: versions: - - versions.yml: - type: file - description: File containing software versions - pattern: "versions.yml" - ontologies: - - edam: http://edamontology.org/format_3750 # YAML + - - ${task.process}: + type: string + description: The name of the process + - openms: + type: string + description: The name of the tool + - "FileInfo --help 2>&1 | sed -nE 's/^Version: ([0-9.]+).*/\\1/p'": + type: eval + description: The expression to obtain the version of the tool + authors: - "@jonasscheid" diff --git a/modules/nf-core/openms/idmerger/tests/main.nf.test b/modules/nf-core/openms/idmerger/tests/main.nf.test index 8945e091..006eb57b 100644 --- a/modules/nf-core/openms/idmerger/tests/main.nf.test +++ b/modules/nf-core/openms/idmerger/tests/main.nf.test @@ -14,7 +14,7 @@ nextflow_process { when { process { """ - input[0] = Channel.of([ + input[0] = channel.of([ [ id:'test'], // meta map [ file(params.modules_testdata_base_path + 'proteomics/openms/HepG2_rep1_small.idXML', checkIfExists: true), file(params.modules_testdata_base_path + 'proteomics/openms/HepG2_rep2_small.idXML', checkIfExists: true)] @@ -26,8 +26,8 @@ nextflow_process { then { assertAll( { assert process.success }, - { assert snapshot(process.out.versions).match()}, - + { assert snapshot(process.out.versions_openms).match()}, + // check single line substrings in output idxml file { assert path(process.out.idxml.get(0).get(1)).readLines().any { it.contains("") }}, { assert path(process.out.idxml.get(0).get(1)).readLines().any { it.contains("") }}, @@ -45,7 +45,7 @@ nextflow_process { when { process { """ - input[0] = Channel.of([ + input[0] = channel.of([ [ id:'test'], // meta map [ file(params.modules_testdata_base_path + 'proteomics/openms/HepG2_rep1_small.idXML', checkIfExists: true), file(params.modules_testdata_base_path + 'proteomics/openms/HepG2_rep2_small.idXML', checkIfExists: true)] 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 a2edce86..13e6f7a8 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,18 @@ "proteomics - openms - idxml": { "content": [ [ - "versions.yml:md5,80b0fb4560c930fd7b9c31dbbd3f66d2" + [ + "OPENMS_IDMERGER", + "openms", + "3.5.0" + ] ] ], "meta": { "nf-test": "0.9.3", "nextflow": "25.04.8" }, - "timestamp": "2025-10-28T08:54:12.914656629" + "timestamp": "2026-01-12T10:06:10.948172124" }, "proteomics - openms - idxml - stub": { "content": [ @@ -23,7 +27,11 @@ ] ], "1": [ - "versions.yml:md5,80b0fb4560c930fd7b9c31dbbd3f66d2" + [ + "OPENMS_IDMERGER", + "openms", + "3.5.0" + ] ], "idxml": [ [ @@ -33,8 +41,12 @@ "test.idXML:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], - "versions": [ - "versions.yml:md5,80b0fb4560c930fd7b9c31dbbd3f66d2" + "versions_openms": [ + [ + "OPENMS_IDMERGER", + "openms", + "3.5.0" + ] ] } ], @@ -42,6 +54,6 @@ "nf-test": "0.9.3", "nextflow": "25.04.8" }, - "timestamp": "2025-10-28T08:54:41.780756135" + "timestamp": "2026-01-12T10:06:23.802686751" } } \ 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 ad4685c0..fd1026d7 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.1" + - "bioconda::openms=3.5.0" diff --git a/modules/nf-core/openms/idripper/main.nf b/modules/nf-core/openms/idripper/main.nf index e545b906..7086be23 100644 --- a/modules/nf-core/openms/idripper/main.nf +++ b/modules/nf-core/openms/idripper/main.nf @@ -4,15 +4,15 @@ 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.1--h81ffffe_1': - 'biocontainers/openms:3.4.1--h81ffffe_1' }" + 'https://depot.galaxyproject.org/singularity/openms:3.5.0--h78fb946_0': + 'biocontainers/openms:3.5.0--h78fb946_0' }" input: tuple val(meta), path(merged_idxml) output: tuple val(meta), path("*.idXML"), emit: idxmls - path "versions.yml" , emit: versions + tuple val("${task.process}"), val('openms'), eval("FileInfo --help 2>&1 | sed -nE 's/^Version: ([0-9.]+).*/\\1/p'"), emit: versions_openms, topic: versions when: task.ext.when == null || task.ext.when @@ -27,11 +27,6 @@ process OPENMS_IDRIPPER { -out . \\ -threads $task.cpus \\ $args - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') - END_VERSIONS """ stub: @@ -41,10 +36,5 @@ process OPENMS_IDRIPPER { """ touch ${prefix}_1.idXML touch ${prefix}_2.idXML - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') - END_VERSIONS """ } diff --git a/modules/nf-core/openms/idripper/meta.yml b/modules/nf-core/openms/idripper/meta.yml index 72e62935..47ee04f5 100644 --- a/modules/nf-core/openms/idripper/meta.yml +++ b/modules/nf-core/openms/idripper/meta.yml @@ -1,6 +1,6 @@ name: openms_idripper -description: Split a merged identification file into their originating identification - files +description: Split a merged identification file into their originating + identification files keywords: - split - idXML @@ -40,13 +40,29 @@ output: description: Multiple idXML files pattern: "*.{idXML}" ontologies: [] + versions_openms: + - - ${task.process}: + type: string + description: The name of the process + - openms: + type: string + description: The name of the tool + - "FileInfo --help 2>&1 | sed -nE 's/^Version: ([0-9.]+).*/\\1/p'": + type: eval + description: The expression to obtain the version of the tool + +topics: versions: - - versions.yml: - type: file - description: File containing software versions - pattern: "versions.yml" - ontologies: - - edam: http://edamontology.org/format_3750 # YAML + - - ${task.process}: + type: string + description: The name of the process + - openms: + type: string + description: The name of the tool + - "FileInfo --help 2>&1 | sed -nE 's/^Version: ([0-9.]+).*/\\1/p'": + type: eval + description: The expression to obtain the version of the tool + authors: - "@jonasscheid" maintainers: diff --git a/modules/nf-core/openms/idripper/tests/main.nf.test b/modules/nf-core/openms/idripper/tests/main.nf.test index 1e9b40d7..1f252316 100644 --- a/modules/nf-core/openms/idripper/tests/main.nf.test +++ b/modules/nf-core/openms/idripper/tests/main.nf.test @@ -16,7 +16,7 @@ nextflow_process { script "../../idmerger/main.nf" process { """ - input[0] = Channel.fromList([ + input[0] = channel.fromList([ tuple([id:'test'], [ file(params.modules_testdata_base_path + 'proteomics/openms/HepG2_rep1_small.idXML', checkIfExists: true), 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 6192f348..07853ac9 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,11 @@ ] ], "1": [ - "versions.yml:md5,3949806b2abeb3db36c6dc0596f39a14" + [ + "OPENMS_IDRIPPER", + "openms", + "3.5.0" + ] ], "idxmls": [ [ @@ -27,8 +31,12 @@ ] ] ], - "versions": [ - "versions.yml:md5,3949806b2abeb3db36c6dc0596f39a14" + "versions_openms": [ + [ + "OPENMS_IDRIPPER", + "openms", + "3.5.0" + ] ] } ], @@ -36,7 +44,7 @@ "nf-test": "0.9.3", "nextflow": "25.04.8" }, - "timestamp": "2025-10-28T08:55:11.687007226" + "timestamp": "2026-01-12T10:06:47.478212501" }, "proteomics - split - idxml - stub": { "content": [ @@ -53,7 +61,11 @@ ] ], "1": [ - "versions.yml:md5,3949806b2abeb3db36c6dc0596f39a14" + [ + "OPENMS_IDRIPPER", + "openms", + "3.5.0" + ] ], "idxmls": [ [ @@ -66,8 +78,12 @@ ] ] ], - "versions": [ - "versions.yml:md5,3949806b2abeb3db36c6dc0596f39a14" + "versions_openms": [ + [ + "OPENMS_IDRIPPER", + "openms", + "3.5.0" + ] ] } ], @@ -75,6 +91,6 @@ "nf-test": "0.9.3", "nextflow": "25.04.8" }, - "timestamp": "2025-10-28T08:55:38.405209447" + "timestamp": "2026-01-12T10:07:10.700393001" } } \ 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 ad4685c0..fd1026d7 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.1" + - "bioconda::openms=3.5.0" diff --git a/modules/nf-core/openms/idscoreswitcher/main.nf b/modules/nf-core/openms/idscoreswitcher/main.nf index 6911b2c5..0f4afdc2 100644 --- a/modules/nf-core/openms/idscoreswitcher/main.nf +++ b/modules/nf-core/openms/idscoreswitcher/main.nf @@ -4,15 +4,15 @@ 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.1--h81ffffe_1': - 'biocontainers/openms:3.4.1--h81ffffe_1' }" + 'https://depot.galaxyproject.org/singularity/openms:3.5.0--h78fb946_0': + 'biocontainers/openms:3.5.0--h78fb946_0' }" input: tuple val(meta), path(idxml) output: tuple val(meta), path("*.idXML"), emit: idxml - path "versions.yml" , emit: versions + tuple val("${task.process}"), val('openms'), eval("FileInfo --help 2>&1 | sed -nE 's/^Version: ([0-9.]+).*/\\1/p'"), emit: versions_openms, topic: versions when: task.ext.when == null || task.ext.when @@ -28,11 +28,6 @@ process OPENMS_IDSCORESWITCHER { -out ${prefix}.idXML \\ -threads $task.cpus \\ $args - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') - END_VERSIONS """ stub: @@ -42,10 +37,5 @@ process OPENMS_IDSCORESWITCHER { """ touch ${prefix}.idXML - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') - END_VERSIONS """ } diff --git a/modules/nf-core/openms/idscoreswitcher/meta.yml b/modules/nf-core/openms/idscoreswitcher/meta.yml index 2a00b66b..fe1fbd3e 100644 --- a/modules/nf-core/openms/idscoreswitcher/meta.yml +++ b/modules/nf-core/openms/idscoreswitcher/meta.yml @@ -1,6 +1,6 @@ name: "openms_idscoreswitcher" -description: Switches between different scores of peptide or protein hits in identification - data +description: Switches between different scores of peptide or protein hits in + identification data keywords: - switch - score @@ -43,13 +43,29 @@ output: obtained from a specified meta value pattern: "*.{idXML}" ontologies: [] + versions_openms: + - - ${task.process}: + type: string + description: The name of the process + - openms: + type: string + description: The name of the tool + - "FileInfo --help 2>&1 | sed -nE 's/^Version: ([0-9.]+).*/\\1/p'": + type: eval + description: The expression to obtain the version of the tool + +topics: versions: - - versions.yml: - type: file - description: File containing software versions - pattern: "versions.yml" - ontologies: - - edam: http://edamontology.org/format_3750 # YAML + - - ${task.process}: + type: string + description: The name of the process + - openms: + type: string + description: The name of the tool + - "FileInfo --help 2>&1 | sed -nE 's/^Version: ([0-9.]+).*/\\1/p'": + type: eval + description: The expression to obtain the version of the tool + 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 c9d84825..35fe46f0 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,11 @@ ] ], "1": [ - "versions.yml:md5,658341a6b21a155b1c141c94c54c4ae3" + [ + "OPENMS_IDSCORESWITCHER", + "openms", + "3.5.0" + ] ], "idxml": [ [ @@ -21,8 +25,12 @@ "test.idXML:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], - "versions": [ - "versions.yml:md5,658341a6b21a155b1c141c94c54c4ae3" + "versions_openms": [ + [ + "OPENMS_IDSCORESWITCHER", + "openms", + "3.5.0" + ] ] } ], @@ -30,7 +38,7 @@ "nf-test": "0.9.3", "nextflow": "25.04.8" }, - "timestamp": "2025-10-28T09:04:11.118518193" + "timestamp": "2026-01-12T10:07:57.184605459" }, "proteomics - switch_score - idxml": { "content": [ @@ -44,7 +52,11 @@ ] ], "1": [ - "versions.yml:md5,658341a6b21a155b1c141c94c54c4ae3" + [ + "OPENMS_IDSCORESWITCHER", + "openms", + "3.5.0" + ] ], "idxml": [ [ @@ -54,8 +66,12 @@ "test.idXML:md5,0db3dfe3dc491ec94ebd951ca6e2c2e4" ] ], - "versions": [ - "versions.yml:md5,658341a6b21a155b1c141c94c54c4ae3" + "versions_openms": [ + [ + "OPENMS_IDSCORESWITCHER", + "openms", + "3.5.0" + ] ] } ], @@ -63,6 +79,6 @@ "nf-test": "0.9.3", "nextflow": "25.04.8" }, - "timestamp": "2025-10-28T09:03:44.673575882" + "timestamp": "2026-01-12T10:07:32.62082728" } } \ 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 664bf59d..7b287592 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.1" + - "bioconda::openms=3.5.0" diff --git a/modules/nf-core/openms/peakpickerhires/main.nf b/modules/nf-core/openms/peakpickerhires/main.nf index 9ac6e935..c30b79aa 100644 --- a/modules/nf-core/openms/peakpickerhires/main.nf +++ b/modules/nf-core/openms/peakpickerhires/main.nf @@ -4,15 +4,15 @@ 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.1--h81ffffe_1' : - 'biocontainers/openms:3.4.1--h81ffffe_1' }" + 'https://depot.galaxyproject.org/singularity/openms:3.5.0--h78fb946_0' : + 'biocontainers/openms:3.5.0--h78fb946_0' }" input: tuple val(meta), path(mzml) output: tuple val(meta), path("*.mzML"), emit: mzml - path "versions.yml" , emit: versions + tuple val("${task.process}"), val('openms'), eval("FileInfo --help 2>&1 | sed -nE 's/^Version: ([0-9.]+).*/\\1/p'"), emit: versions_openms, topic: versions when: task.ext.when == null || task.ext.when @@ -27,11 +27,6 @@ process OPENMS_PEAKPICKERHIRES { -out ${prefix}.mzML \\ -threads $task.cpus \\ $args - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') - END_VERSIONS """ stub: @@ -40,10 +35,5 @@ process OPENMS_PEAKPICKERHIRES { """ touch ${prefix}.mzML - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') - END_VERSIONS """ } diff --git a/modules/nf-core/openms/peakpickerhires/meta.yml b/modules/nf-core/openms/peakpickerhires/meta.yml index db8feaad..100c5b19 100644 --- a/modules/nf-core/openms/peakpickerhires/meta.yml +++ b/modules/nf-core/openms/peakpickerhires/meta.yml @@ -1,6 +1,6 @@ name: "openms_peakpickerhires" -description: A tool for peak detection in high-resolution profile data (Orbitrap or - FTICR) +description: A tool for peak detection in high-resolution profile data (Orbitrap + or FTICR) keywords: - peak picking - mzml @@ -40,13 +40,29 @@ output: description: Peak-picked mass spectrometer output file in mzML format pattern: "*.{mzML}" ontologies: [] + versions_openms: + - - ${task.process}: + type: string + description: The name of the process + - openms: + type: string + description: The name of the tool + - "FileInfo --help 2>&1 | sed -nE 's/^Version: ([0-9.]+).*/\\1/p'": + type: eval + description: The expression to obtain the version of the tool + +topics: versions: - - versions.yml: - type: file - description: File containing software versions - pattern: "versions.yml" - ontologies: - - edam: http://edamontology.org/format_3750 # YAML + - - ${task.process}: + type: string + description: The name of the process + - openms: + type: string + description: The name of the tool + - "FileInfo --help 2>&1 | sed -nE 's/^Version: ([0-9.]+).*/\\1/p'": + type: eval + description: The expression to obtain the version of the tool + authors: - "@jonasscheid" maintainers: diff --git a/modules/nf-core/openms/peakpickerhires/tests/main.nf.test b/modules/nf-core/openms/peakpickerhires/tests/main.nf.test index df2071c4..563aa777 100644 --- a/modules/nf-core/openms/peakpickerhires/tests/main.nf.test +++ b/modules/nf-core/openms/peakpickerhires/tests/main.nf.test @@ -26,7 +26,7 @@ nextflow_process { assertAll( { assert process.success }, { assert path(process.out.mzml.get(0).get(1)).readLines().contains('\t\t\t') }, - { assert snapshot(process.out.versions).match() } + { assert snapshot(process.out.versions_openms).match() } ) } 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 83f15738..a3d88062 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,18 @@ "proteomics - mzML": { "content": [ [ - "versions.yml:md5,69c600d25edebd411ef84718668821df" + [ + "OPENMS_PEAKPICKERHIRES", + "openms", + "3.5.0" + ] ] ], "meta": { "nf-test": "0.9.3", "nextflow": "25.04.8" }, - "timestamp": "2025-10-28T09:07:00.776951188" + "timestamp": "2026-01-12T10:08:19.636849899" }, "proteomics - mzML - stub": { "content": [ @@ -23,7 +27,11 @@ ] ], "1": [ - "versions.yml:md5,69c600d25edebd411ef84718668821df" + [ + "OPENMS_PEAKPICKERHIRES", + "openms", + "3.5.0" + ] ], "mzml": [ [ @@ -33,8 +41,12 @@ "test_stub.mzML:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], - "versions": [ - "versions.yml:md5,69c600d25edebd411ef84718668821df" + "versions_openms": [ + [ + "OPENMS_PEAKPICKERHIRES", + "openms", + "3.5.0" + ] ] } ], @@ -42,6 +54,6 @@ "nf-test": "0.9.3", "nextflow": "25.04.8" }, - "timestamp": "2025-10-28T09:07:18.50818535" + "timestamp": "2026-01-12T10:08:41.181970232" } } \ 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 ad4685c0..fd1026d7 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.1" + - "bioconda::openms=3.5.0" diff --git a/modules/nf-core/openms/peptideindexer/main.nf b/modules/nf-core/openms/peptideindexer/main.nf index 1456a908..d94a0257 100644 --- a/modules/nf-core/openms/peptideindexer/main.nf +++ b/modules/nf-core/openms/peptideindexer/main.nf @@ -4,15 +4,15 @@ 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.1--h81ffffe_1' : - 'biocontainers/openms:3.4.1--h81ffffe_1' }" + 'https://depot.galaxyproject.org/singularity/openms:3.5.0--h78fb946_0' : + 'biocontainers/openms:3.5.0--h78fb946_0' }" input: tuple val(meta), path(idxml), path(fasta) output: tuple val(meta), path("*.idXML"), emit: indexed_idxml - path "versions.yml" , emit: versions + tuple val("${task.process}"), val('openms'), eval("FileInfo --help 2>&1 | sed -nE 's/^Version: ([0-9.]+).*/\\1/p'"), emit: versions_openms, topic: versions when: task.ext.when == null || task.ext.when @@ -30,11 +30,6 @@ process OPENMS_PEPTIDEINDEXER { -out ${prefix}.idXML \\ -threads $task.cpus \\ $args - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') - END_VERSIONS """ stub: @@ -43,10 +38,5 @@ process OPENMS_PEPTIDEINDEXER { """ touch ${prefix}.idXML - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - openms: \$(echo \$(FileInfo --help 2>&1) | sed 's/^.*Version: //; s/-.*\$//' | sed 's/ -*//; s/ .*\$//') - END_VERSIONS """ } diff --git a/modules/nf-core/openms/peptideindexer/meta.yml b/modules/nf-core/openms/peptideindexer/meta.yml index 1c200b5d..a635472f 100644 --- a/modules/nf-core/openms/peptideindexer/meta.yml +++ b/modules/nf-core/openms/peptideindexer/meta.yml @@ -43,13 +43,29 @@ output: description: Refreshed idXML identification file pattern: "*.idXML" ontologies: [] + versions_openms: + - - ${task.process}: + type: string + description: The name of the process + - openms: + type: string + description: The name of the tool + - "FileInfo --help 2>&1 | sed -nE 's/^Version: ([0-9.]+).*/\\1/p'": + type: eval + description: The expression to obtain the version of the tool + +topics: versions: - - versions.yml: - type: file - description: File containing software versions - pattern: "versions.yml" - ontologies: - - edam: http://edamontology.org/format_3750 # YAML + - - ${task.process}: + type: string + description: The name of the process + - openms: + type: string + description: The name of the tool + - "FileInfo --help 2>&1 | sed -nE 's/^Version: ([0-9.]+).*/\\1/p'": + type: eval + description: The expression to obtain the version of the tool + authors: - "@jonasscheid" maintainers: diff --git a/modules/nf-core/openms/peptideindexer/tests/main.nf.test b/modules/nf-core/openms/peptideindexer/tests/main.nf.test index ecc2b005..c4533b2e 100644 --- a/modules/nf-core/openms/peptideindexer/tests/main.nf.test +++ b/modules/nf-core/openms/peptideindexer/tests/main.nf.test @@ -16,7 +16,7 @@ nextflow_process { script "../../decoydatabase/main.nf" process { """ - input[0] = Channel.of([ + input[0] = channel.of([ [ id:'test'], file(params.modules_testdata_base_path + 'proteomics/database/UP000005640_9606.fasta', checkIfExists: true) ]) @@ -30,7 +30,7 @@ nextflow_process { when { process { """ - input[0] = Channel.of([ + input[0] = channel.of([ [id:'test'], file(params.modules_testdata_base_path + 'proteomics/openms/HepG2_rep1_small.idXML', checkIfExists: true) ]).join(OPENMS_DECOYDATABASE.out.decoy_fasta) @@ -53,7 +53,7 @@ nextflow_process { when { process { """ - input[0] = Channel.of([ + input[0] = channel.of([ [id:'test'], file(params.modules_testdata_base_path + 'proteomics/openms/HepG2_rep1_small.idXML', checkIfExists: true) ]).join(OPENMS_DECOYDATABASE.out.decoy_fasta) 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 0aa17984..9c849cb4 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,11 @@ ] ], "1": [ - "versions.yml:md5,c2965a55db2530b792b1620a935107d2" + [ + "OPENMS_PEPTIDEINDEXER", + "openms", + "3.5.0" + ] ], "indexed_idxml": [ [ @@ -21,8 +25,12 @@ "test_indexed.idXML:md5,ab771bf6bec1b88babd608cbf3b57144" ] ], - "versions": [ - "versions.yml:md5,c2965a55db2530b792b1620a935107d2" + "versions_openms": [ + [ + "OPENMS_PEPTIDEINDEXER", + "openms", + "3.5.0" + ] ] } ], @@ -30,7 +38,7 @@ "nf-test": "0.9.3", "nextflow": "25.04.8" }, - "timestamp": "2025-10-28T08:11:48.453753483" + "timestamp": "2026-01-12T10:09:11.498692207" }, "proteomics - refresh_idxml - stub": { "content": [ @@ -44,7 +52,11 @@ ] ], "1": [ - "versions.yml:md5,c2965a55db2530b792b1620a935107d2" + [ + "OPENMS_PEPTIDEINDEXER", + "openms", + "3.5.0" + ] ], "indexed_idxml": [ [ @@ -54,8 +66,12 @@ "test_indexed.idXML:md5,d41d8cd98f00b204e9800998ecf8427e" ] ], - "versions": [ - "versions.yml:md5,c2965a55db2530b792b1620a935107d2" + "versions_openms": [ + [ + "OPENMS_PEPTIDEINDEXER", + "openms", + "3.5.0" + ] ] } ], @@ -63,6 +79,6 @@ "nf-test": "0.9.3", "nextflow": "25.04.8" }, - "timestamp": "2025-10-28T08:12:25.400421367" + "timestamp": "2026-01-12T10:09:30.793034749" } } \ 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 7e9c2818..45f695a6 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.1" + - "bioconda::openms-thirdparty=3.5.0" diff --git a/modules/nf-core/openmsthirdparty/cometadapter/main.nf b/modules/nf-core/openmsthirdparty/cometadapter/main.nf index 27fc32fd..14e85a3f 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.1--h9ee0642_1' : - 'biocontainers/openms-thirdparty:3.4.1--h9ee0642_1' }" + 'https://depot.galaxyproject.org/singularity/openms-thirdparty:3.5.0--h9ee0642_0' : + 'biocontainers/openms-thirdparty:3.5.0--h9ee0642_0' }" input: tuple val(meta), path(mzml), path(fasta) @@ -13,7 +13,8 @@ process OPENMSTHIRDPARTY_COMETADAPTER { output: tuple val(meta), path("*.idXML"), emit: idxml tuple val(meta), path("*.tsv") , emit: pin, optional: true - path "versions.yml" , emit: versions + tuple val("${task.process}"), val('CometAdapter'), eval("CometAdapter --help 2>&1 | sed -nE 's/^Version: ([0-9.]+).*/\\1/p'"), emit: versions_cometadapter, topic: versions + tuple val("${task.process}"), val('Comet'), eval("comet 2>&1 | sed -n 's/.*Comet version \" *\\(.*\\)\".*/\\1/p'"), emit: versions_comet, topic: versions when: task.ext.when == null || task.ext.when @@ -29,13 +30,6 @@ process OPENMSTHIRDPARTY_COMETADAPTER { -out ${prefix}.idXML \\ -threads $task.cpus \\ $args - - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - CometAdapter: \$(CometAdapter 2>&1 | grep -E '^Version(.*)' | sed 's/Version: //g' | cut -d ' ' -f 1 | cut -d '-' -f 1) - Comet: \$(comet 2>&1 | grep -E "Comet version.*" | sed 's/Comet version //g' | sed 's/"//g') - END_VERSIONS """ stub: @@ -45,11 +39,5 @@ process OPENMSTHIRDPARTY_COMETADAPTER { """ touch ${prefix}.idXML touch ${prefix}_pin.tsv - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - CometAdapter: \$(CometAdapter 2>&1 | grep -E '^Version(.*)' | sed 's/Version: //g' | cut -d ' ' -f 1 | cut -d '-' -f 1) - Comet: \$(comet 2>&1 | grep -E "Comet version.*" | sed 's/Comet version //g' | sed 's/"//g') - END_VERSIONS """ } diff --git a/modules/nf-core/openmsthirdparty/cometadapter/meta.yml b/modules/nf-core/openmsthirdparty/cometadapter/meta.yml index 50c1e1e4..70cda434 100644 --- a/modules/nf-core/openmsthirdparty/cometadapter/meta.yml +++ b/modules/nf-core/openmsthirdparty/cometadapter/meta.yml @@ -16,7 +16,18 @@ tools: doi: "10.1038/s41592-024-02197-7" licence: ["BSD"] identifier: "" + - CometAdapter: + description: "Annotates MS/MS spectra using Comet." + homepage: "https://openms.de" + documentation: "https://openms.readthedocs.io/en/latest/index.html" + identifier: "" + - Comet: + description: "Comet is an open source tandem mass spectrometry (MS/MS) sequence + database search tool." + homepage: "http://comet-ms.sourceforge.net/" + documentation: "http://comet-ms.sourceforge.net/" + identifier: "" input: - - meta: type: map @@ -57,13 +68,48 @@ output: pattern: "*.{tsv}" ontologies: - edam: http://edamontology.org/format_3475 # TSV + versions_cometadapter: + - - ${task.process}: + type: string + description: The name of the process + - CometAdapter: + type: string + description: The name of the tool + - "CometAdapter --help 2>&1 | sed -nE 's/^Version: ([0-9.]+).*/\\1/p'": + type: eval + description: The expression to obtain the version of the tool + versions_comet: + - - ${task.process}: + type: string + description: The name of the process + - Comet: + type: string + description: The name of the tool + - comet 2>&1 | sed -n 's/.*Comet version " *\(.*\)".*/\1/p': + type: eval + description: The expression to obtain the version of the tool + +topics: versions: - - versions.yml: - type: file - description: File containing software versions - pattern: "versions.yml" - ontologies: - - edam: http://edamontology.org/format_3750 # YAML + - - ${task.process}: + type: string + description: The name of the process + - CometAdapter: + type: string + description: The name of the tool + - "CometAdapter --help 2>&1 | sed -nE 's/^Version: ([0-9.]+).*/\\1/p'": + type: eval + description: The expression to obtain the version of the tool + - - ${task.process}: + type: string + description: The name of the process + - Comet: + type: string + description: The name of the tool + - comet 2>&1 | sed -n 's/.*Comet version " *\(.*\)".*/\1/p': + type: eval + description: The expression to obtain the version of the tool + authors: - "@jonasscheid" maintainers: diff --git a/modules/nf-core/openmsthirdparty/cometadapter/tests/main.nf.test b/modules/nf-core/openmsthirdparty/cometadapter/tests/main.nf.test index cf1a0bcd..d43d461b 100644 --- a/modules/nf-core/openmsthirdparty/cometadapter/tests/main.nf.test +++ b/modules/nf-core/openmsthirdparty/cometadapter/tests/main.nf.test @@ -18,7 +18,7 @@ nextflow_process { script "../../../thermorawfileparser/main.nf" process { """ - input[0] = Channel.of([ + input[0] = channel.of([ [ id:'test'], file(params.modules_testdata_base_path + 'proteomics/msspectra/PXD012083_e005640_II.raw', checkIfExists: true) ]) @@ -30,7 +30,7 @@ nextflow_process { script "../../../openms/decoydatabase/main.nf" process { """ - input[0] = Channel.of([ + input[0] = channel.of([ [ id:'test'], file(params.modules_testdata_base_path + 'proteomics/database/UP000005640_9606.fasta', checkIfExists: true) ]) @@ -59,7 +59,7 @@ nextflow_process { // Make sure the file is not empty assert file(process.out.idxml[0][1]).readLines().any { it.contains('ProteinHit') } assert file(process.out.idxml[0][1]).readLines().any { it.contains('PeptideHit') } - assert snapshot(path(process.out.versions.get(0)).yaml).match("versions") + assert snapshot(process.out.versions_cometadapter, process.out.versions_comet).match("versions") } } 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 81a248a8..7fd6dbba 100644 --- a/modules/nf-core/openmsthirdparty/cometadapter/tests/main.nf.test.snap +++ b/modules/nf-core/openmsthirdparty/cometadapter/tests/main.nf.test.snap @@ -43,17 +43,25 @@ }, "versions": { "content": [ - { - "OPENMSTHIRDPARTY_COMETADAPTER": { - "CometAdapter": "3.4.1", - "Comet": "2024.01 rev. 1" - } - } + [ + [ + "OPENMSTHIRDPARTY_COMETADAPTER", + "CometAdapter", + "3.5.0" + ] + ], + [ + [ + "OPENMSTHIRDPARTY_COMETADAPTER", + "Comet", + "2024.01 rev. 1" + ] + ] ], "meta": { "nf-test": "0.9.3", "nextflow": "25.04.8" }, - "timestamp": "2025-10-28T08:16:50.757046344" + "timestamp": "2026-01-12T12:27:11.62435964" } } \ No newline at end of file diff --git a/modules/nf-core/thermorawfileparser/main.nf b/modules/nf-core/thermorawfileparser/main.nf index 4f407e97..bb790b1c 100644 --- a/modules/nf-core/thermorawfileparser/main.nf +++ b/modules/nf-core/thermorawfileparser/main.nf @@ -12,7 +12,7 @@ process THERMORAWFILEPARSER { output: tuple val(meta), path("*.{mzML,mzML.gz,mgf,mgf.gz,parquet,parquet.gz}"), emit: spectra - path "versions.yml" , emit: versions + tuple val("${task.process}"), val('thermorawfileparser'), eval("ThermoRawFileParser.sh --version"), emit: versions_thermorawfileparser, topic: versions when: task.ext.when == null || task.ext.when @@ -32,11 +32,6 @@ process THERMORAWFILEPARSER { -i $raw \\ -b ${prefix}.${suffix} \\ $args - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - thermorawfileparser: \$(ThermoRawFileParser.sh --version) - END_VERSIONS """ stub: @@ -51,10 +46,5 @@ process THERMORAWFILEPARSER { """ touch ${prefix}.${suffix} - - cat <<-END_VERSIONS > versions.yml - "${task.process}": - thermorawfileparser: \$(ThermoRawFileParser.sh --version) - END_VERSIONS """ } diff --git a/modules/nf-core/thermorawfileparser/meta.yml b/modules/nf-core/thermorawfileparser/meta.yml index 26e37e07..ecd33189 100644 --- a/modules/nf-core/thermorawfileparser/meta.yml +++ b/modules/nf-core/thermorawfileparser/meta.yml @@ -1,5 +1,6 @@ name: "thermorawfileparser" -description: Parses a Thermo RAW file containing mass spectra to an open file format +description: Parses a Thermo RAW file containing mass spectra to an open file + format keywords: - raw - mzml @@ -41,13 +42,29 @@ output: description: Mass spectra in open format pattern: "*.{mzML,mzML.gz,mgf,mgf.gz,parquet,parquet.gz}" ontologies: [] + versions_thermorawfileparser: + - - ${task.process}: + type: string + description: The process the versions were collected from + - thermorawfileparser: + type: string + description: The name of the tool + - ThermoRawFileParser.sh --version: + type: eval + description: The expression to obtain the version of the tool + +topics: versions: - - versions.yml: - type: file - description: File containing software versions - pattern: "versions.yml" - ontologies: - - edam: http://edamontology.org/format_3750 # YAML + - - ${task.process}: + type: string + description: The process the versions were collected from + - thermorawfileparser: + type: string + description: The name of the tool + - ThermoRawFileParser.sh --version: + type: eval + description: The expression to obtain the version of the tool + authors: - "@jonasscheid" maintainers: diff --git a/modules/nf-core/thermorawfileparser/tests/main.nf.test.snap b/modules/nf-core/thermorawfileparser/tests/main.nf.test.snap index 62a55e3f..a9ad37eb 100644 --- a/modules/nf-core/thermorawfileparser/tests/main.nf.test.snap +++ b/modules/nf-core/thermorawfileparser/tests/main.nf.test.snap @@ -52,7 +52,11 @@ ] ], "1": [ - "versions.yml:md5,92962c5af8265404031d46df0bda0eff" + [ + "THERMORAWFILEPARSER", + "thermorawfileparser", + "1.4.5" + ] ], "spectra": [ [ @@ -63,14 +67,18 @@ ] ], "versions": [ - "versions.yml:md5,92962c5af8265404031d46df0bda0eff" + [ + "THERMORAWFILEPARSER", + "thermorawfileparser", + "1.4.5" + ] ] } ], "meta": { - "nf-test": "0.9.2", - "nextflow": "24.10.4" + "nf-test": "0.9.3", + "nextflow": "25.04.8" }, - "timestamp": "2025-02-14T11:00:58.349510248" + "timestamp": "2026-01-27T17:25:10.402558587" } } \ No newline at end of file diff --git a/nextflow.config b/nextflow.config index 97ebb856..46484ee2 100644 --- a/nextflow.config +++ b/nextflow.config @@ -12,6 +12,7 @@ params { input = null outdir = null fasta = null + search_presets = "${projectDir}/assets/search_presets.tsv" // Workflow options skip_decoy_generation = false @@ -229,13 +230,16 @@ profiles { singularity.runOptions = '--nv' } test { includeConfig 'conf/test.config' } + test_sdrf { includeConfig 'conf/test_sdrf.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' } + test_single_quant { includeConfig 'conf/test_single_quant.config' } + test_search_presets { includeConfig 'conf/test_search_presets.config' } + test_full { includeConfig 'conf/test_full.config' } } // Load nf-core custom profiles from different institutions @@ -256,6 +260,7 @@ podman.registry = 'quay.io' singularity.registry = 'quay.io' charliecloud.registry = 'quay.io' + // Export these variables to prevent local Python/R libraries from conflicting with those in the container // The JULIA depot path has been adjusted to a fixed path `/usr/local/share/julia` that needs to be used for packages in the container. // See https://apeltzer.github.io/post/03-julia-lang-nextflow/ for details on that. Once we have a common agreement on where to keep Julia packages, this is adjustable. @@ -354,7 +359,7 @@ manifest { mainScript = 'main.nf' defaultBranch = 'master' nextflowVersion = '!>=25.04.0' - version = '3.1.0' + version = '3.2.0dev' doi = '10.1186/s13059-025-03763-8' } diff --git a/nextflow_schema.json b/nextflow_schema.json index 05d3b5b0..4e4d89c7 100644 --- a/nextflow_schema.json +++ b/nextflow_schema.json @@ -14,13 +14,9 @@ "properties": { "input": { "type": "string", - "description": "Input raw / mzML files listed in a tsv file (see help for details)", - "help_text": "Use this to specify a sample sheet table including your input raw or mzml files as well as their meta information such as SampleID and Condition. For example:\n\n| ID | Sample | Condition | ReplicateFileName |\n| -----|:------------:| ----------:|------------------------------------------:|\n| 1 | MM15_Melanom | A | data/MM15_Melanom_W_1_A_standard.raw |\n| 2 | MM15_Melanom | B | data/MM15_Melanom_W_1_B_standard.raw |\n| 3 | MM17_Melanom | B | data/MM17_Melanom_W_1_B_standard.raw |\n\n```bash\n--input 'path/samples.tsv'\n```", - "format": "file-path", - "exists": true, - "schema": "assets/schema_input.json", - "mimetype": "text/csv", - "pattern": "^\\S+\\.tsv$", + "pattern": "^(PXD\\d{6,}|\\S+\\.sdrf\\.tsv|\\S+\\.tsv)$", + "description": "Input: samplesheet TSV, SDRF file (.sdrf.tsv), or PRIDE accession (PXD...)", + "help_text": "Accepts three input modes:\n\n1. **Samplesheet TSV** (default): Tab-separated file with columns ID, Sample, Condition, ReplicateFileName.\n2. **SDRF file** (`.sdrf.tsv`): Files are downloaded from PRIDE automatically. Requires `--fasta`.\n3. **PRIDE accession** (e.g., `PXD009752`): SDRF and raw files are fetched from PRIDE. Requires `--fasta`.", "fa_icon": "fas fa-file" }, "outdir": { @@ -250,6 +246,15 @@ "fa_icon": "fas fa-file-code", "hidden": true, "description": "Specify custom Comet params file. All parameters of this take precedence." + }, + "search_presets": { + "type": "string", + "format": "file-path", + "exists": true, + "schema": "assets/schema_search_presets.json", + "mimetype": "text/csv", + "pattern": "^\\S+\\.tsv$", + "description": "TSV file with search parameter presets. Users can supply a custom file to define their own presets." } } }, diff --git a/ro-crate-metadata.json b/ro-crate-metadata.json index 9484fb86..ff701c73 100644 --- a/ro-crate-metadata.json +++ b/ro-crate-metadata.json @@ -21,9 +21,9 @@ { "@id": "./", "@type": "Dataset", - "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", + "creativeWorkStatus": "InProgress", + "datePublished": "2026-01-08T12:19:18+00:00", + "description": "

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

\n\n[![Open in GitHub Codespaces](https://img.shields.io/badge/Open_In_GitHub_Codespaces-black?labelColor=grey&logo=github)](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.5.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.5.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" @@ -105,7 +105,7 @@ }, "mentions": [ { - "@id": "#3dbe415b-3d82-41eb-a11f-065f425f8a83" + "@id": "#9e4c34cf-5530-46b2-be64-79e63d572382" } ], "name": "nf-core/mhcquant" @@ -139,18 +139,18 @@ { "@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-5923-1343" + }, + { + "@id": "https://orcid.org/0000-0002-6503-2180" } ], "dateCreated": "", - "dateModified": "2025-10-20T07:45:13Z", + "dateModified": "2026-01-08T12:19:18Z", "dct:conformsTo": "https://bioschemas.org/profiles/ComputationalWorkflow/1.0-RELEASE/", "keywords": [ "nf-core", @@ -187,10 +187,10 @@ }, "url": [ "https://github.com/nf-core/mhcquant", - "https://nf-co.re/mhcquant/3.1.0/" + "https://nf-co.re/mhcquant/dev/" ], "version": [ - "3.1.0" + "3.2.0dev" ] }, { @@ -206,11 +206,11 @@ "version": "!>=25.04.0" }, { - "@id": "#3dbe415b-3d82-41eb-a11f-065f425f8a83", + "@id": "#9e4c34cf-5530-46b2-be64-79e63d572382", "@type": "TestSuite", "instance": [ { - "@id": "#cd4e5431-8228-4f6a-a3c6-4b722e22ba0a" + "@id": "#b55a3b6b-29d0-41f1-a5dc-9c168ffc0064" } ], "mainEntity": { @@ -219,7 +219,7 @@ "name": "Test suite for nf-core/mhcquant" }, { - "@id": "#cd4e5431-8228-4f6a-a3c6-4b722e22ba0a", + "@id": "#b55a3b6b-29d0-41f1-a5dc-9c168ffc0064", "@type": "TestInstance", "name": "GitHub Actions workflow for testing nf-core/mhcquant", "resource": "repos/nf-core/mhcquant/actions/workflows/nf-test.yml", @@ -369,12 +369,6 @@ "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", @@ -386,6 +380,12 @@ "@type": "Person", "email": "43858870+jonasscheid@users.noreply.github.com", "name": "Jonas Scheid" + }, + { + "@id": "https://orcid.org/0000-0002-6503-2180", + "@type": "Person", + "email": "apeltzer@users.noreply.github.com", + "name": "Alexander Peltzer" } ] } \ No newline at end of file diff --git a/subworkflows/local/map_alignment/main.nf b/subworkflows/local/map_alignment/main.nf index 76725d0d..8ee871d5 100644 --- a/subworkflows/local/map_alignment/main.nf +++ b/subworkflows/local/map_alignment/main.nf @@ -14,41 +14,35 @@ workflow MAP_ALIGNMENT { merge_meta_map main: - ch_versions = Channel.empty() - // Compute group-wise alignment rt transformation OPENMS_MAPALIGNERIDENTIFICATION( ch_runs_to_be_aligned ) - ch_versions = ch_versions.mix(OPENMS_MAPALIGNERIDENTIFICATION.out.versions) // Join run specific trafoXMLs with meta information merge_meta_map .flatMap { group_meta, metas -> metas } .map { meta -> [[spectra:meta.spectra], meta]} .join( OPENMS_MAPALIGNERIDENTIFICATION.out.trafoxml - .flatMap { group_meta, trafoxmls -> trafoxmls.collect { trafoxml -> [[spectra: trafoxml.baseName], trafoxml] } }) + .flatMap { group_meta, trafoxmls -> [trafoxmls].flatten().collect { trafoxml -> [[spectra: trafoxml.baseName], trafoxml] } }) .map { spectra, meta, trafoxml -> [meta, trafoxml] } .set { ch_trafos } // Align mzML files using trafoXMLs ch_trafos_mzmls = ch_mzml.join(ch_trafos) OPENMS_MAPRTTRANSFORMERMZML(ch_trafos_mzmls) - ch_versions = ch_versions.mix(OPENMS_MAPRTTRANSFORMERMZML.out.versions) // Align idXMLfiles using trafoXMLs ch_runs_to_be_aligned - .flatMap { group_meta, idxmls -> idxmls.collect { idxml -> [[spectra: idxml.baseName.replace("_fdr_filtered","")], idxml] } } - .join( merge_meta_map - .flatMap { group_meta, metas -> metas } - .map { meta -> [[spectra:meta.spectra], meta]} ) - .map { group_meta, idxml, meta -> [meta, idxml] } - .join( ch_trafos ) - .set { ch_trafos_idxml } + .flatMap { group_meta, idxmls -> [idxmls].flatten().collect { idxml -> [[spectra: idxml.baseName.replace("_fdr_filtered","")], idxml] } } + .join( merge_meta_map + .flatMap { group_meta, metas -> metas } + .map { meta -> [[spectra:meta.spectra], meta]} ) + .map { group_meta, idxml, meta -> [meta, idxml] } + .join( ch_trafos ) + .set { ch_trafos_idxml } OPENMS_MAPRTTRANSFORMERIDXML(ch_trafos_idxml) - ch_versions = ch_versions.mix(OPENMS_MAPRTTRANSFORMERIDXML.out.versions) emit: - versions = ch_versions aligned_idxml = OPENMS_MAPRTTRANSFORMERIDXML.out.aligned aligned_mzml = OPENMS_MAPRTTRANSFORMERMZML.out.aligned } diff --git a/subworkflows/local/prepare_spectra/main.nf b/subworkflows/local/prepare_spectra/main.nf index 6c199bf6..a06abf15 100644 --- a/subworkflows/local/prepare_spectra/main.nf +++ b/subworkflows/local/prepare_spectra/main.nf @@ -14,36 +14,31 @@ workflow PREPARE_SPECTRA { ch_samplesheet main: - ch_versions = Channel.empty() - ch_samplesheet .branch { meta, filename -> raw : meta.ext == 'raw' - return [ meta.subMap('id', 'sample', 'condition', 'group_count', 'spectra'), filename ] + return [ meta.subMap(meta.keySet() - ['ext']), filename ] mzml : meta.ext == 'mzml' - return [ meta.subMap('id', 'sample', 'condition', 'group_count', 'spectra'), filename ] + return [ meta.subMap(meta.keySet() - ['ext']), filename ] mzml_gz : meta.ext == 'mzml.gz' - return [ meta.subMap('id', 'sample', 'condition', 'group_count', 'spectra'), filename ] + return [ meta.subMap(meta.keySet() - ['ext']), filename ] d : meta.ext == 'd' - return [ meta.subMap('id', 'sample', 'condition', 'group_count', 'spectra'), filename ] + return [ meta.subMap(meta.keySet() - ['ext']), filename ] d_tar : meta.ext == 'd.tar' | meta.ext == 'd.tar.gz' - return [ meta.subMap('id', 'sample', 'condition', 'group_count', 'spectra'), filename ] + return [ meta.subMap(meta.keySet() - ['ext']), filename ] d_zip : meta.ext == 'd.zip' - return [ meta.subMap('id', 'sample', 'condition', 'group_count', 'spectra'), filename ] + return [ meta.subMap(meta.keySet() - ['ext']), filename ] other : true } .set { branched_ms_files } // Raw file conversion THERMORAWFILEPARSER(branched_ms_files.raw) - ch_versions = ch_versions.mix(THERMORAWFILEPARSER.out.versions) // Decompress timsTOF archive for data conversion UNTAR(branched_ms_files.d_tar) - ch_versions = ch_versions.mix(UNTAR.out.versions) UNZIP(branched_ms_files.d_zip) - ch_versions = ch_versions.mix(UNZIP.out.versions) ch_tdf_files = branched_ms_files.d .mix(UNTAR.out.untar, @@ -51,11 +46,9 @@ workflow PREPARE_SPECTRA { // timsTOF data conversion TDF2MZML(ch_tdf_files) - ch_versions = ch_versions.mix(TDF2MZML.out.versions) // Gunzip mzML files GUNZIP(branched_ms_files.mzml_gz) - ch_versions = ch_versions.mix(GUNZIP.out.versions) // Initialize channel for ms files that do not need to be converted ch_ms_files = branched_ms_files.mzml .mix(GUNZIP.out.gunzip, @@ -65,7 +58,6 @@ workflow PREPARE_SPECTRA { // Optional: Run Peak Picking as Preprocessing if (params.run_centroidisation) { OPENMS_PEAKPICKERHIRES(ch_ms_files) - ch_versions = ch_versions.mix(OPENMS_PEAKPICKERHIRES.out.versions) ch_mzml_file = OPENMS_PEAKPICKERHIRES.out.mzml } else { ch_mzml_file = ch_ms_files @@ -73,5 +65,4 @@ workflow PREPARE_SPECTRA { emit: mzml = ch_mzml_file - versions = ch_versions } diff --git a/subworkflows/local/process_feature/main.nf b/subworkflows/local/process_feature/main.nf index 8156a5f2..e414883c 100644 --- a/subworkflows/local/process_feature/main.nf +++ b/subworkflows/local/process_feature/main.nf @@ -4,32 +4,39 @@ include { OPENMS_FEATUREFINDERIDENTIFICATION } from '../../../modules/local/openms/featurefinderidentification' include { OPENMS_FEATURELINKERUNLABELEDKD } from '../../../modules/local/openmsthirdparty/featurelinkerunlabeledkd' -include { OPENMS_IDCONFLICTRESOLVER } from '../../../modules/local/openms/idconflictresolver' +include { OPENMS_IDCONFLICTRESOLVER } from '../../../modules/local/openms/idconflictresolver/main' +include { OPENMS_FILECONVERTER } from '../../../modules/local/openms/fileconverter/main' workflow PROCESS_FEATURE { take: ch_runs_to_be_quantified main: - ch_versions = Channel.empty() - // Quantify identifications using targeted feature extraction OPENMS_FEATUREFINDERIDENTIFICATION(ch_runs_to_be_quantified).featurexml .map { meta, featurexml -> [ groupKey([id: "${meta.sample}_${meta.condition}"], meta.group_count), featurexml] } .groupTuple() - .set { ch_features_grouped } - ch_versions = ch_versions.mix(OPENMS_FEATUREFINDERIDENTIFICATION.out.versions) + .set { ch_featuresxmls } + + ch_featuresxmls + .branch { + single: it[1].size() == 1 + multiple: it[1].size() > 1 + } + .set { ch_features } // Link extracted features - OPENMS_FEATURELINKERUNLABELEDKD(ch_features_grouped) - ch_versions = ch_versions.mix(OPENMS_FEATURELINKERUNLABELEDKD.out.versions) + OPENMS_FEATURELINKERUNLABELEDKD(ch_features.multiple) + + // Single replicate: promote featureXML to consensusXML + OPENMS_FILECONVERTER(ch_features.single.map { meta, features -> [ meta, features[0], "consensusXML" ] }) // Resolve conflicting ids matching to the same feature - OPENMS_IDCONFLICTRESOLVER(OPENMS_FEATURELINKERUNLABELEDKD.out.consensusxml) - ch_versions = ch_versions.mix(OPENMS_IDCONFLICTRESOLVER.out.versions) + ch_consensus_input = OPENMS_FEATURELINKERUNLABELEDKD.out.consensusxml + .mix(OPENMS_FILECONVERTER.out.consensusxml) + + OPENMS_IDCONFLICTRESOLVER(ch_consensus_input) emit: - // Define the information that is returned by this workflow - versions = ch_versions consensusxml = OPENMS_IDCONFLICTRESOLVER.out.consensusxml } diff --git a/subworkflows/local/quant/main.nf b/subworkflows/local/quant/main.nf index d9202d8d..a3ba3444 100644 --- a/subworkflows/local/quant/main.nf +++ b/subworkflows/local/quant/main.nf @@ -25,25 +25,22 @@ workflow QUANT { mzml main: - ch_versions = Channel.empty() // Split post-percolator idXML files and manipulate such that we end up with [meta_run1, idxml_run1] [meta_run2, idxml_run2] ... // We need to make sure that the order of the runs is the same as in the mzml files since IDRipper always sorts the runs // (and nextflow does not guarantee the order of the maps in merged_meta_map) OPENMS_IDRIPPER( merged_pout ).idxmls - .flatMap { group_meta, idxmls -> idxmls.collect { idxml -> [[spectra: idxml.baseName], idxml] } } - // join on file basename to make sure that the order of the runs is the same as in the mzml files - // Is there a smoother way to do this? - .join( merge_meta_map - .flatMap { group_meta, metas -> metas } - .map { meta -> [[spectra:meta.spectra], meta]} ) - .map { spectra, idxmls, meta -> [meta, idxmls] } - .set { ch_ripped_idxml } - ch_versions = ch_versions.mix(OPENMS_IDRIPPER.out.versions) + // Handle both single file and list of files + .flatMap { group_meta, idxmls -> [idxmls].flatten().collect { idxml -> [[spectra: idxml.baseName], idxml] } } + // join on file basename to make sure that the order of the runs is the same as in the mzml files + .join( merge_meta_map + .flatMap { group_meta, metas -> metas } + .map { meta -> [[spectra:meta.spectra], meta]} ) + .map { spectra, idxmls, meta -> [meta, idxmls] } + .set { ch_ripped_idxml } // Switch to xcorr for filtering since q-values are set to 1 with peptide-level-fdr if (params.fdr_level == 'peptide_level_fdrs'){ ch_runs_score_switched = OPENMS_IDSCORESWITCHER( ch_ripped_idxml ).idxml - ch_versions = ch_versions.mix(OPENMS_IDSCORESWITCHER.out.versions) } else { ch_runs_score_switched = ch_ripped_idxml } @@ -61,7 +58,6 @@ workflow QUANT { .map { meta, idxml -> [ groupKey([id:"${meta.sample}_${meta.condition}"], meta.group_count), idxml] } .groupTuple() .set { ch_runs_to_be_aligned } - ch_versions = ch_versions.mix(OPENMS_IDFILTER_QUANT.out.versions) // Align retention times of runs MAP_ALIGNMENT( @@ -69,13 +65,11 @@ workflow QUANT { mzml, merge_meta_map ) - ch_versions = ch_versions.mix( MAP_ALIGNMENT.out.versions ) // We need to merge groupwise the aligned idxml files together to use them as id_ext in featurefinder OPENMS_IDMERGER_QUANT( MAP_ALIGNMENT.out.aligned_idxml .map { meta, aligned_idxml -> [ groupKey([id: "${meta.sample}_${meta.condition}"], meta.group_count), aligned_idxml] } .groupTuple()) - ch_versions = ch_versions.mix(OPENMS_IDMERGER_QUANT.out.versions) // Manipulate channels such that we end up with : [meta, mzml, run_idxml, merged_runs_idxml] MAP_ALIGNMENT.out.aligned_mzml @@ -89,12 +83,9 @@ workflow QUANT { .set { ch_runs_to_be_quantified } PROCESS_FEATURE ( ch_runs_to_be_quantified ) - ch_versions = ch_versions.mix(PROCESS_FEATURE.out.versions) OPENMS_MZTABEXPORTER(PROCESS_FEATURE.out.consensusxml) - ch_versions = ch_versions.mix(OPENMS_MZTABEXPORTER.out.versions) emit: consensusxml = PROCESS_FEATURE.out.consensusxml - versions = ch_versions } diff --git a/subworkflows/local/rescore/main.nf b/subworkflows/local/rescore/main.nf index 564a6b0c..15c6aea3 100644 --- a/subworkflows/local/rescore/main.nf +++ b/subworkflows/local/rescore/main.nf @@ -8,8 +8,10 @@ include { MS2RESCORE } from '../../../modules/local/ms2rescore' include { OPENMS_PSMFEATUREEXTRACTOR } from '../../../modules/local/openms/psmfeatureextractor' -include { OPENMS_PERCOLATORADAPTER; - OPENMS_PERCOLATORADAPTER as OPENMS_PERCOLATORADAPTER_GLOBAL } from '../../../modules/local/openmsthirdparty/percolatoradapter' +include { + OPENMS_PERCOLATORADAPTER ; + OPENMS_PERCOLATORADAPTER as OPENMS_PERCOLATORADAPTER_GLOBAL +} from '../../../modules/local/openmsthirdparty/percolatoradapter' include { OPENMS_TEXTEXPORTER as OPENMS_TEXTEXPORTER_GLOBAL } from '../../../modules/local/openms/textexporter' // // MODULE: Installed directly from nf-core/modules @@ -17,76 +19,79 @@ include { OPENMS_TEXTEXPORTER as OPENMS_TEXTEXPORTER_GLOBAL } from '.. include { OPENMS_IDMERGER as OPENMS_IDMERGER_GLOBAL } from '../../../modules/nf-core/openms/idmerger/main' include { OPENMS_IDSCORESWITCHER } from '../../../modules/nf-core/openms/idscoreswitcher/main.nf' -include { OPENMS_IDFILTER as OPENMS_IDFILTER_Q_VALUE; - OPENMS_IDFILTER as OPENMS_IDFILTER_Q_VALUE_GLOBAL; - OPENMS_IDFILTER as OPENMS_IDFILTER_GLOBAL } from '../../../modules/nf-core/openms/idfilter/main' +include { + OPENMS_IDFILTER as OPENMS_IDFILTER_Q_VALUE ; + OPENMS_IDFILTER as OPENMS_IDFILTER_Q_VALUE_GLOBAL ; + OPENMS_IDFILTER as OPENMS_IDFILTER_GLOBAL +} from '../../../modules/nf-core/openms/idfilter/main' workflow RESCORE { - take: - ch_merged_runs - ch_multiqc_files + ch_merged_runs + ch_multiqc_files main: - ch_versions = Channel.empty() - // Compute features via ms2rescore MS2RESCORE(ch_merged_runs) - ch_versions = ch_versions.mix(MS2RESCORE.out.versions) if (params.rescoring_engine == 'mokapot') { - log.warn "The rescoring engine is set to mokapot. This rescoring engine currently only supports psm-level-fdr via ms2rescore." + log.warn("The rescoring engine is set to mokapot. This rescoring engine currently only supports psm-level-fdr via ms2rescore.") if (params.global_fdr) { - log.warn "Global FDR is currently not supported by mokapot. The global_fdr parameter will be ignored." + log.warn("Global FDR is currently not supported by mokapot. The global_fdr parameter will be ignored.") } // Switch comet e-value to mokapot q-value OPENMS_IDSCORESWITCHER(MS2RESCORE.out.idxml) - ch_versions = ch_versions.mix(OPENMS_IDSCORESWITCHER.out.versions) ch_rescored_runs = OPENMS_IDSCORESWITCHER.out.idxml // Filter by mokapot q-value - OPENMS_IDFILTER_Q_VALUE(ch_rescored_runs.map {group_meta, idxml -> [group_meta, idxml, []]}) - ch_versions = ch_versions.mix(OPENMS_IDFILTER_Q_VALUE.out.versions) + OPENMS_IDFILTER_Q_VALUE(ch_rescored_runs.map { group_meta, idxml -> [group_meta, idxml, []] }) ch_filter_q_value = OPENMS_IDFILTER_Q_VALUE.out.filtered - - } else { + } + else { // Extract PSM features for Percolator OPENMS_PSMFEATUREEXTRACTOR(MS2RESCORE.out.idxml.join(MS2RESCORE.out.feature_names)) - ch_versions = ch_versions.mix(OPENMS_PSMFEATUREEXTRACTOR.out.versions) // Run Percolator with local FDR OPENMS_PERCOLATORADAPTER(OPENMS_PSMFEATUREEXTRACTOR.out.idxml) - ch_versions = ch_versions.mix(OPENMS_PERCOLATORADAPTER.out.versions) - ch_multiqc_files = ch_multiqc_files.mix(OPENMS_PERCOLATORADAPTER.out.feature_weights.map{ meta, feature_weights -> feature_weights }) + ch_multiqc_files = ch_multiqc_files.mix(OPENMS_PERCOLATORADAPTER.out.feature_weights.map { meta, feature_weights -> feature_weights }) ch_pout = OPENMS_PERCOLATORADAPTER.out.idxml if (params.global_fdr) { - // Merge all samples into one group - OPENMS_IDMERGER_GLOBAL(OPENMS_PSMFEATUREEXTRACTOR.out.idxml.map {group_meta, idxml -> [[id:'global'], idxml] }.groupTuple()) - // Run Percolator with global FDR + // Group by search_preset for global FDR. Samples without a preset all share + // the same params (CLI or defaults), so they correctly group under 'global'. + OPENMS_IDMERGER_GLOBAL( + OPENMS_PSMFEATUREEXTRACTOR.out.idxml.map { group_meta, idxml -> [group_meta + [id: group_meta.search_preset ?: 'global'], idxml] }.groupTuple() + ) + // Run Percolator with global FDR (one per preset group) OPENMS_PERCOLATORADAPTER_GLOBAL(OPENMS_IDMERGER_GLOBAL.out.idxml) ch_rescored_runs = OPENMS_PERCOLATORADAPTER_GLOBAL.out.idxml // Filter by global percolator q-value - OPENMS_IDFILTER_Q_VALUE_GLOBAL(ch_rescored_runs.map {id, idxml -> [id, idxml, []]}) - ch_versions = ch_versions.mix(OPENMS_IDFILTER_Q_VALUE_GLOBAL.out.versions) - // Backfilter sample_condition runs according to global FDR - OPENMS_IDFILTER_GLOBAL(ch_pout.combine(OPENMS_IDFILTER_Q_VALUE_GLOBAL.out.filtered.map{ it[1] })) + OPENMS_IDFILTER_Q_VALUE_GLOBAL(ch_rescored_runs.map { id, idxml -> [id, idxml, []] }) + // Backfilter: match each local file with its corresponding preset's global FDR file + OPENMS_IDFILTER_GLOBAL( + ch_pout.map { group_meta, idxml -> + [group_meta.search_preset ?: 'global', group_meta, idxml] + }.combine( + OPENMS_IDFILTER_Q_VALUE_GLOBAL.out.filtered.map { global_meta, idxml -> [global_meta.id, idxml] }, + by: 0 + ).map { preset, group_meta, local_idxml, global_filtered_idxml -> + [group_meta, local_idxml, global_filtered_idxml] + } + ) ch_filter_q_value = OPENMS_IDFILTER_GLOBAL.out.filtered - // Save globally merged runs in tsv + // Save globally merged runs in tsv (one per preset group) OPENMS_TEXTEXPORTER_GLOBAL(OPENMS_IDFILTER_Q_VALUE_GLOBAL.out.filtered) - - } else { + } + else { ch_rescored_runs = ch_pout // Filter by percolator q-value - OPENMS_IDFILTER_Q_VALUE(ch_rescored_runs.map {group_meta, idxml -> [group_meta, idxml, []]}) - ch_versions = ch_versions.mix(OPENMS_IDFILTER_Q_VALUE.out.versions) + OPENMS_IDFILTER_Q_VALUE(ch_rescored_runs.map { group_meta, idxml -> [group_meta, idxml, []] }) ch_filter_q_value = OPENMS_IDFILTER_Q_VALUE.out.filtered } } emit: - rescored_runs = ch_rescored_runs - fdr_filtered = ch_filter_q_value - versions = ch_versions - multiqc_files = ch_multiqc_files + rescored_runs = ch_rescored_runs.map { meta, file -> [[id: meta.id], file] } + fdr_filtered = ch_filter_q_value.map { meta, file -> [[id: meta.id], file] } + multiqc_files = ch_multiqc_files } diff --git a/subworkflows/local/sdrf_to_samplesheet/main.nf b/subworkflows/local/sdrf_to_samplesheet/main.nf new file mode 100644 index 00000000..7d060ef0 --- /dev/null +++ b/subworkflows/local/sdrf_to_samplesheet/main.nf @@ -0,0 +1,81 @@ +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + SDRF_TO_SAMPLESHEET: Convert SDRF to mhcquant samplesheet + download files from PRIDE +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +*/ + +include { SDRF_PIPELINES_PARSE_SDRF } from '../../../modules/local/sdrf_pipelines/parse_sdrf/main' +include { PRIDEPY_FETCH_SDRF } from '../../../modules/local/pridepy/fetch_sdrf/main' +include { PRIDEPY_DOWNLOAD_FILE } from '../../../modules/local/pridepy/download_file/main' + +workflow SDRF_TO_SAMPLESHEET { + + take: + sdrf // path: local SDRF file, or null + pride_id // val: PRIDE accession, or null + + main: + + // If pride_id given but no local SDRF, fetch from PRIDE + if (pride_id && !sdrf) { + PRIDEPY_FETCH_SDRF(pride_id) + ch_sdrf = PRIDEPY_FETCH_SDRF.out.sdrf + } else { + ch_sdrf = channel.fromPath(sdrf, checkIfExists: true) + } + + // Convert SDRF to mhcquant samplesheet + search presets + SDRF_PIPELINES_PARSE_SDRF(ch_sdrf) + + // Resolve PRIDE accession for file downloads + def resolved_accession = pride_id ?: inferPrideAccession(sdrf) + + // Parse samplesheet to get file names for downloading + ch_samplesheet_rows = SDRF_PIPELINES_PARSE_SDRF.out.samplesheet + .splitCsv(header: true, sep: '\t') + .map { row -> + def meta = [ + id: row.ID as int, + sample: row.Sample.toString(), + condition: row.Condition.toString(), + search_preset: row.SearchPreset + ] + [meta, row.ReplicateFileName] + } + + // Download each file from PRIDE + ch_to_download = ch_samplesheet_rows + .map { meta, filename -> [meta, filename, resolved_accession] } + + PRIDEPY_DOWNLOAD_FILE(ch_to_download) + + // Write a validated samplesheet with local file paths + ch_samplesheet_file = PRIDEPY_DOWNLOAD_FILE.out.downloaded_file + .map { meta, downloaded_file -> + [meta.id, meta.sample, meta.condition, downloaded_file, meta.search_preset].join('\t') + } + .collectFile(name: 'sdrf_samplesheet.tsv', seed: ['ID', 'Sample', 'Condition', 'ReplicateFileName', 'SearchPreset'].join('\t'), newLine: true) + + emit: + samplesheet = ch_samplesheet_file // path: samplesheet.tsv with local file paths + search_presets = SDRF_PIPELINES_PARSE_SDRF.out.search_presets // path: search_presets.tsv +} + +/* +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + FUNCTIONS +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +*/ + +def inferPrideAccession(sdrf_path) { + def name = file(sdrf_path).name + def matcher = (name =~ /PXD\d{6,}/) + if (matcher.find()) { + return matcher.group() + } + error """\ + Could not infer PRIDE accession from SDRF filename: ${name} + Please provide input as a PRIDE accession (e.g., --input PXD009752) + or use an SDRF file named with the PXD accession (e.g., PXD009752.sdrf.tsv) + """.stripIndent() +} diff --git a/subworkflows/local/speclib/main.nf b/subworkflows/local/speclib/main.nf index dad8aa0f..55b1f71b 100644 --- a/subworkflows/local/speclib/main.nf +++ b/subworkflows/local/speclib/main.nf @@ -6,29 +6,25 @@ // MODULE: Loaded from modules/local/ // -include { EASYPQP_CONVERT } from '../../../modules/local/easypqp/convert' -include { EASYPQP_LIBRARY; - EASYPQP_LIBRARY as EASYPQP_LIBRARY_GLOBAL } from '../../../modules/local/easypqp/library' +include { EASYPQP_CONVERT } from '../../../modules/local/easypqp/convert' +include { EASYPQP_LIBRARY } from '../../../modules/local/easypqp/library' +include { EASYPQP_LIBRARY as EASYPQP_LIBRARY_GLOBAL } from '../../../modules/local/easypqp/library' // // MODULE: Installed directly from nf-core/modules // workflow SPECLIB { - take: - fdrfiltered_comet_idxml - mzml + fdrfiltered_comet_idxml + mzml main: - ch_versions = Channel.empty() - // Load unimod tables (Future:) - unimod = file("$projectDir/assets/250120_unimod_tables.xml", checkIfExists: true) + unimod = file("${projectDir}/assets/250120_unimod_tables.xml", checkIfExists: true) // Convert psms and spectra to pickle files EASYPQP_CONVERT(fdrfiltered_comet_idxml.join(mzml), unimod) - ch_versions = ch_versions.mix(EASYPQP_CONVERT.out.versions) EASYPQP_CONVERT.out.psmpkl .map { meta, psmpkl -> [groupKey([id: "${meta.sample}_${meta.condition}"], meta.group_count), psmpkl] } @@ -41,21 +37,17 @@ workflow SPECLIB { // Generate spectrum library for each sample-condition pair EASYPQP_LIBRARY(ch_psmpkl.join(ch_peakpkl)) - ch_versions = ch_versions.mix(EASYPQP_LIBRARY.out.versions) // Generate spectrum library for all MSruns in the samplesheet if (params.global_fdr) { EASYPQP_CONVERT.out.psmpkl - .map { meta, psmpkl -> [[id: "global"], psmpkl] } + .map { meta, psmpkl -> [[id: meta.search_preset ?: 'global'], psmpkl] } .groupTuple() .set { ch_global_psmpkl } EASYPQP_CONVERT.out.peakpkl - .map { meta, peakpkl -> [[id: "global"], peakpkl] } + .map { meta, peakpkl -> [[id: meta.search_preset ?: 'global'], peakpkl] } .groupTuple() .set { ch_global_peakpkl } EASYPQP_LIBRARY_GLOBAL(ch_global_psmpkl.join(ch_global_peakpkl)) } - - emit: - versions = ch_versions } diff --git a/subworkflows/local/utils_nfcore_mhcquant_pipeline/main.nf b/subworkflows/local/utils_nfcore_mhcquant_pipeline/main.nf index de3353fc..125e62fa 100644 --- a/subworkflows/local/utils_nfcore_mhcquant_pipeline/main.nf +++ b/subworkflows/local/utils_nfcore_mhcquant_pipeline/main.nf @@ -17,6 +17,7 @@ include { completionSummary } from '../../nf-core/utils_nfcore_pipeline' include { imNotification } from '../../nf-core/utils_nfcore_pipeline' include { UTILS_NFCORE_PIPELINE } from '../../nf-core/utils_nfcore_pipeline' include { UTILS_NEXTFLOW_PIPELINE } from '../../nf-core/utils_nextflow_pipeline' +include { SDRF_TO_SAMPLESHEET } from '../sdrf_to_samplesheet' /* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -39,7 +40,6 @@ workflow PIPELINE_INITIALISATION { main: - ch_versions = Channel.empty() // // Print version and exit if required and dump pipeline parameters to JSON file @@ -64,7 +64,7 @@ workflow PIPELINE_INITIALISATION { \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" : ""} + after_text = """${workflow.manifest.doi ? "\n* The pipeline\n" : ""}${workflow.manifest.doi.tokenize(",").collect { doi -> " https://doi.org/${doi.trim().replace('https://doi.org/','')}"}.join("\n")}${workflow.manifest.doi ? "\n" : ""} * The nf-core framework https://doi.org/10.1038/s41587-020-0439-x @@ -93,28 +93,82 @@ workflow PIPELINE_INITIALISATION { ) // - // Create channel from input file provided through params.input + // Detect input type and build samplesheet channels // + def inputType = detectInputType(params.input) + + if (inputType == 'sdrf' || inputType == 'pride_id') { + // + // SDRF / PRIDE input mode: fetch SDRF, convert, download files + // + def sdrf_path = (inputType == 'sdrf') ? params.input : null + def pride_id = (inputType == 'pride_id') ? params.input : null + + if (inputType == 'sdrf' && !pride_id) { + def matcher = (file(params.input).name =~ /PXD\d{6,}/) + pride_id = matcher.find() ? matcher.group() : null + } + + SDRF_TO_SAMPLESHEET(sdrf_path, pride_id) + + ch_samplesheet_file = SDRF_TO_SAMPLESHEET.out.samplesheet + ch_presets_file = SDRF_TO_SAMPLESHEET.out.search_presets - Channel - .fromList(samplesheetToList(params.input, "${projectDir}/assets/schema_input.json")) - .map { meta, file, fasta -> [meta.subMap('sample','condition'), meta, file, fasta] } + } else { + // + // Standard samplesheet input mode + // + ch_samplesheet_file = channel.value(params.input) + ch_presets_file = channel.fromPath(params.search_presets, checkIfExists: true) + } + + // + // Build presets map (shared) + // + ch_presets_map = ch_presets_file + .map { presets_file -> + samplesheetToList(presets_file.toString(), "${projectDir}/assets/schema_search_presets.json") + .collectEntries { item -> + // samplesheetToList wraps all-meta rows in a list + def row = (item instanceof List) ? item[0] : item + // nf-schema parses empty TSV cells as [] instead of ''; normalize for string operations + ['fixed_mods', 'variable_mods'].each { key -> if (!row[key]) row[key] = '' } + [(row.preset_name): row] + } + } + + // + // Parse samplesheet with nf-schema validation, enrich, resolve search params (shared) + // + ch_samplesheet_file + .flatMap { samplesheet_path -> + samplesheetToList(samplesheet_path.toString(), "${projectDir}/assets/schema_input.json") + } + .map { meta, file, fasta -> + def m = meta + [sample: meta.sample.toString(), condition: meta.condition.toString()] + [m.subMap('sample', 'condition'), m, file, fasta] + } .tap { ch_input } .groupTuple() - // get number of files per sample-condition - .map { group_meta, metas, files, fastas -> [ group_meta, files.size()] } - .combine( ch_input, by:0 ) - .map { group_meta, group_count, meta, file, fasta -> [meta + ['group_count':group_count, 'spectra':file.baseName.tokenize('.')[0], 'ext':getCustomExtension(file)], file, fasta] } + .map { group_meta, metas, files, fastas -> [group_meta, files.size()] } + .combine(ch_input, by: 0) + .map { group_meta, group_count, meta, file, fasta -> + def enrichedMeta = meta + [group_count: group_count, spectra: file.baseName.tokenize('.')[0], ext: getCustomExtension(file)] + [enrichedMeta, file, fasta] + } .set { ch_samplesheet_raw } - ch_samplesheet = ch_samplesheet_raw.map { meta, file, fasta -> [ meta, file ]} + ch_samplesheet = ch_samplesheet_raw + .combine(ch_presets_map) + .map { meta, file, fasta, presetsMap -> + [resolveSearchParams(meta, presetsMap), file] + } // - // Create channel from the reference_database through params.fasta or from the samplesheet fasta files + // Create channel from the reference_database through params.fasta // - if (params.fasta) { - Channel.fromPath(params.fasta, checkIfExists: true) + channel.fromPath(params.fasta, checkIfExists: true) .map { fasta -> [[id:fasta.getBaseName()], fasta] } .set { ch_fasta } @@ -129,10 +183,9 @@ workflow PIPELINE_INITIALISATION { 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] } + // Fasta from samplesheet column + 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() @@ -144,7 +197,6 @@ workflow PIPELINE_INITIALISATION { 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()] } @@ -209,6 +261,54 @@ workflow PIPELINE_COMPLETION { FUNCTIONS ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ + +// +// Detect input type from the --input parameter value +// +def detectInputType(input) { + def inputStr = input.toString() + if (inputStr =~ /^PXD\d{6,}$/) { + return 'pride_id' + } + if (inputStr.endsWith('.sdrf.tsv')) { + return 'sdrf' + } + return 'samplesheet' +} + +// +// Resolve a search parameter with priority: CLI params > samplesheet preset > nextflow.config default +// +def resolveSearchParams(meta, presetsMap) { + def searchParamKeys = ['instrument', 'activation_method', 'digest_mass_range', 'prec_charge', + 'precursor_mass_tolerance', 'precursor_error_units', 'fragment_mass_tolerance', + 'fragment_bin_offset', 'number_mods', 'ms2pip_model', + 'peptide_min_length', 'peptide_max_length', + 'fixed_mods', 'variable_mods'] + def presetName = meta.search_preset + def hasPreset = presetName && !(presetName instanceof List && presetName.size() == 0) && presetName != '' + def presetConfig = hasPreset ? presetsMap[presetName] : [:] + if (hasPreset && !presetConfig) { + error "Unknown search preset '${presetName}'. Available: ${presetsMap.keySet().join(', ')}" + } + if (!presetConfig) { presetConfig = [:] } + + def result = new LinkedHashMap(meta) + + searchParamKeys.each { key -> + def cliOverride = (workflow.commandLine =~ /--${key}[\s=]/).find() + if (cliOverride) { + result.put(key, params[key]) + } else if (presetConfig.containsKey(key)) { + result.put(key, presetConfig[key]) + } else { + result.put(key, params[key]) + } + } + + return result +} + // // Validate channels from input samplesheet // diff --git a/subworkflows/nf-core/utils_nfcore_pipeline/main.nf b/subworkflows/nf-core/utils_nfcore_pipeline/main.nf index bfd25876..2f30e9a4 100644 --- a/subworkflows/nf-core/utils_nfcore_pipeline/main.nf +++ b/subworkflows/nf-core/utils_nfcore_pipeline/main.nf @@ -98,7 +98,7 @@ def workflowVersionToYAML() { // Get channel of software versions used in pipeline in YAML format // def softwareVersionsToYAML(ch_versions) { - return ch_versions.unique().map { version -> processVersionsFromYAML(version) }.unique().mix(Channel.of(workflowVersionToYAML())) + return ch_versions.unique().map { version -> processVersionsFromYAML(version) }.unique().mix(channel.of(workflowVersionToYAML())) } // diff --git a/tests/.nftignore b/tests/.nftignore index 53b36346..b794e87c 100644 --- a/tests/.nftignore +++ b/tests/.nftignore @@ -1,5 +1,4 @@ .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 diff --git a/tests/default.nf.test.snap b/tests/default.nf.test.snap index 85ba67fb..a6669ef5 100644 --- a/tests/default.nf.test.snap +++ b/tests/default.nf.test.snap @@ -3,36 +3,36 @@ "content": [ { "MS2RESCORE": { - "MS\u00b2Rescore": "3.1.5)" + "MS2Rescore": "3.1.5" }, "OPENMSTHIRDPARTY_COMETADAPTER": { - "CometAdapter": "3.4.1", - "Comet": "2024.01 rev. 1" + "Comet": "2024.01 rev. 1", + "CometAdapter": "3.5.0" }, "OPENMS_DECOYDATABASE": { - "openms": "3.4.1" + "openms": "3.5.0" }, "OPENMS_IDFILTER_Q_VALUE": { - "openms": "3.4.1" + "openms": "3.5.0" }, "OPENMS_IDMASSACCURACY": { - "OpenMS": "3.4.1" + "openms": "3.4.1" }, "OPENMS_IDMERGER": { - "openms": "3.4.1" + "openms": "3.5.0" }, "OPENMS_PEPTIDEINDEXER": { - "openms": "3.4.1" + "openms": "3.5.0" }, "OPENMS_PERCOLATORADAPTER": { - "PercolatorAdapter": "3.4.1-pre-exported-20250822", - "percolator": "3.07.1, Build Date Mar 13 2025 17:19:27" + "PercolatorAdapter": "3.5.0-pre-exported-20251212", + "percolator": "3.07.1" }, "OPENMS_PSMFEATUREEXTRACTOR": { - "openms": "3.4.1" + "openms": "3.5.0" }, "OPENMS_TEXTEXPORTER": { - "openms": "3.4.1" + "openms": "3.5.0" }, "PYOPENMS_CHROMATOGRAMEXTRACTOR": { "pyopenms": "3.4.1" @@ -41,7 +41,7 @@ "pyopenms": "3.4.1" }, "Workflow": { - "nf-core/mhcquant": "v3.1.0" + "nf-core/mhcquant": "v3.2.0dev" } }, [ @@ -382,8 +382,8 @@ ], "meta": { "nf-test": "0.9.3", - "nextflow": "25.04.8" + "nextflow": "25.10.3" }, - "timestamp": "2025-10-28T21:36:13.560396546" + "timestamp": "2026-04-12T20:25:20.873410846" } } \ No newline at end of file diff --git a/tests/ionannotator.nf.test.snap b/tests/ionannotator.nf.test.snap index b0fd3915..77dd99cd 100644 --- a/tests/ionannotator.nf.test.snap +++ b/tests/ionannotator.nf.test.snap @@ -4,36 +4,36 @@ 22, { "MS2RESCORE": { - "MS\u00b2Rescore": "3.1.5)" + "MS2Rescore": "3.1.5" }, "OPENMSTHIRDPARTY_COMETADAPTER": { - "CometAdapter": "3.4.1", - "Comet": "2024.01 rev. 1" + "Comet": "2024.01 rev. 1", + "CometAdapter": "3.5.0" }, "OPENMS_DECOYDATABASE": { - "openms": "3.4.1" + "openms": "3.5.0" }, "OPENMS_IDFILTER_Q_VALUE": { - "openms": "3.4.1" + "openms": "3.5.0" }, "OPENMS_IDMASSACCURACY": { - "OpenMS": "3.4.1" + "openms": "3.4.1" }, "OPENMS_IDMERGER": { - "openms": "3.4.1" + "openms": "3.5.0" }, "OPENMS_PEPTIDEINDEXER": { - "openms": "3.4.1" + "openms": "3.5.0" }, "OPENMS_PERCOLATORADAPTER": { - "PercolatorAdapter": "3.4.1-pre-exported-20250822", - "percolator": "3.07.1, Build Date Mar 13 2025 17:19:27" + "PercolatorAdapter": "3.5.0-pre-exported-20251212", + "percolator": "3.07.1" }, "OPENMS_PSMFEATUREEXTRACTOR": { - "openms": "3.4.1" + "openms": "3.5.0" }, "OPENMS_TEXTEXPORTER": { - "openms": "3.4.1" + "openms": "3.5.0" }, "PYOPENMS_CHROMATOGRAMEXTRACTOR": { "pyopenms": "3.4.1" @@ -45,7 +45,7 @@ "pyopenms": "3.4.1" }, "Workflow": { - "nf-core/mhcquant": "v3.1.0" + "nf-core/mhcquant": "v3.2.0dev" } }, [ @@ -403,8 +403,8 @@ ], "meta": { "nf-test": "0.9.3", - "nextflow": "25.04.8" + "nextflow": "25.10.3" }, - "timestamp": "2025-10-28T21:53:36.826911285" + "timestamp": "2026-04-12T20:31:52.006375101" } } \ No newline at end of file diff --git a/tests/mokapot.nf.test.snap b/tests/mokapot.nf.test.snap index 4acd6735..9dfb2ea9 100644 --- a/tests/mokapot.nf.test.snap +++ b/tests/mokapot.nf.test.snap @@ -4,32 +4,32 @@ 20, { "MS2RESCORE": { - "MS\u00b2Rescore": "3.1.5)" + "MS2Rescore": "3.1.5" }, "OPENMSTHIRDPARTY_COMETADAPTER": { - "CometAdapter": "3.4.1", - "Comet": "2024.01 rev. 1" + "Comet": "2024.01 rev. 1", + "CometAdapter": "3.5.0" }, "OPENMS_DECOYDATABASE": { - "openms": "3.4.1" + "openms": "3.5.0" }, "OPENMS_IDFILTER_Q_VALUE": { - "openms": "3.4.1" + "openms": "3.5.0" }, "OPENMS_IDMASSACCURACY": { - "OpenMS": "3.4.1" + "openms": "3.4.1" }, "OPENMS_IDMERGER": { - "openms": "3.4.1" + "openms": "3.5.0" }, "OPENMS_IDSCORESWITCHER": { - "openms": "3.4.1" + "openms": "3.5.0" }, "OPENMS_PEPTIDEINDEXER": { - "openms": "3.4.1" + "openms": "3.5.0" }, "OPENMS_TEXTEXPORTER": { - "openms": "3.4.1" + "openms": "3.5.0" }, "PYOPENMS_CHROMATOGRAMEXTRACTOR": { "pyopenms": "3.4.1" @@ -38,7 +38,7 @@ "pyopenms": "3.4.1" }, "Workflow": { - "nf-core/mhcquant": "v3.1.0" + "nf-core/mhcquant": "v3.2.0dev" } }, [ @@ -112,6 +112,6 @@ "nf-test": "0.9.3", "nextflow": "25.04.8" }, - "timestamp": "2025-10-28T22:04:22.998726246" + "timestamp": "2026-01-24T12:19:49.496533324" } } \ No newline at end of file diff --git a/tests/sdrf.nf.test b/tests/sdrf.nf.test new file mode 100644 index 00000000..6c2d121f --- /dev/null +++ b/tests/sdrf.nf.test @@ -0,0 +1,54 @@ +nextflow_pipeline { + + name "Test pipeline with SDRF input" + script "../main.nf" + tag "pipeline" + profile "test_sdrf" + + test("-profile test_sdrf") { + + 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/sdrf.nf.test.snap b/tests/sdrf.nf.test.snap new file mode 100644 index 00000000..560fff3d --- /dev/null +++ b/tests/sdrf.nf.test.snap @@ -0,0 +1,288 @@ +{ + "-profile test_sdrf": { + "content": [ + { + "MS2RESCORE": { + "MS2Rescore": "3.1.5" + }, + "OPENMSTHIRDPARTY_COMETADAPTER": { + "Comet": "2024.01 rev. 1", + "CometAdapter": "3.5.0" + }, + "OPENMS_DECOYDATABASE": { + "openms": "3.5.0" + }, + "OPENMS_IDFILTER_Q_VALUE": { + "openms": "3.5.0" + }, + "OPENMS_IDMASSACCURACY": { + "openms": "3.4.1" + }, + "OPENMS_IDMERGER": { + "openms": "3.5.0" + }, + "OPENMS_PEPTIDEINDEXER": { + "openms": "3.5.0" + }, + "OPENMS_PERCOLATORADAPTER": { + "PercolatorAdapter": "3.5.0-pre-exported-20251212", + "percolator": "3.07.1" + }, + "OPENMS_PSMFEATUREEXTRACTOR": { + "openms": "3.5.0" + }, + "OPENMS_TEXTEXPORTER": { + "openms": "3.5.0" + }, + "PRIDEPY_DOWNLOAD_FILE": { + "pridepy": "0.0.12" + }, + "PYOPENMS_CHROMATOGRAMEXTRACTOR": { + "pyopenms": "3.4.1" + }, + "SDRF_PIPELINES_PARSE_SDRF": { + "sdrf-pipelines": "0.1.2" + }, + "SUMMARIZE_RESULTS": { + "pyopenms": "3.4.1" + }, + "THERMORAWFILEPARSER": { + "thermorawfileparser": "1.4.5" + }, + "Workflow": { + "nf-core/mhcquant": "v3.2.0dev" + } + }, + [ + "intermediate_results", + "intermediate_results/comet", + "intermediate_results/comet/IP_lung_1T_060317_1_pin.tsv", + "intermediate_results/rescoring", + "intermediate_results/rescoring/lc2_1_ms2rescore.idXML", + "intermediate_results/rescoring/lc2_1_pout.idXML", + "intermediate_results/rescoring/lc2_1_pout_filtered.idXML", + "intermediate_results/rescoring/lc2_1_psm.idXML", + "lc2_1.tsv", + "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", + "sdrf", + "sdrf/samplesheet.tsv", + "sdrf/search_presets.tsv" + ], + [ + "samplesheet.tsv:md5,4d7d2f1ca8d3def75b05ae8c01c481d8", + "search_presets.tsv:md5,3ba3b5c24f71025bfc1799ea87cd0a12" + ], + [ + [ + "lc2_1.tsv", + [ + "AEDGLKHEY", + "AEDKENYKKF", + "AEDKENYKKFY", + "AEGTLSKKL", + "AEKELHEKF", + "ATAQFKINKK", + "ATEQPLTAK", + "ATEQPLTAKK", + "ATFPGMWER", + "ATNKITIIFK", + "ATQTSVVVK", + "AVATALGLK", + "AVIQVSQIVAR", + "AVQEFGLAR", + "AVQEFGLARFK", + "AVSEGTKAVTK", + "AVTDQTVSK", + "AVTKYTSSK", + "AVVELVTVK", + "DAYPEIEKF", + "DYIDTIWKI", + "EEDPNTHILY", + "EEIEILLRY", + "EELQKIYKTY", + "EERVINEEY", + "EETPVVLQL", + "EEVPKRKW", + "EILKWYLNK", + "FPAGKVPAF", + "GEASRLAHY", + "GEWASGGVRSF", + "GGHSGSSYLNTVQK", + "GIAGSLTNK", + "GSLGFTVTK", + "GSQAGGSQTLK", + "GSSPEQVVRPK", + "GSYNKVFLAK", + "GTFLEGVAK", + "GTIHAGQPVK", + "GTNVNMPVSK", + "GTVDKKMVEK", + "GTVTPPPRLVK", + "HFDPEVVQI", + "HPDTGISSKAM", + "HPFIVKLHY", + "HPFLSGAETF", + "HPVEELLDSY", + "HTASPTGMMK", + "HYDAVEAEL", + "IVADHVASY", + "IYLPYLHEW", + "KAFNQGKIFK", + "KEIFLRELI", + "KEIPN(Deamidated)FPTL", + "KPITTGGVTY", + "KSFDTSLIRK", + "KVLHFFNVK", + "KYLADLPTL", + "KYVKVFHKF", + "LPAKDIQTNVY", + "LPALLEKNAM", + "LPPGSVISY", + "LPSSEVVKF", + "LVFPSEIVGK", + "LYDLVTEKM", + "MAIEAQQKF", + "MPVDPNEPTY", + "MPVGMTHGL", + "N(Deamidated)M(Oxidation)TSCHRPICRKEG", + "NAIEDTIFY", + "NESLFGKKY", + "NEYESRSLW", + "NPFEKGDLY", + "NVLDIMVTK", + "NYFHLAVAF", + "NYVPMTPGTFDF", + "PAPPPPPPP", + "PFLPQLQT", + "QELIGKKEY", + "QPFREAIAL", + "QPWEEIKTSY", + "RILFFNTPK", + "RTLQQMLLK", + "RVLDVTKKK", + "RYGPQFTL", + "RYIRDAHTF", + "RYLADLPTL", + "SADRVVAF", + "SAQSFFENK", + "SAVDPVQMK", + "SEADVAQQF", + "SEGTKAVTK", + "SEIAQKQKL", + "SELAEDKENY", + "SEN(Deamidated)ELKKAY", + "SENELKKAY", + "SFSPKTYSF", + "SGSSYLNTVQK", + "SIMEGPLSK", + "SLQDKQ(Deamidated)KGAK", + "SQIEKFQEK", + "SSADGSQPPK", + "SSIQGQWPK", + "SSLYIILKK", + "STDERAYQR", + "STEKIYIRK", + "STLAVTSQK", + "STMGYMMAK", + "STMGYMMAKK", + "SVAELRSQK", + "SVIVQPFSK", + "SVPREPIDRK", + "SVSQPVAQK", + "SYGSVFKAI", + "SYIAAISARF", + "SYQRAFNEF", + "TAADTAVYY", + "TEHYDIPKVSW", + "TENKERKSF", + "TFMDRGFVF", + "TPSSDVLVF", + "TPTGAISQY", + "TVFENLINK", + "TVSETFMSK", + "TYIDKSTQL", + "TYNKVLHFF", + "VPPVFVVSY", + "VPSPAQIMY", + "VPVEEQEEF", + "VSEGTKAVTK", + "VTQSEIAQK", + "VTQSEIAQKQK", + "VVQEPGQVFK", + "VWSDVTPLTF", + "VYEGPELNHAF", + "VYIKHPVSL", + "VYNKVHITL", + "YIKHPVSL", + "YYDVAKQLL", + "YYISPRLTF" + ] + ] + ] + ], + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.10.3" + }, + "timestamp": "2026-04-22T13:14:10.634291398" + } +} \ No newline at end of file diff --git a/tests/search_presets.nf.test b/tests/search_presets.nf.test new file mode 100644 index 00000000..3d441f0b --- /dev/null +++ b/tests/search_presets.nf.test @@ -0,0 +1,56 @@ +nextflow_pipeline { + + name "Test pipeline with search parameter presets" + script "../main.nf" + tag "pipeline" + tag "test_search_presets" + profile "test_search_presets" + + test("-profile test_search_presets") { + + 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 result TSV files (qe and lumos groups) + def peptidoform_data = [] + new File(params.outdir).eachFileRecurse { file -> + if (file.name.endsWith('.tsv') && file.parentFile.path == params.outdir) { + 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]) + } + } + } + } + peptidoform_data.sort { it[0] } + 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 result TSV files + peptidoform_data + ).match() } + ) + } + } +} diff --git a/tests/search_presets.nf.test.snap b/tests/search_presets.nf.test.snap new file mode 100644 index 00000000..4410fbaf --- /dev/null +++ b/tests/search_presets.nf.test.snap @@ -0,0 +1,557 @@ +{ + "-profile test_search_presets": { + "content": [ + { + "MS2RESCORE": { + "MS2Rescore": "3.1.5" + }, + "OPENMSTHIRDPARTY_COMETADAPTER": { + "Comet": "2024.01 rev. 1", + "CometAdapter": "3.5.0" + }, + "OPENMS_DECOYDATABASE": { + "openms": "3.5.0" + }, + "OPENMS_IDFILTER_Q_VALUE": { + "openms": "3.5.0" + }, + "OPENMS_IDMASSACCURACY": { + "openms": "3.4.1" + }, + "OPENMS_IDMERGER": { + "openms": "3.5.0" + }, + "OPENMS_PEPTIDEINDEXER": { + "openms": "3.5.0" + }, + "OPENMS_PERCOLATORADAPTER": { + "PercolatorAdapter": "3.5.0-pre-exported-20251212", + "percolator": "3.07.1" + }, + "OPENMS_PSMFEATUREEXTRACTOR": { + "openms": "3.5.0" + }, + "OPENMS_TEXTEXPORTER": { + "openms": "3.5.0" + }, + "PYOPENMS_CHROMATOGRAMEXTRACTOR": { + "pyopenms": "3.4.1" + }, + "SUMMARIZE_RESULTS": { + "pyopenms": "3.4.1" + }, + "Workflow": { + "nf-core/mhcquant": "v3.2.0dev" + } + }, + [ + "HepG2_lumos.tsv", + "HepG2_qe.tsv", + "intermediate_results", + "intermediate_results/comet", + "intermediate_results/comet/HepG2_rep3_small_pin.tsv", + "intermediate_results/rescoring", + "intermediate_results/rescoring/HepG2_lumos_ms2rescore.idXML", + "intermediate_results/rescoring/HepG2_lumos_pout.idXML", + "intermediate_results/rescoring/HepG2_lumos_pout_filtered.idXML", + "intermediate_results/rescoring/HepG2_lumos_psm.idXML", + "intermediate_results/rescoring/HepG2_qe_ms2rescore.idXML", + "intermediate_results/rescoring/HepG2_qe_pout.idXML", + "intermediate_results/rescoring/HepG2_qe_pout_filtered.idXML", + "intermediate_results/rescoring/HepG2_qe_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_lumos.tsv", + [ + "AAAAAAHRL", + "AAATVTKKV", + "AAHPNVQKV", + "AAM(Oxidation)SVAKRV", + "AANAQPHKL", + "AANDKLKKM", + "AAPPPPAHA", + "AAPRPPPKPM(Oxidation)", + "AAQAHTREL", + "AARAEAREI", + "AASPVGKRL", + "AASSLKKQY", + "AATDHSNQL", + "AATPAKKTV", + "AATVTKKTY", + "AKDVKFGAD", + "ALKDKIEKA", + "ALKDSVQRA", + "ALKKALAAA", + "ALSDLHAHK", + "AM(Oxidation)AARPHSI", + "AM(Oxidation)AASPHAV", + "AM(Oxidation)ASHLTST", + "AM(Oxidation)HGHVEVV", + "AM(Oxidation)NARPHKV", + "AMNARPHKV", + "APPKAHEV", + "APRADAKAY", + "APRPPPKPM(Oxidation)", + "AVM(Oxidation)GNPKVKA", + "DAAVHQRI", + "DAKKQIKQV", + "DAPAGRKV", + "DGKKKISTV", + "DHVITNM(Oxidation)N", + "DNKKTRII", + "DPM(Oxidation)KARVV", + "DPPKTHVT", + "DPPRDSKGL", + "EYSKQM(Oxidation)QRF", + "FADPHSKRV", + "GKVGAHAGEY", + "GKVGAHAGEYG", + "GLAKSIHHA", + "GMAKKVTKA", + "GNVAEGETKPD", + "GPNKKPRF", + "GPRVVERH", + "GRVVEPKR", + "GVM(Oxidation)VGM(Oxidation)GQKD", + "HAAENPGKY", + "HAANPNGRYY", + "HAASRIKTI", + "HAATYTKKV", + "HAGPTAHEL", + "HAKEKLTAL", + "HAM(Oxidation)EEVKKF", + "HAPELTKKV", + "HLKEDQTEY", + "HPAENGKSNF", + "HPESERISM(Oxidation)", + "HPGRPQPPA", + "HPNKVKVY", + "HPYQPDPKM(Oxidation)", + "HSRNEGVATY", + "HSSPASSNY", + "HVKDANGNSF", + "HVSTHQHNY", + "IAPKTTRV", + "IASQTVKKV", + "IKTVETRD", + "IPQKFHRSV", + "ISSEAHREV", + "IVGRPRHQ", + "KAAKPKVV", + "KAAQPKSL", + "KAASHIKSI", + "KAISGVHTV", + "KAKPGTYKV", + "KALVKPKEV", + "KASEQAKVV", + "KASGTLREY", + "KAYGKAKSI", + "KGTGASGSF", + "KLAESVEKA", + "KLAPPPKKA", + "KLQPGSVKKV", + "KM(Oxidation)DESKHEI", + "KM(Oxidation)LDHEYTT", + "KMDESKHEI", + "KMNESTRSV", + "KMQEHSDQV", + "KRSSPETL", + "KSKEFVQKV", + "KTKEGVREV", + "KTLGTDVVKS", + "KVHLGARAS", + "KVVNPTQK", + "KYKERGTVL", + "KYLGKTHNL", + "KYNRQSM(Oxidation)TL", + "KYQPKPKQI", + "KYTPPPHHI", + "LAKTGVHHY", + "LLKSEKSSY", + "LPSENHKEM", + "LPSENHKEM(Oxidation)", + "M(Oxidation)PPEHVRKI", + "M(Oxidation)PQGGGQHY", + "M(Oxidation)PQKERESI", + "MPNKVRKI", + "MPQKERESI", + "NAHGEPRNY", + "NALAHKYH", + "NAM(Oxidation)KIRDV", + "NASARDNTI", + "NATAVVRHM(Oxidation)", + "NGTHVVRHY", + "NIQKITKS", + "NLKVKGPVR", + "NLRPKKKVK", + "NLSSLSKK", + "NLTEEEEKSKS", + "NNLSSLSKK", + "NPAAYENDK", + "NPFGGASHAKG", + "NPKESSSSL", + "NPKREIQKI", + "NQNPGSPRPGSTG", + "NSHSTTSSF", + "NTKGGDAPAAGEDA", + "NTKIGPRR", + "NVDYSKLKK", + "NVINGGSHA", + "NVKIVKVKKE", + "PPNKKPKV", + "QAGPINREM(Oxidation)", + "QALKHLKQY", + "QGVM(Oxidation)VGM(Oxidation)GQK", + "QPAKADKESF", + "QTHQPPAPNS", + "QYKKDGADF", + "RLAEAHAKV", + "RLHEKIQEA", + "RLNNKSAKV", + "RMARTPQTV", + "RPVPKGATY", + "RSNEHIREL", + "RSTENVNKL", + "RSTQYM(Oxidation)KEY", + "RVAGIHKKV", + "RYDDM(Oxidation)AAAM(Oxidation)", + "SAKLERSHY", + "SAM(Oxidation)SNPRAM", + "SAQTTSHEL", + "SARAGETRF", + "SASEAAKKY", + "SATGHPRKV", + "SATSNKHLL", + "SAYANAKKY", + "SEVAHRFK", + "SIVGRPRH", + "SLDKTSHSV", + "SLDTQPKKV", + "SM(Oxidation)LGSPHKV", + "SM(Oxidation)NTHLKAV", + "SM(Oxidation)PEQAHKV", + "SQRFPKAE", + "SSRSYTSGPG", + "SVKNDHSAY", + "SVQVFGRKK", + "SYVGDEAQSKR", + "SYVGDEAQSKRG", + "TAPQTQHV", + "TARPGPRAV", + "TDKSFVEK", + "TDRETGKL", + "TEDSPGLK", + "TEKLVTSK", + "TEKLVTSKG", + "TGSETESPRNPSSA", + "THYDPPRK", + "TKELPSGKKY", + "TKGGDAPAAGEDA", + "TRLSRTPGNR", + "TSGPGSRISSSS", + "TSTPNAKTV", + "TTPISEQKG", + "TVKDSRTVY", + "VAPPKAHEV", + "VARAGQKGY", + "VHLTPEEK", + "VITDKEKAE", + "VPKEGKVV", + "VQKTIAEN", + "VSKGTLVQTKGT", + "VVRHQLLKT", + "VYAQKHQQL", + "VYGKTSHL", + "YADEKTKDV", + "YGSTVSKRV", + "YLNKHIQKV", + "YTKKLNTQ", + "YTM(Oxidation)KKVHAL", + "YVGDEAQSKR", + "YVGDEAQSKRG" + ] + ], + [ + "HepG2_qe.tsv", + [ + "AAAAAAHRL", + "AAATVTKKV", + "AAHPNVQKV", + "AAM(Oxidation)SVAKRV", + "AANAQPHKL", + "AANDKLKKM", + "AAPPPPAHA", + "AAPRPPPKPM(Oxidation)", + "AAQAHTREL", + "AARAEAREI", + "AASPVGKRL", + "AASSLKKQY", + "AATDHSNQL", + "AATPAKKTV", + "AATVTKKTY", + "AKDVKFGAD", + "ALKDKIEKA", + "ALKDSVQRA", + "ALKKALAAA", + "ALSDLHAHK", + "AM(Oxidation)AARPHSI", + "AM(Oxidation)AASPHAV", + "AM(Oxidation)ASHLTST", + "AM(Oxidation)HGHVEVV", + "AM(Oxidation)NARPHKV", + "AMNARPHKV", + "APPKAHEV", + "APRADAKAY", + "APRPPPKPM(Oxidation)", + "AVM(Oxidation)GNPKVKA", + "DAAVHQRI", + "DAKKQIKQV", + "DAPAGRKV", + "DGKKKISTV", + "DHVITNM(Oxidation)N", + "DNKKTRII", + "DPM(Oxidation)KARVV", + "DPPKTHVT", + "DPPRDSKGL", + "EYSKQM(Oxidation)QRF", + "FADPHSKRV", + "GKVGAHAGEY", + "GKVGAHAGEYG", + "GLAKSIHHA", + "GMAKKVTKA", + "GNVAEGETKPD", + "GPNKKPRF", + "GPRVVERH", + "GRVVEPKR", + "GVM(Oxidation)VGM(Oxidation)GQKD", + "HAAENPGKY", + "HAANPNGRYY", + "HAASRIKTI", + "HAATYTKKV", + "HAGPTAHEL", + "HAKEKLTAL", + "HAM(Oxidation)EEVKKF", + "HAPELTKKV", + "HLKEDQTEY", + "HPAENGKSNF", + "HPESERISM(Oxidation)", + "HPGRPQPPA", + "HPNKVKVY", + "HPYQPDPKM(Oxidation)", + "HSRNEGVATY", + "HSSPASSNY", + "HVKDANGNSF", + "HVSTHQHNY", + "IAPKTTRV", + "IASQTVKKV", + "IKTVETRD", + "IPQKFHRSV", + "ISSEAHREV", + "IVGRPRHQ", + "KAAKPKVV", + "KAAQPKSL", + "KAASHIKSI", + "KAISGVHTV", + "KAKPGTYKV", + "KALVKPKEV", + "KASEQAKVV", + "KASGTLREY", + "KAYGKAKSI", + "KGTGASGSF", + "KLAESVEKA", + "KLAPPPKKA", + "KLQPGSVKKV", + "KM(Oxidation)DESKHEI", + "KM(Oxidation)LDHEYTT", + "KMDESKHEI", + "KMNESTRSV", + "KMQEHSDQV", + "KRSSPETL", + "KSKEFVQKV", + "KTKEGVREV", + "KTLGTDVVKS", + "KVHLGARAS", + "KVVNPTQK", + "KYKERGTVL", + "KYLGKTHNL", + "KYNRQSM(Oxidation)TL", + "KYQPKPKQI", + "KYTPPPHHI", + "LAKTGVHHY", + "LLKSEKSSY", + "LPSENHKEM", + "LPSENHKEM(Oxidation)", + "M(Oxidation)PPEHVRKI", + "M(Oxidation)PQGGGQHY", + "M(Oxidation)PQKERESI", + "MPNKVRKI", + "MPQKERESI", + "NAHGEPRNY", + "NALAHKYH", + "NAM(Oxidation)KIRDV", + "NASARDNTI", + "NATAVVRHM(Oxidation)", + "NGTHVVRHY", + "NIQKITKS", + "NLKVKGPVR", + "NLRPKKKVK", + "NLSSLSKK", + "NLTEEEEKSKS", + "NNLSSLSKK", + "NPAAYENDK", + "NPFGGASHAKG", + "NPKESSSSL", + "NPKREIQKI", + "NQNPGSPRPGSTG", + "NSHSTTSSF", + "NTKGGDAPAAGEDA", + "NTKIGPRR", + "NVDYSKLKK", + "NVINGGSHA", + "NVKIVKVKKE", + "PPNKKPKV", + "QAGPINREM(Oxidation)", + "QALKHLKQY", + "QGVM(Oxidation)VGM(Oxidation)GQK", + "QPAKADKESF", + "QTHQPPAPNS", + "QYKKDGADF", + "RLAEAHAKV", + "RLHEKIQEA", + "RLNNKSAKV", + "RMARTPQTV", + "RPVPKGATY", + "RSNEHIREL", + "RSTENVNKL", + "RSTQYM(Oxidation)KEY", + "RVAGIHKKV", + "RYDDM(Oxidation)AAAM(Oxidation)", + "SAKLERSHY", + "SAM(Oxidation)SNPRAM", + "SAQTTSHEL", + "SARAGETRF", + "SASEAAKKY", + "SATGHPRKV", + "SATSNKHLL", + "SAYANAKKY", + "SEVAHRFK", + "SIVGRPRH", + "SLDKTSHSV", + "SLDTQPKKV", + "SM(Oxidation)LGSPHKV", + "SM(Oxidation)NTHLKAV", + "SM(Oxidation)PEQAHKV", + "SQRFPKAE", + "SSRSYTSGPG", + "SVKNDHSAY", + "SVQVFGRKK", + "SYVGDEAQSKR", + "SYVGDEAQSKRG", + "TAPQTQHV", + "TARPGPRAV", + "TDKSFVEK", + "TDRETGKL", + "TEDSPGLK", + "TEKLVTSK", + "TEKLVTSKG", + "TGSETESPRNPSSA", + "THYDPPRK", + "TKELPSGKKY", + "TKGGDAPAAGEDA", + "TRLSRTPGNR", + "TSGPGSRISSSS", + "TSTPNAKTV", + "TTPISEQKG", + "TVKDSRTVY", + "VAPPKAHEV", + "VARAGQKGY", + "VHLTPEEK", + "VITDKEKAE", + "VPKEGKVV", + "VQKTIAEN", + "VSKGTLVQTKGT", + "VVRHQLLKT", + "VYAQKHQQL", + "VYGKTSHL", + "YADEKTKDV", + "YGSTVSKRV", + "YLNKHIQKV", + "YTKKLNTQ", + "YTM(Oxidation)KKVHAL", + "YVGDEAQSKR", + "YVGDEAQSKRG" + ] + ] + ] + ], + "meta": { + "nf-test": "0.9.3", + "nextflow": "25.10.3" + }, + "timestamp": "2026-02-13T13:35:56.062370587" + } +} \ No newline at end of file diff --git a/tests/speclib.nf.test.snap b/tests/speclib.nf.test.snap index 4864a01a..2c4e1612 100644 --- a/tests/speclib.nf.test.snap +++ b/tests/speclib.nf.test.snap @@ -4,42 +4,45 @@ 28, { "EASYPQP_CONVERT": { - "easypqp": "0.1.53" + "easypqp": "0.1.57" }, "EASYPQP_LIBRARY": { - "easypqp": "0.1.53" + "easypqp": "0.1.57" }, "MS2RESCORE": { - "MS\u00b2Rescore": "3.1.5)" + "MS2Rescore": "3.1.5" }, "OPENMSTHIRDPARTY_COMETADAPTER": { - "CometAdapter": "3.4.1", - "Comet": "2024.01 rev. 1" + "Comet": "2024.01 rev. 1", + "CometAdapter": "3.5.0" }, "OPENMS_DECOYDATABASE": { - "openms": "3.4.1" + "openms": "3.5.0" + }, + "OPENMS_IDFILTER_FOR_SPECLIB": { + "openms": "3.5.0" }, "OPENMS_IDFILTER_Q_VALUE": { - "openms": "3.4.1" + "openms": "3.5.0" }, "OPENMS_IDMASSACCURACY": { - "OpenMS": "3.4.1" + "openms": "3.4.1" }, "OPENMS_IDMERGER": { - "openms": "3.4.1" + "openms": "3.5.0" }, "OPENMS_PEPTIDEINDEXER": { - "openms": "3.4.1" + "openms": "3.5.0" }, "OPENMS_PERCOLATORADAPTER": { - "PercolatorAdapter": "3.4.1-pre-exported-20250822", - "percolator": "3.07.1, Build Date Mar 13 2025 17:19:27" + "PercolatorAdapter": "3.5.0-pre-exported-20251212", + "percolator": "3.07.1" }, "OPENMS_PSMFEATUREEXTRACTOR": { - "openms": "3.4.1" + "openms": "3.5.0" }, "OPENMS_TEXTEXPORTER": { - "openms": "3.4.1" + "openms": "3.5.0" }, "PYOPENMS_CHROMATOGRAMEXTRACTOR": { "pyopenms": "3.4.1" @@ -48,7 +51,7 @@ "pyopenms": "3.4.1" }, "Workflow": { - "nf-core/mhcquant": "v3.1.0" + "nf-core/mhcquant": "v3.2.0dev" } }, [ @@ -391,8 +394,8 @@ ], "meta": { "nf-test": "0.9.3", - "nextflow": "25.04.8" + "nextflow": "25.10.3" }, - "timestamp": "2025-10-28T22:13:30.098880662" + "timestamp": "2026-02-12T14:02:45.605055829" } -} \ No newline at end of file +} diff --git a/tests/test_single_quant.nf.test b/tests/test_single_quant.nf.test new file mode 100644 index 00000000..456957f8 --- /dev/null +++ b/tests/test_single_quant.nf.test @@ -0,0 +1,54 @@ +nextflow_pipeline { + + name "Test pipeline for single replicate" + script "../main.nf" + tag "pipeline" + tag "single_replicate" + + test("-profile test_single_quant") { + + 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/test_single_quant.nf.test.snap b/tests/test_single_quant.nf.test.snap new file mode 100644 index 00000000..12b2533a --- /dev/null +++ b/tests/test_single_quant.nf.test.snap @@ -0,0 +1,389 @@ +{ + "-profile test_single_quant": { + "content": [ + { + "MS2RESCORE": { + "MS2Rescore": "3.1.5" + }, + "OPENMSTHIRDPARTY_COMETADAPTER": { + "Comet": "2024.01 rev. 1", + "CometAdapter": "3.5.0" + }, + "OPENMS_DECOYDATABASE": { + "openms": "3.5.0" + }, + "OPENMS_IDFILTER_Q_VALUE": { + "openms": "3.5.0" + }, + "OPENMS_IDMASSACCURACY": { + "openms": "3.4.1" + }, + "OPENMS_IDMERGER": { + "openms": "3.5.0" + }, + "OPENMS_PEPTIDEINDEXER": { + "openms": "3.5.0" + }, + "OPENMS_PERCOLATORADAPTER": { + "PercolatorAdapter": "3.5.0-pre-exported-20251212", + "percolator": "3.07.1" + }, + "OPENMS_PSMFEATUREEXTRACTOR": { + "openms": "3.5.0" + }, + "OPENMS_TEXTEXPORTER": { + "openms": "3.5.0" + }, + "PYOPENMS_CHROMATOGRAMEXTRACTOR": { + "pyopenms": "3.4.1" + }, + "SUMMARIZE_RESULTS": { + "pyopenms": "3.4.1" + }, + "Workflow": { + "nf-core/mhcquant": "v3.2.0dev" + } + }, + [ + "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.10.3" + }, + "timestamp": "2026-02-12T14:09:29.998035249" + } +} \ No newline at end of file diff --git a/workflows/mhcquant.nf b/workflows/mhcquant.nf index dad8d043..ae38634c 100644 --- a/workflows/mhcquant.nf +++ b/workflows/mhcquant.nf @@ -10,6 +10,7 @@ include { PYOPENMS_CHROMATOGRAMEXTRACTOR } from '../modules/local/pyopenms/chromatogramextractor' include { PYOPENMS_IONANNOTATOR } from '../modules/local/pyopenms/ionannotator' +include { OPENMS_IDMASSACCURACY } from '../modules/local/openms/idmassaccuracy/main' include { OPENMS_TEXTEXPORTER } from '../modules/local/openms/textexporter' include { SUMMARIZE_RESULTS } from '../modules/local/pyopenms/summarize_results' include { EPICORE } from '../modules/local/epicore' @@ -33,7 +34,6 @@ include { QUANT } from '../subworkflows/local/quant' // include { OPENMS_FILEFILTER } from '../modules/nf-core/openms/filefilter/main' include { OPENMS_DECOYDATABASE } from '../modules/nf-core/openms/decoydatabase/main' -include { OPENMS_IDMASSACCURACY } from '../modules/nf-core/openms/idmassaccuracy/main' include { OPENMSTHIRDPARTY_COMETADAPTER } from '../modules/nf-core/openmsthirdparty/cometadapter/main' include { OPENMS_PEPTIDEINDEXER } from '../modules/nf-core/openms/peptideindexer/main' include { OPENMS_IDMERGER } from '../modules/nf-core/openms/idmerger/main' @@ -57,18 +57,15 @@ workflow MHCQUANT { ch_fasta // channel: reference database read in from --fasta main: - ch_versions = Channel.empty() - ch_multiqc_files = Channel.empty() + ch_multiqc_files = channel.empty() // Prepare spectra files (Decompress archives, convert to mzML, centroid if specified) PREPARE_SPECTRA(ch_samplesheet) - ch_versions = ch_versions.mix(PREPARE_SPECTRA.out.versions) // Decoy Database creation if (!params.skip_decoy_generation) { // 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 } else { ch_decoy_db = ch_fasta @@ -77,7 +74,6 @@ workflow MHCQUANT { // Optionally clean up mzML files if (params.filter_mzml){ OPENMS_FILEFILTER(PREPARE_SPECTRA.out.mzml) - ch_versions = ch_versions.mix(OPENMS_FILEFILTER.out.versions) ch_clean_mzml_file = OPENMS_FILEFILTER.out.mzml } else { ch_clean_mzml_file = PREPARE_SPECTRA.out.mzml @@ -85,7 +81,6 @@ workflow MHCQUANT { // Compute MS1 TICs for QC PYOPENMS_CHROMATOGRAMEXTRACTOR(ch_clean_mzml_file) - ch_versions = ch_versions.mix(PYOPENMS_CHROMATOGRAMEXTRACTOR.out.versions) ch_multiqc_files = ch_multiqc_files.mix(PYOPENMS_CHROMATOGRAMEXTRACTOR.out.csv.map{ meta, mzml -> mzml }) // Prepare the comet input channel with global fasta or per-sample_condition fasta @@ -98,7 +93,6 @@ workflow MHCQUANT { // Run comet database search and index decoy and target hits OPENMSTHIRDPARTY_COMETADAPTER(ch_comet_in) - ch_versions = ch_versions.mix(OPENMSTHIRDPARTY_COMETADAPTER.out.versions) // Prepare the peptideindexer channel with global fasta or per-sample_condition fasta ch_peptideindexer_in = params.fasta ? @@ -109,11 +103,9 @@ workflow MHCQUANT { .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) 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 @@ -129,21 +121,24 @@ workflow MHCQUANT { // Merge aligned idXMLfiles OPENMS_IDMERGER(ch_runs_to_merge) - ch_versions = ch_versions.mix(OPENMS_IDMERGER.out.versions) // Run MS2Rescore ch_clean_mzml_file - .map { meta, mzml -> [ groupKey([id: "${meta.sample}_${meta.condition}"], meta.group_count), mzml] } + .map { meta, mzml -> [ groupKey([id: "${meta.sample}_${meta.condition}"], meta.group_count), meta, mzml] } .groupTuple() .join(OPENMS_IDMERGER.out.idxml) - .map { meta, mzml, idxml -> [meta, idxml, mzml, []] } + .map { gkey, metas, mzmls, idxml -> + // All replicates in a group share the same search params + def meta = metas[0] + def searchMeta = meta.subMap(meta.keySet() - ['id', 'sample', 'condition', 'group_count', 'spectra']) + [[id: "${meta.sample}_${meta.condition}"] + searchMeta, idxml, mzmls, []] + } .set { ch_rescore_in } // // SUBWORKFLOW: RESCORE WITH MOKKAPOT OR PERCOLATOR AND FILTER BY Q-VALUE ON LOCAL/GLOBAL FDR // RESCORE( ch_rescore_in, ch_multiqc_files ) - ch_versions = ch_versions.mix(RESCORE.out.versions) ch_multiqc_files = ch_multiqc_files.mix(RESCORE.out.multiqc_files) // GENERATE SPECTRUM LIBRARY @@ -164,7 +159,6 @@ workflow MHCQUANT { // SUBWORKFLOW: SPECLIB // SPECLIB(ch_fdrfilter_comet_idxml_filtered, ch_clean_mzml_file) - ch_versions = ch_versions.mix(SPECLIB.out.versions) } // @@ -172,7 +166,6 @@ workflow MHCQUANT { // if (params.quantify) { QUANT(merge_meta_map, RESCORE.out.rescored_runs, RESCORE.out.fdr_filtered, ch_clean_mzml_file) - ch_versions = ch_versions.mix(QUANT.out.versions) ch_output = QUANT.out.consensusxml } else { ch_output = RESCORE.out.fdr_filtered @@ -180,20 +173,23 @@ workflow MHCQUANT { // Annotate Ions for follow-up spectrum validation if (params.annotate_ions) { - // Join the ch_filtered_idxml and the ch_mzml_file - ch_clean_mzml_file.map { meta, mzml -> [ groupKey([id: "${meta.sample}_${meta.condition}"], meta.group_count), mzml] } + // Join mzml files and fdr-filtered idxml, reconstructing search params from ch_clean_mzml_file + ch_clean_mzml_file.map { meta, mzml -> + [ [id: "${meta.sample}_${meta.condition}"], + meta.subMap(meta.keySet() - ['id', 'sample', 'condition', 'group_count', 'spectra']), + mzml ] + } .groupTuple() .join(RESCORE.out.fdr_filtered) + .map { key, searchMetas, mzmls, idxml -> [key + searchMetas[0], mzmls, idxml] } .set{ ch_ion_annotator_input } // Annotate spectra with ion fragmentation information PYOPENMS_IONANNOTATOR( ch_ion_annotator_input ) - ch_versions = ch_versions.mix(PYOPENMS_IONANNOTATOR.out.versions) } // Prepare for check if file is empty OPENMS_TEXTEXPORTER(ch_output) - ch_versions = ch_versions.mix(OPENMS_TEXTEXPORTER.out.versions) // Return an error message when there is only a header present in the document OPENMS_TEXTEXPORTER.out.tsv.map { meta, tsv -> if (tsv.size() < 130) { @@ -203,14 +199,12 @@ workflow MHCQUANT { // Process the tsv file to facilitate visualization with MultiQC 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) + EPICORE(ch_fasta.map{ fasta -> fasta.last()}.first(), SUMMARIZE_RESULTS.out.epicore_input) ch_multiqc_files = ch_multiqc_files.mix( EPICORE.out.length_dist, EPICORE.out.intensity_hist @@ -224,6 +218,7 @@ workflow MHCQUANT { SUMMARIZE_RESULTS.out.hist_mz, SUMMARIZE_RESULTS.out.hist_rt, SUMMARIZE_RESULTS.out.hist_scores, + SUMMARIZE_RESULTS.out.hist_im, SUMMARIZE_RESULTS.out.xcorr, SUMMARIZE_RESULTS.out.lengths, SUMMARIZE_RESULTS.out.intensities, @@ -233,7 +228,25 @@ workflow MHCQUANT { // // Collate and save software versions // - softwareVersionsToYAML(ch_versions) + def topic_versions = channel.topic("versions") + .distinct() + .branch { entry -> + versions_file: entry instanceof Path + versions_tuple: true + } + + def topic_versions_string = topic_versions.versions_tuple + .map { process, tool, version -> + [ process[process.lastIndexOf(':')+1..-1], " ${tool}: ${version}" ] + } + .groupTuple(by:0) + .map { process, tool_versions -> + tool_versions.unique().sort() + "${process}:\n${tool_versions.join('\n')}" + } + + softwareVersionsToYAML(topic_versions.versions_file) + .mix(topic_versions_string) .collectFile( storeDir: "${params.outdir}/pipeline_info", name: 'nf_core_' + 'mhcquant_software_' + 'mqc_' + 'versions.yml', @@ -244,24 +257,24 @@ workflow MHCQUANT { // // MODULE: MultiQC // - ch_multiqc_config = Channel.fromPath( + ch_multiqc_config = channel.fromPath( "$projectDir/assets/multiqc_config.yml", checkIfExists: true) ch_multiqc_custom_config = params.multiqc_config ? - Channel.fromPath(params.multiqc_config, checkIfExists: true) : - Channel.empty() + channel.fromPath(params.multiqc_config, checkIfExists: true) : + channel.empty() ch_multiqc_logo = params.multiqc_logo ? - Channel.fromPath(params.multiqc_logo, checkIfExists: true) : - Channel.empty() + channel.fromPath(params.multiqc_logo, checkIfExists: true) : + channel.empty() summary_params = paramsSummaryMap( workflow, parameters_schema: "nextflow_schema.json") - ch_workflow_summary = Channel.value(paramsSummaryMultiqc(summary_params)) + ch_workflow_summary = channel.value(paramsSummaryMultiqc(summary_params)) ch_multiqc_files = ch_multiqc_files.mix( ch_workflow_summary.collectFile(name: 'workflow_summary_mqc.yaml')) ch_multiqc_custom_methods_description = params.multiqc_methods_description ? file(params.multiqc_methods_description, checkIfExists: true) : file("$projectDir/assets/methods_description_template.yml", checkIfExists: true) - ch_methods_description = Channel.value( + ch_methods_description = channel.value( methodsDescriptionText(ch_multiqc_custom_methods_description)) ch_multiqc_files = ch_multiqc_files.mix(ch_collated_versions) @@ -282,8 +295,6 @@ workflow MHCQUANT { ) emit:multiqc_report = MULTIQC.out.report.toList() // channel: /path/to/multiqc_report.html - versions = ch_versions // channel: [ path(versions.yml) ] - } /*