Skip to content
Merged
Show file tree
Hide file tree
Changes from 35 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
6f93d36
Update openms and openmsthirdparty nf-core modules
jonasscheid Jan 23, 2026
8f939b7
Update local modules to use topic channels for versions
jonasscheid Jan 23, 2026
d0b1b82
Remove redundant version parsing and channel creation from subworkflows
jonasscheid Jan 23, 2026
49c0b78
Merge branch 'nf-core:dev' into dev
jonasscheid Feb 5, 2026
c6c4269
Merge branch 'dev' of https://github.com/jonasscheid/mhcquant into dev
jonasscheid Feb 5, 2026
eda222d
Merge remote-tracking branch 'upstream/topics' into search-params-sam…
jonasscheid Feb 6, 2026
ff79328
Add per-sample search parameter support via samplesheet and presets
jonasscheid Feb 6, 2026
100aa29
Use meta-based search parameters in module configs
jonasscheid Feb 6, 2026
c823c07
Group global FDR by search preset instead of merging all samples
jonasscheid Feb 6, 2026
146f77b
Add test profile and samplesheet for search params feature
jonasscheid Feb 6, 2026
15fb6ac
Fix deprecated Nextflow syntax for strict mode compliance
jonasscheid Feb 6, 2026
22e930d
Update CHANGELOG for per-sample search parameters feature
jonasscheid Feb 6, 2026
2efdd68
Add nf-test for search params and use test-datasets samplesheet
jonasscheid Feb 6, 2026
e502ff5
Rename test_search_params to test_search_presets and add nf-test prof…
jonasscheid Feb 6, 2026
570bc7f
Merge remote-tracking branch 'upstream/dev' into search-params-sample…
jonasscheid Feb 6, 2026
bab72f6
Remove redundant emit declarations from version outputs and clean up …
jonasscheid Feb 6, 2026
52b1591
Fix CI failures: prettier formatting, lint ignore, and ionannotator s…
jonasscheid Feb 6, 2026
d6ad64e
Add search_presets as hidden param in nextflow_schema.json to fix lint
jonasscheid Feb 6, 2026
06184be
Document per-sample search parameters and fix stale ch_versions refer…
jonasscheid Feb 6, 2026
11c1926
Align search preset fragment_mass_tolerance with recommended settings
jonasscheid Feb 6, 2026
7985ec6
Remove duplicate comment in mhcquant workflow
jonasscheid Feb 9, 2026
103bcf5
Propagate search params through pipeline with CLI > samplesheet > pre…
jonasscheid Feb 9, 2026
87179c8
Update docs/usage.md with CLI > samplesheet > preset > default priority
jonasscheid Feb 9, 2026
bbf7eb1
Fix lint: move search_param_defaults into resolveSearchParams and ski…
jonasscheid Feb 9, 2026
7a174c4
Fix CLI override detection and add fixed/variable mods as per-sample …
jonasscheid Feb 10, 2026
793e24e
Use workflow.commandLine for CLI override detection instead of hardco…
jonasscheid Feb 10, 2026
9f8ac95
Update snapshots and fix invalid input parameter warning for search_p…
jonasscheid Feb 10, 2026
b8a882b
Fix ion annotator join key mismatch and rename XL preset comment
jonasscheid Feb 11, 2026
83a1fd5
Address PR review: fix mods tokenization, revert fixed_mods default, …
jonasscheid Feb 12, 2026
3217313
Add search_presets back to defaultIgnoreParams to fix nf-schema valid…
jonasscheid Feb 12, 2026
01c2f5a
Add TSV validation to search_presets schema, fix PrecursorMassToleran…
jonasscheid Feb 12, 2026
92f3f4b
Add search_presets.tsv, remove old search_presets.config, simplify in…
jonasscheid Feb 12, 2026
2ae3aa6
Update search_presets test for qe/lumos groups with stable snapshot
jonasscheid Feb 12, 2026
8669e50
Add PrecursorErrorUnit to presets, fix fragment_mass_tolerance to 0.0…
jonasscheid Feb 13, 2026
b813fc4
Capture full peptidoform content in search_presets snapshot
jonasscheid Feb 13, 2026
5d5a595
Address PR review comments: remove defaultIgnoreParams hack, simplify…
jonasscheid Feb 13, 2026
337b1da
Merge branch 'dev' into search-params-samplesheet
jonasscheid Feb 21, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ testing/
testing*
*.pyc
null/
CLAUDE.md
.claude/
1 change: 1 addition & 0 deletions .nf-core.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ lint:
files_unchanged:
- .github/CONTRIBUTING.md
- .vscode/settings.json
pipeline_if_empty_null: false
nf_core_version: 3.5.1
repository_type: pipeline
template:
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### `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)

### `Fixed`

Expand Down
14 changes: 10 additions & 4 deletions assets/schema_input.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"]
},
Expand All @@ -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"]
Expand Down
125 changes: 125 additions & 0 deletions assets/schema_search_presets.json
Original file line number Diff line number Diff line change
@@ -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"
]
}
}
11 changes: 11 additions & 0 deletions assets/search_presets.tsv
Original file line number Diff line number Diff line change
@@ -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)
67 changes: 34 additions & 33 deletions conf/modules.config
Original file line number Diff line number Diff line change
Expand Up @@ -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}",
Expand Down Expand Up @@ -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,
Expand All @@ -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
]
Expand All @@ -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,
Expand Down Expand Up @@ -348,23 +348,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,
Expand Down Expand Up @@ -395,15 +395,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
]
Expand Down Expand Up @@ -526,11 +527,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,
Expand Down
29 changes: 29 additions & 0 deletions conf/test_search_presets.config
Original file line number Diff line number Diff line change
@@ -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,<docker/singularity> --outdir <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'
}
Loading
Loading