Reading MS Annika Result Files
from pyXLMS import __version__
print(f"Installed pyXLMS version: {__version__}")
Installed pyXLMS version: 1.1.2
from pyXLMS import parser
from pyXLMS import transform
All functionality to parse crosslink-spectrum-matches (CSMs) and crosslinks (XLs) from MS Annika result files is available via the parser
submodule. We also import the transform
submodule to show some summary statistics of the read files.
Reading MS Annika Result Files via parser.read()
parser_result = parser.read(
"../../data/ms_annika/XLpeplib_Beveridge_QEx-HFX_DSS_R1_CSMs.txt",
engine="MS Annika",
crosslinker="DSS",
)
Reading MS Annika CSMs...: 100%|βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ| 826/826 [00:00<00:00, 7639.53it/s]
We can read any MS Annika result file using the parser.read()
method and setting engine="MS Annika"
. The method also requires us to specify the used crosslinker, in this case DSS was used (crosslinker="DSS"
). You can read the documentation for the parser.read()
method here: docs.
for k, v in parser_result.items():
print(f"{k}: {type(v) if isinstance(v, list) else v}")
data_type: parser_result
completeness: partial
search_engine: MS Annika
crosslink-spectrum-matches: <class 'list'>
crosslinks: None
The parser.read()
method returns a dictionary with a set of specified keys and their values. We refer to this dictionary as a parser_result
object. All parser.read*
methods return such a parser_result
object, you can read more about that here: docs, and here: data types specification.
As you can see from the parser_result
the MS Annika result file contained CSMs. We would be able to access those via parser_result["crosslink-spectrum-matches"]
.
_ = transform.summary(parser_result)
Number of CSMs: 826.0
Number of unique CSMs: 826.0
Number of intra CSMs: 803.0
Number of inter CSMs: 23.0
Number of target-target CSMs: 786.0
Number of target-decoy CSMs: 39.0
Number of decoy-decoy CSMs: 1.0
Minimum CSM score: 1.11
Maximum CSM score: 452.99
With the transform.summary()
method we can also print out some summary statistics about our read CSMs. You can read more about the method here: docs.
sample_csm = parser_result["crosslink-spectrum-matches"][0]
for k, v in sample_csm.items():
print(f"{k}: {v}")
data_type: crosslink-spectrum-match
completeness: full
alpha_peptide: GQKNSR
alpha_modifications: {3: ('DSS', 138.06808)}
alpha_peptide_crosslink_position: 3
alpha_proteins: ['Cas9']
alpha_proteins_crosslink_positions: [779]
alpha_proteins_peptide_positions: [777]
alpha_score: 119.83
alpha_decoy: False
beta_peptide: GQKNSR
beta_modifications: {3: ('DSS', 138.06808)}
beta_peptide_crosslink_position: 3
beta_proteins: ['Cas9']
beta_proteins_crosslink_positions: [779]
beta_proteins_peptide_positions: [777]
beta_score: 119.83
beta_decoy: False
crosslink_type: intra
score: 119.83
spectrum_file: XLpeplib_Beveridge_QEx-HFX_DSS_R1.raw
scan_nr: 2257
charge: 3
retention_time: 733.188
ion_mobility: 0.0
additional_information: None
Here is an example CSM, you can learn more about the specific attributes and their values here: docs, and here: data types specification.
parser_result = parser.read(
"../../data/ms_annika/XLpeplib_Beveridge_QEx-HFX_DSS_R1_Crosslinks.xlsx",
engine="MS Annika",
crosslinker="DSS",
)
Reading MS Annika crosslinks...: 100%|βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ| 300/300 [00:00<00:00, 8801.27it/s]
We can also as easily read a crosslink result file, notice how this time we also read a Microsoft Excel file instead of a txt file and donβt even have to change anything. This is because when a filename is given, the parser will automatically detect the corresponding extension and use the correct sub-method. This behaviour is controlled by the format
parameter in the MS Annika parserΒ . More about that laterβ¦
_ = transform.summary(parser_result)
Number of crosslinks: 300.0
Number of unique crosslinks by peptide: 300.0
Number of unique crosslinks by protein: 298.0
Number of intra crosslinks: 279.0
Number of inter crosslinks: 21.0
Number of target-target crosslinks: 265.0
Number of target-decoy crosslinks: 0.0
Number of decoy-decoy crosslinks: 35.0
Minimum crosslink score: 1.11
Maximum crosslink score: 452.99
Similarly, with the transform.summary()
method we can also print out some summary statistics about our read crosslinks.
sample_crosslink = parser_result["crosslinks"][0]
for k, v in sample_crosslink.items():
print(f"{k}: {v}")
data_type: crosslink
completeness: full
alpha_peptide: GQKNSR
alpha_peptide_crosslink_position: 3
alpha_proteins: ['Cas9']
alpha_proteins_crosslink_positions: [779]
alpha_decoy: False
beta_peptide: GQKNSR
beta_peptide_crosslink_position: 3
beta_proteins: ['Cas9']
beta_proteins_crosslink_positions: [779]
beta_decoy: False
crosslink_type: intra
score: 119.83
additional_information: None
Here is an example crosslink, you can learn more about the specific attributes and their values here: docs, and here: data types specification.
parser_result = parser.read(
[
"../../data/ms_annika/XLpeplib_Beveridge_QEx-HFX_DSS_R1_CSMs.txt",
"../../data/ms_annika/XLpeplib_Beveridge_QEx-HFX_DSS_R1_Crosslinks.xlsx",
],
engine="MS Annika",
crosslinker="DSS",
)
Reading MS Annika CSMs...: 100%|βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ| 826/826 [00:00<00:00, 6911.35it/s]
Reading MS Annika crosslinks...: 100%|ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ| 300/300 [00:00<00:00, 18167.65it/s]
Itβs also possible to read multiple files into one parser_result
, this for example makes sense if you have crosslinks and crosslink-spectrum-matches from the same run.
_ = transform.summary(parser_result)
Number of CSMs: 826.0
Number of unique CSMs: 826.0
Number of intra CSMs: 803.0
Number of inter CSMs: 23.0
Number of target-target CSMs: 786.0
Number of target-decoy CSMs: 39.0
Number of decoy-decoy CSMs: 1.0
Minimum CSM score: 1.11
Maximum CSM score: 452.99
Number of crosslinks: 300.0
Number of unique crosslinks by peptide: 300.0
Number of unique crosslinks by protein: 298.0
Number of intra crosslinks: 279.0
Number of inter crosslinks: 21.0
Number of target-target crosslinks: 265.0
Number of target-decoy crosslinks: 0.0
Number of decoy-decoy crosslinks: 35.0
Minimum crosslink score: 1.11
Maximum crosslink score: 452.99
If the parser_result
contains both crosslinks and CSMs, summary statistics for both will be calculated by transform.summary()
.
parser_result = parser.read(
"../../data/ms_annika/XLpeplib_Beveridge_QEx-HFX_DSS_R1_CSMs.txt",
engine="MS Annika",
crosslinker="DSS",
parse_modifications=False,
)
Reading MS Annika CSMs...: 100%|ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ| 826/826 [00:00<00:00, 10655.56it/s]
We can also tell the parser to not parse modifications via parse_modifications=False
, this might be useful if you donβt care about post-translational-modifications, or if you have unknown modifications in your results that you would have to manually specify - and you donβt want to do that.
In case you want to parse modifications but have unknown modifications in your results, you have to set them via the modifications
parameter that can be passed via **kwargs
to parser.read_msannika()
. More about that laterβ¦
sample_csm = parser_result["crosslink-spectrum-matches"][0]
for k, v in sample_csm.items():
print(f"{k}: {v}")
data_type: crosslink-spectrum-match
completeness: partial
alpha_peptide: GQKNSR
alpha_modifications: None
alpha_peptide_crosslink_position: 3
alpha_proteins: ['Cas9']
alpha_proteins_crosslink_positions: [779]
alpha_proteins_peptide_positions: [777]
alpha_score: 119.83
alpha_decoy: False
beta_peptide: GQKNSR
beta_modifications: None
beta_peptide_crosslink_position: 3
beta_proteins: ['Cas9']
beta_proteins_crosslink_positions: [779]
beta_proteins_peptide_positions: [777]
beta_score: 119.83
beta_decoy: False
crosslink_type: intra
score: 119.83
spectrum_file: XLpeplib_Beveridge_QEx-HFX_DSS_R1.raw
scan_nr: 2257
charge: 3
retention_time: 733.188
ion_mobility: 0.0
additional_information: None
Notice that this time the fields alpha_modifications
and beta_modifications
are empty (None
) for our sample CSM.
parser_result = parser.read(
"../../data/ms_annika/XLpeplib_Beveridge_QEx-HFX_DSS_R1.pdResult",
engine="MS Annika",
crosslinker="DSS",
)
Reading MS Annika CSMs...: 100%|βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ| 826/826 [00:00<00:00, 6478.03it/s]
Reading MS Annika crosslinks...: 100%|ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ| 300/300 [00:00<00:00, 10331.48it/s]
Last but not least you can also directly read a pdResult
from Proteome Discoverer which will automatically read all CSMs and crosslinks detected with MS Annika.
Reading MS Annika Result Files via parser.read_msannika()
parser_result = parser.read_msannika(
"../../data/ms_annika/XLpeplib_Beveridge_QEx-HFX_DSS_R1_CSMs.txt"
)
Reading MS Annika CSMs...: 100%|βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ| 826/826 [00:00<00:00, 5919.43it/s]
We can also read any MS Annika result file using the parser.read_msannika()
method which allows a more nuanced control over reading MS Annika result files - even though theoretically everything can be done with the parser.read()
function as well. You can read the documentation for the parser.read_msannika()
method here: docs.
_ = transform.summary(parser_result)
Number of CSMs: 826.0
Number of unique CSMs: 826.0
Number of intra CSMs: 803.0
Number of inter CSMs: 23.0
Number of target-target CSMs: 786.0
Number of target-decoy CSMs: 39.0
Number of decoy-decoy CSMs: 1.0
Minimum CSM score: 1.11
Maximum CSM score: 452.99
from pyXLMS.constants import MODIFICATIONS
MODIFICATIONS
{'Carbamidomethyl': 57.021464,
'Oxidation': 15.994915,
'Phospho': 79.966331,
'Acetyl': 42.010565,
'BS3': 138.06808,
'DSS': 138.06808,
'DSSO': 158.00376,
'DSBU': 196.08479231,
'ADH': 138.09054635,
'DSBSO': 308.03883,
'PhoX': 209.97181}
By default the MS Annika parser considers all modifications that are in constants.MODIFICATIONS
as shown above for pyXLMS version 1.1.1 - a full list of default modifications is given here: docs.
my_mods = dict(MODIFICATIONS)
my_mods["Methyl"] = 14.01565
my_mods
{'Carbamidomethyl': 57.021464,
'Oxidation': 15.994915,
'Phospho': 79.966331,
'Acetyl': 42.010565,
'BS3': 138.06808,
'DSS': 138.06808,
'DSSO': 158.00376,
'DSBU': 196.08479231,
'ADH': 138.09054635,
'DSBSO': 308.03883,
'PhoX': 209.97181,
'Methyl': 14.01565}
If you have any additional modifications in your result file(s) the parser needs to know about them, which is done via the modifications
parameter that allows for passing a custom dictionary of modifications. It is usually a good idea to base this custom dictionary on constants.MODIFICATIONS
and add your modifications after, as shown above for methylation.
parser_result = parser.read_msannika(
"../../data/ms_annika/XLpeplib_Beveridge_QEx-HFX_DSS_R1_CSMs.txt",
modifications=my_mods,
)
Reading MS Annika CSMs...: 100%|βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ| 826/826 [00:00<00:00, 8056.97it/s]
You can then pass the full list of expected modifications my_mods
via the modifications
parameter.
_ = transform.summary(parser_result)
Number of CSMs: 826.0
Number of unique CSMs: 826.0
Number of intra CSMs: 803.0
Number of inter CSMs: 23.0
Number of target-target CSMs: 786.0
Number of target-decoy CSMs: 39.0
Number of decoy-decoy CSMs: 1.0
Minimum CSM score: 1.11
Maximum CSM score: 452.99
with open(
"../../data/ms_annika/XLpeplib_Beveridge_QEx-HFX_DSS_R1_Crosslinks.txt", "r"
) as f:
parser_result = parser.read_msannika(f, format="txt")
f.close()
Reading MS Annika crosslinks...: 100%|ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ| 300/300 [00:00<00:00, 24124.14it/s]
The format
parameter is necessary when files are directly read from a file-stream because the format then cannot be automatically be inferred, such as in the case above. Please do note that reading of pdResult files from a file-stream is not supported. The format
parameter accepts the following values: "auto"
, "csv"
, "txt"
, "tsv"
, "xlsx"
, "pdresult"
.
_ = transform.summary(parser_result)
Number of crosslinks: 300.0
Number of unique crosslinks by peptide: 300.0
Number of unique crosslinks by protein: 298.0
Number of intra crosslinks: 279.0
Number of inter crosslinks: 21.0
Number of target-target crosslinks: 265.0
Number of target-decoy crosslinks: 0.0
Number of decoy-decoy crosslinks: 35.0
Minimum crosslink score: 1.11
Maximum crosslink score: 452.99
There are several other parameters that can be set, you can read more about them here: docs.