Skip to content

Commit eeae581

Browse files
authored
Merge pull request #639 from bigbio/copilot/deprecate-openms-schema-input
Deprecate OpenMS experimental design format, enforce SDRF-only input
2 parents cc20b80 + 5f22aa8 commit eeae581

11 files changed

Lines changed: 93 additions & 132 deletions

File tree

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/)
44
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
55

6+
## [1.8.0] bigbio/quantms - [Unreleased]
7+
8+
### `Deprecations`
9+
10+
- **BREAKING: Deprecated OpenMS experimental design format as input**: The pipeline now only accepts SDRF (Sample to Data Relation Format) files as input. The OpenMS experimental design format (`.tsv` without SDRF structure) is no longer supported. All input files are now treated as SDRF regardless of file extension. Supported file extensions for SDRF input are `.sdrf`, `.tsv`, and `.csv`. This change aligns with nf-core best practices and simplifies input handling for cloud storage interfaces like Seqera Datastudios and Explorer. Users must convert their OpenMS experimental design files to SDRF format. The `--labelling_type` and `--acquisition_method` parameters are no longer used for determining input file type - all information must be specified in the SDRF file.
11+
612
## [1.7.0] bigbio/quantms - [08/01/2026] - [Caracas]
713

814
### `Added`

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ Have a look at public datasets that were already annotated [here](https://github
9999
Those SDRFs should be ready for one-command re-analysis and you can just use the URL to the file on GitHub,
100100
e.g., `https://raw.githubusercontent.com/bigbio/proteomics-sample-metadata/master/annotated-projects/PXD000396/PXD000396.sdrf.tsv`.
101101
If you create your own, please adhere to the specifications and point the pipeline to your local folder or a remote location where you uploaded it to.
102+
The SDRF file can have `.sdrf`, `.tsv`, or `.csv` extensions.
102103

103104
The second requirement is a protein sequence database. We suggest downloading a database for the organism(s)/proteins of interest from [Uniprot](https://www.uniprot.org/proteomes?query=*).
104105

conf/tests/test_lfq.config

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ params {
2626

2727
// Input data
2828
labelling_type = "label free sample"
29-
input = 'https://raw.githubusercontent.com/bigbio/quantms-test-datasets/quantms/testdata/lfq_ci/BSA/BSA_design_urls.tsv'
29+
input = 'https://raw.githubusercontent.com/bigbio/quantms-test-datasets/refs/heads/quantms/testdata/lfq_ci/BSA/BSA_design.sdrf.tsv'
3030
database = 'https://raw.githubusercontent.com/bigbio/quantms-test-datasets/quantms/testdata/lfq_ci/BSA/18Protein_SoCe_Tr_detergents_trace_target_decoy.fasta'
3131
search_engines = "comet,sage"
3232
decoy_string= "rev"

docs/usage.md

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,7 @@ The typical command for running the pipeline is as follows:
1414
nextflow run bigbio/quantms --input '/url/path/to/your/experiment_design.sdrf.tsv' --database '/url/path/to/your/proteindatabase.fasta' --outdir './results' -profile docker
1515
```
1616

17-
where the experimental design file has to be one of:
18-
19-
- [Sample-to-data-relationship format](https://pubs.acs.org/doi/abs/10.1021/acs.jproteome.0c00376) (.sdrf.tsv)
20-
- [OpenMS experimental design format](https://abibuilder.cs.uni-tuebingen.de/archive/openms/Documentation/release/latest/html/classOpenMS_1_1ExperimentalDesign.html#details) (.tsv)
17+
The input file must be in [Sample-to-data-relationship format (SDRF)](https://pubs.acs.org/doi/abs/10.1021/acs.jproteome.0c00376) and can have `.sdrf`, `.tsv`, or `.csv` file extensions.
2118

2219
### Supported file formats
2320

modules/local/samplesheet_check/main.nf

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,29 +9,39 @@ process SAMPLESHEET_CHECK {
99

1010
input:
1111
path input_file
12-
val is_sdrf
1312
val validate_ontologies
1413

1514
output:
1615
path "*.log", emit: log
17-
path "${input_file}", emit: checked_file
16+
path "*.sdrf.tsv", includeInputs: true, emit: checked_file
1817
path "versions.yml", emit: versions
1918

2019
when:
2120
task.ext.when == null || task.ext.when
2221

23-
script: // This script is bundled with the pipeline, in bigbio/quantms/bin/
24-
// TODO validate experimental design file
22+
script:
2523
def args = task.ext.args ?: ''
2624
def string_skip_sdrf_validation = params.validate_ontologies == false ? "--skip_sdrf_validation" : ""
2725
def string_skip_ms_validation = params.skip_ms_validation == true ? "--skip_ms_validation" : ""
2826
def string_skip_factor_validation = params.skip_factor_validation == true ? "--skip_factor_validation" : ""
2927
def string_skip_experimental_design_validation = params.skip_experimental_design_validation == true ? "--skip_experimental_design_validation" : ""
3028
def string_use_ols_cache_only = params.use_ols_cache_only == true ? "--use_ols_cache_only" : ""
31-
def string_is_sdrf = is_sdrf == true ? "--is_sdrf" : ""
3229

3330
"""
34-
quantmsutilsc checksamplesheet --exp_design "${input_file}" ${string_is_sdrf} \\
31+
# Get basename and create output filename
32+
BASENAME=\$(basename "${input_file}")
33+
# Remove .sdrf.tsv, .sdrf.csv, or .sdrf extension (in that order to match longest first)
34+
BASENAME=\$(echo "\$BASENAME" | sed -E 's/\\.sdrf\\.(tsv|csv)\$//' | sed -E 's/\\.sdrf\$//')
35+
OUTPUT_FILE="\${BASENAME}.sdrf.tsv"
36+
37+
# Convert CSV to TSV if needed using pandas
38+
if [[ "${input_file}" == *.csv ]]; then
39+
python -c "import pandas as pd; df = pd.read_csv('${input_file}'); df.to_csv('\$OUTPUT_FILE', sep='\\t', index=False)"
40+
elif [[ "${input_file}" != "\$OUTPUT_FILE" ]]; then
41+
cp "${input_file}" "\$OUTPUT_FILE"
42+
fi
43+
44+
quantmsutilsc checksamplesheet --exp_design "\$OUTPUT_FILE" --is_sdrf \\
3545
${string_skip_sdrf_validation} \\
3646
${string_skip_ms_validation} \\
3747
${string_skip_factor_validation} \\

modules/local/samplesheet_check/meta.yml

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,7 @@ input:
1111
- meta: input_file
1212
type: file
1313
description: Input samplesheet or experimental design file
14-
pattern: "*.{tsv,txt,csv}"
15-
- meta: is_sdrf
16-
type: boolean
17-
description: Whether the input file is in SDRF format
14+
pattern: "*.{tsv,csv,sdrf}"
1815
- meta: validate_ontologies
1916
type: boolean
2017
description: Whether to validate ontologies
@@ -26,7 +23,7 @@ output:
2623
- meta: checked_file
2724
type: file
2825
description: Validated input file
29-
pattern: "*.{tsv,txt,csv}"
26+
pattern: "*.{sdrf.tsv}"
3027
- meta: versions
3128
type: file
3229
description: File containing software versions

nextflow_schema.json

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@
1616
"type": "string",
1717
"format": "file-path",
1818
"exists": true,
19-
"mimetype": "text/tsv",
20-
"pattern": "^\\S+\\.(?:tsv|sdrf)$",
21-
"description": "URI/path to an [SDRF](https://github.com/bigbio/proteomics-metadata-standard/tree/master/annotated-projects) file (.sdrf.tsv) **OR** [OpenMS-style experimental design](https://abibuilder.cs.uni-tuebingen.de/archive/openms/Documentation/release/latest/html/classOpenMS_1_1ExperimentalDesign.html#details) with paths to spectra files (.tsv)",
22-
"help_text": "Input is specified by using a path or URI to a PRIDE Sample to Data Relation Format file (SDRF), e.g. as part of a submitted and\nannotated PRIDE experiment (see [here](https://github.com/bigbio/proteomics-metadata-standard/tree/master/annotated-projects) for examples). Input files will be downloaded and cached from the URIs specified in the SDRF file.\nAn OpenMS-style experimental design will be generated based on the factor columns of the SDRF. The settings for the\nfollowing parameters will currently be overwritten by the ones specified in the SDRF:\n\n * `fixed_mods`,\n * `variable_mods`,\n * `precursor_mass_tolerance`,\n * `precursor_mass_tolerance_unit`,\n * `fragment_mass_tolerance`,\n * `fragment_mass_tolerance_unit`,\n * `fragment_method`,\n * `enzyme`\n You can also specify an [OpenMS-style experimental design](https://abibuilder.cs.uni-tuebingen.de/archive/openms/Documentation/release/latest/html/classOpenMS_1_1ExperimentalDesign.html#details) directly (.tsv ending). In this case, the aforementioned parameters have to be specified or defaults will be used.",
19+
"mimetype": "text/csv",
20+
"pattern": "^\\S+\\.(?:csv|tsv|sdrf)$",
21+
"description": "URI/path to an SDRF file in SDRF format with .sdrf, .tsv, or .csv extension. For more info see help text or docs.",
22+
"help_text": "Input is specified by using a path or URI to a PRIDE Sample to Data Relation Format file (SDRF), e.g. as part of a submitted and annotated PRIDE experiment (see [here](https://github.com/bigbio/proteomics-metadata-standard/tree/master/annotated-projects) for examples). Input files will be downloaded and cached from the URIs specified in the SDRF file.\n\nThe SDRF file can have .sdrf, .tsv, or .csv extensions. An OpenMS-style experimental design will be generated based on the factor columns of the SDRF. The settings for the following parameters will currently be overwritten by the ones specified in the SDRF:\n\n * `fixed_mods`,\n * `variable_mods`,\n * `precursor_mass_tolerance`,\n * `precursor_mass_tolerance_unit`,\n * `fragment_mass_tolerance`,\n * `fragment_mass_tolerance_unit`,\n * `fragment_method`,\n * `enzyme`",
2323
"fa_icon": "fas fa-file-csv"
2424
},
2525
"outdir": {
@@ -43,16 +43,16 @@
4343
},
4444
"root_folder": {
4545
"type": "string",
46-
"description": "Root folder in which the spectrum files specified in the SDRF/design are searched",
46+
"description": "Root folder in which the spectrum files specified in the SDRF are searched",
4747
"fa_icon": "fas fa-folder",
48-
"help_text": "This optional parameter can be used to specify a root folder in which the spectrum files specified in the SDRF/design are searched.\nIt is usually used if you have a local version of the experiment already. Note that this option does not support recursive\nsearching yet."
48+
"help_text": "This optional parameter can be used to specify a root folder in which the spectrum files specified in the SDRF are searched.\nIt is usually used if you have a local version of the experiment already. Note that this option does not support recursive\nsearching yet."
4949
},
5050
"local_input_type": {
5151
"type": "string",
52-
"description": "Overwrite the file type/extension of the filename as specified in the SDRF/design",
52+
"description": "Overwrite the file type/extension of the filename as specified in the SDRF",
5353
"fa_icon": "fas fa-file-invoice",
5454
"default": "mzML",
55-
"help_text": "If the above [`--root_folder`](#root_folder) was given to load local input files, this overwrites the file type/extension of\nthe filename as specified in the SDRF/design. Usually used in case you have an mzML-converted version of the files already. Needs to be\none of 'mzML', 'raw', 'd', or 'dia' (the letter cases should match your files exactly). Compressed variants (.gz, .tar, .tar.gz, .zip) are supported for 'mzML', 'raw', and 'd' formats."
55+
"help_text": "If the above [`--root_folder`](#root_folder) was given to load local input files, this overwrites the file type/extension of\nthe filename as specified in the SDRF. Usually used in case you have an mzML-converted version of the files already. Needs to be\none of 'mzML', 'raw', 'd', or 'dia' (the letter cases should match your files exactly). Compressed variants (.gz, .tar, .tar.gz, .zip) are supported for 'mzML', 'raw', and 'd' formats."
5656
},
5757
"acquisition_method": {
5858
"type": "string",

subworkflows/local/create_input_channel/main.nf

Lines changed: 54 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -2,50 +2,34 @@
22
// Create channel for input file
33
//
44
include { SDRF_PARSING } from '../../../modules/local/sdrf_parsing/main'
5-
include { PREPROCESS_EXPDESIGN } from '../../../modules/local/preprocess_expdesign'
65

76

87

98
workflow CREATE_INPUT_CHANNEL {
109
take:
11-
ch_sdrf_or_design
12-
is_sdrf
10+
ch_sdrf
1311

1412
main:
1513
ch_versions = channel.empty()
1614

17-
if (is_sdrf.toString().toLowerCase().contains("true")) {
18-
SDRF_PARSING(ch_sdrf_or_design)
19-
ch_versions = ch_versions.mix(SDRF_PARSING.out.versions)
20-
ch_config = SDRF_PARSING.out.ch_sdrf_config_file
21-
22-
ch_expdesign = SDRF_PARSING.out.ch_expdesign
23-
}
24-
else {
25-
PREPROCESS_EXPDESIGN(ch_sdrf_or_design)
26-
ch_versions = ch_versions.mix(PREPROCESS_EXPDESIGN.out.versions)
27-
28-
ch_config = PREPROCESS_EXPDESIGN.out.ch_config
29-
ch_expdesign = PREPROCESS_EXPDESIGN.out.ch_expdesign
30-
}
15+
// Always parse as SDRF (OpenMS experimental design format deprecated)
16+
SDRF_PARSING(ch_sdrf)
17+
ch_versions = ch_versions.mix(SDRF_PARSING.out.versions)
18+
ch_config = SDRF_PARSING.out.ch_sdrf_config_file
19+
ch_expdesign = SDRF_PARSING.out.ch_expdesign
3120

3221
def Set enzymes = []
3322
def Set files = []
3423

35-
// TODO remove. We can't use the variable to direct channels anyway
3624
def wrapper = [
3725
labelling_type: "",
3826
acquisition_method: "",
39-
experiment_id: ch_sdrf_or_design,
27+
experiment_id: ch_sdrf,
4028
]
4129

42-
if (is_sdrf.toString().toLowerCase().contains("false")) {
43-
log.info("No SDRF given. Using parameters to determine tolerance, enzyme, mod. and labelling settings")
44-
}
45-
4630
ch_config
4731
.splitCsv(header: true, sep: '\t')
48-
.map { row -> create_meta_channel(row, is_sdrf, enzymes, files, wrapper) }
32+
.map { row -> create_meta_channel(row, enzymes, files, wrapper) }
4933
.branch { item ->
5034
ch_meta_config_dia: item[0].acquisition_method.contains("dia")
5135
ch_meta_config_iso: item[0].labelling_type.contains("tmt") || item[0].labelling_type.contains("itraq")
@@ -65,20 +49,16 @@ workflow CREATE_INPUT_CHANNEL {
6549
}
6650

6751
// Function to get list of [meta, [ spectra_files ]]
68-
def create_meta_channel(LinkedHashMap row, is_sdrf, enzymes, files, wrapper) {
52+
def create_meta_channel(LinkedHashMap row, enzymes, files, wrapper) {
6953
def meta = [:]
7054
def filestr
7155

72-
if (is_sdrf.toString().toLowerCase().contains("false")) {
73-
filestr = row.Spectra_Filepath.toString()
56+
// Always use SDRF format
57+
if (!params.root_folder) {
58+
filestr = row.URI.toString()
7459
}
7560
else {
76-
if (!params.root_folder) {
77-
filestr = row.URI.toString()
78-
}
79-
else {
80-
filestr = row.Filename.toString()
81-
}
61+
filestr = row.Filename.toString()
8262
}
8363

8464
meta.mzml_id = file(filestr).name.take(file(filestr).name.lastIndexOf('.'))
@@ -92,72 +72,57 @@ def create_meta_channel(LinkedHashMap row, is_sdrf, enzymes, files, wrapper) {
9272
: filestr)
9373
}
9474

95-
96-
9775
// existence check
9876
if (!file(filestr).exists()) {
9977
exit(1, "ERROR: Please check input file -> File Uri does not exist!\n${filestr}")
10078
}
10179

102-
// for sdrf read from config file, without it, read from params
103-
if (is_sdrf.toString().toLowerCase().contains("false")) {
104-
meta.labelling_type = params.labelling_type
105-
meta.dissociationmethod = params.ms2_fragment_method
106-
meta.fixedmodifications = params.fixed_mods
107-
meta.variablemodifications = params.variable_mods
108-
meta.precursormasstolerance = params.precursor_mass_tolerance
109-
meta.precursormasstoleranceunit = params.precursor_mass_tolerance_unit
110-
meta.fragmentmasstolerance = params.fragment_mass_tolerance
111-
meta.fragmentmasstoleranceunit = params.fragment_mass_tolerance_unit
112-
meta.enzyme = params.enzyme
113-
meta.acquisition_method = params.acquisition_method
80+
// Read metadata from SDRF config file
81+
if (row["Proteomics Data Acquisition Method"].toString().toLowerCase().contains("data-dependent acquisition")) {
82+
meta.acquisition_method = "dda"
83+
}
84+
else if (row["Proteomics Data Acquisition Method"].toString().toLowerCase().contains("data-independent acquisition")) {
85+
meta.acquisition_method = "dia"
11486
}
11587
else {
116-
if (row["Proteomics Data Acquisition Method"].toString().toLowerCase().contains("data-dependent acquisition")) {
117-
meta.acquisition_method = "dda"
118-
}
119-
else if (row["Proteomics Data Acquisition Method"].toString().toLowerCase().contains("data-independent acquisition")) {
120-
meta.acquisition_method = "dia"
121-
}
122-
else {
123-
log.error("Currently DIA and DDA are supported for the pipeline. Check and Fix your SDRF.")
124-
exit(1)
125-
}
88+
log.error("Currently DIA and DDA are supported for the pipeline. Check and Fix your SDRF.")
89+
exit(1)
90+
}
12691

127-
// dissociation method conversion
128-
if (row.DissociationMethod == "COLLISION-INDUCED DISSOCIATION") {
129-
meta.dissociationmethod = "CID"
130-
}
131-
else if (row.DissociationMethod == "HIGHER ENERGY BEAM-TYPE COLLISION-INDUCED DISSOCIATION") {
132-
meta.dissociationmethod = "HCD"
133-
}
134-
else if (row.DissociationMethod == "ELECTRON TRANSFER DISSOCIATION") {
135-
meta.dissociationmethod = "ETD"
136-
}
137-
else if (row.DissociationMethod == "ELECTRON CAPTURE DISSOCIATION") {
138-
meta.dissociationmethod = "ECD"
139-
}
140-
else {
141-
meta.dissociationmethod = row.DissociationMethod
142-
}
92+
// dissociation method conversion
93+
if (row.DissociationMethod == "COLLISION-INDUCED DISSOCIATION") {
94+
meta.dissociationmethod = "CID"
95+
}
96+
else if (row.DissociationMethod == "HIGHER ENERGY BEAM-TYPE COLLISION-INDUCED DISSOCIATION") {
97+
meta.dissociationmethod = "HCD"
98+
}
99+
else if (row.DissociationMethod == "ELECTRON TRANSFER DISSOCIATION") {
100+
meta.dissociationmethod = "ETD"
101+
}
102+
else if (row.DissociationMethod == "ELECTRON CAPTURE DISSOCIATION") {
103+
meta.dissociationmethod = "ECD"
104+
}
105+
else {
106+
meta.dissociationmethod = row.DissociationMethod
107+
}
143108

144-
wrapper.acquisition_method = meta.acquisition_method
145-
meta.labelling_type = row.Label
146-
meta.fixedmodifications = row.FixedModifications
147-
meta.variablemodifications = row.VariableModifications
148-
meta.precursormasstolerance = Double.parseDouble(row.PrecursorMassTolerance)
149-
meta.precursormasstoleranceunit = row.PrecursorMassToleranceUnit
150-
meta.fragmentmasstolerance = Double.parseDouble(row.FragmentMassTolerance)
151-
meta.fragmentmasstoleranceunit = row.FragmentMassToleranceUnit
152-
meta.enzyme = row.Enzyme
153-
154-
enzymes += row.Enzyme
155-
if (enzymes.size() > 1) {
156-
log.error("Currently only one enzyme is supported for the whole experiment. Specified was '${enzymes}'. Check or split your SDRF.")
157-
log.error(filestr)
158-
exit(1)
159-
}
109+
wrapper.acquisition_method = meta.acquisition_method
110+
meta.labelling_type = row.Label
111+
meta.fixedmodifications = row.FixedModifications
112+
meta.variablemodifications = row.VariableModifications
113+
meta.precursormasstolerance = Double.parseDouble(row.PrecursorMassTolerance)
114+
meta.precursormasstoleranceunit = row.PrecursorMassToleranceUnit
115+
meta.fragmentmasstolerance = Double.parseDouble(row.FragmentMassTolerance)
116+
meta.fragmentmasstoleranceunit = row.FragmentMassToleranceUnit
117+
meta.enzyme = row.Enzyme
118+
119+
enzymes += row.Enzyme
120+
if (enzymes.size() > 1) {
121+
log.error("Currently only one enzyme is supported for the whole experiment. Specified was '${enzymes}'. Check or split your SDRF.")
122+
log.error(filestr)
123+
exit(1)
160124
}
125+
161126
// Nothing to determine for dia. Only LFQ allowed there.
162127
if (!meta.acquisition_method.equals("dia")) {
163128
if (wrapper.labelling_type.equals("")) {

0 commit comments

Comments
 (0)