diff --git a/ms2rescore/exceptions.py b/ms2rescore/exceptions.py index ba5492a..68b1b43 100644 --- a/ms2rescore/exceptions.py +++ b/ms2rescore/exceptions.py @@ -41,3 +41,9 @@ class RescoringError(MS2RescoreError): """Error while rescoring PSMs.""" pass + + +class ParseSpectrumError(MS2RescoreError): + """Error while rescoring PSMs.""" + + pass diff --git a/ms2rescore/package_data/config_default.json b/ms2rescore/package_data/config_default.json index 733ea70..126fde8 100644 --- a/ms2rescore/package_data/config_default.json +++ b/ms2rescore/package_data/config_default.json @@ -12,6 +12,7 @@ }, "maxquant": {} }, + "psm_generator": {}, "rescoring_engine": { "mokapot": { "train_fdr": 0.01, diff --git a/ms2rescore/package_data/config_schema.json b/ms2rescore/package_data/config_schema.json index ab77f3b..4047171 100644 --- a/ms2rescore/package_data/config_schema.json +++ b/ms2rescore/package_data/config_schema.json @@ -62,6 +62,18 @@ "mokapot": {} } }, + "psm_generator": { + "description": "PSM generator and their configuration.", + "type": "object", + "minProperties": 0, + "maxProperties": 1, + "patternProperties": { + ".*": { "$ref": "#/definitions/psm_generator" }, + "mumble": { + "$ref": "#/definitions/mumble" + } + } + }, "config_file": { "description": "Path to configuration file", "oneOf": [{ "type": "string" }, { "type": "null" }] @@ -179,6 +191,7 @@ "type": "boolean", "default": false } + } } }, @@ -193,6 +206,11 @@ "type": "object", "additionalProperties": true }, + "psm_generator": { + "description": "Additional PSM feature generator configuration", + "type": "object", + "additionalProperties": true + }, "basic": { "$ref": "#/definitions/feature_generator", "description": "Basic feature generator configuration", @@ -273,6 +291,30 @@ } } }, + "mumble": { + "$ref": "#/definitions/psm_generator", + "description": "Mumble PSM generator configuration using Mubmle", + "type": "object", + "additionalProperties": true, + "properties": { + "aa_combinations": { + "description": "Additional amino acid combinations to consider as mass shift", + "type": "integer", + "default": 0 + }, + "fasta_file": { + "description": "Maximum number of modifications per peptide", + "oneOf": [{ "type": "string" }, { "type": "null" }], + "default": false + }, + "mass_error": { + "description": "mass error in Da", + "type": "number", + "default": 0.2 + } + } + }, + "mokapot": { "$ref": "#/definitions/rescoring_engine", "description": "Mokapot rescoring engine configuration. Additional properties are passed to the Mokapot brew function.", diff --git a/ms2rescore/parse_psms.py b/ms2rescore/parse_psms.py index 6a3c606..ae28b51 100644 --- a/ms2rescore/parse_psms.py +++ b/ms2rescore/parse_psms.py @@ -5,6 +5,7 @@ import numpy as np import psm_utils.io from psm_utils import PSMList +from mumble import PSMHandler from ms2rescore.exceptions import MS2RescoreConfigurationError @@ -90,6 +91,19 @@ def parse_psms(config: Dict, psm_list: Union[PSMList, None]) -> PSMList: new_ids = [_match_psm_ids(old_id, pattern) for old_id in psm_list["spectrum_id"]] psm_list["spectrum_id"] = new_ids + # Addition of Modifications for mass shifts in the PSMs with Mumble + if "mumble" in config["psm_generator"]: + logger.debug("Applying modifications for mass shifts using Mumble...") + mumble_config = config["psm_generator"]["mumble"] + psm_handler = PSMHandler( + **mumble_config, # TODO how do we store config for mumble? + ) + psm_list = psm_handler.add_modified_psms( + psm_list, generate_modified_decoys=True, keep_original=True + ) + if mumble_config["output_file"]: + psm_handler.write_modified_psm_list(psm_list, mumble_config["output_file"]) + return psm_list diff --git a/pyproject.toml b/pyproject.toml index f57ad80..7c1b0a9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -50,6 +50,7 @@ dependencies = [ "pyteomics>=4.7.2", "rich>=12", "tomli>=2; python_version < '3.11'", + "mumble" ] [project.optional-dependencies]