CoreMS 4.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (171) hide show
  1. corems/__init__.py +63 -0
  2. corems/chroma_peak/__init__.py +0 -0
  3. corems/chroma_peak/calc/ChromaPeakCalc.py +480 -0
  4. corems/chroma_peak/calc/__init__.py +0 -0
  5. corems/chroma_peak/calc/subset.py +196 -0
  6. corems/chroma_peak/factory/__init__.py +0 -0
  7. corems/chroma_peak/factory/chroma_peak_classes.py +1178 -0
  8. corems/encapsulation/__init__.py +0 -0
  9. corems/encapsulation/constant.py +1283 -0
  10. corems/encapsulation/factory/__init__.py +0 -0
  11. corems/encapsulation/factory/parameters.py +392 -0
  12. corems/encapsulation/factory/processingSetting.py +1244 -0
  13. corems/encapsulation/input/__init__.py +0 -0
  14. corems/encapsulation/input/parameter_from_json.py +579 -0
  15. corems/encapsulation/output/__init__.py +0 -0
  16. corems/encapsulation/output/parameter_to_dict.py +142 -0
  17. corems/encapsulation/output/parameter_to_json.py +332 -0
  18. corems/mass_spectra/__init__.py +0 -0
  19. corems/mass_spectra/calc/GC_Calc.py +84 -0
  20. corems/mass_spectra/calc/GC_Deconvolution.py +558 -0
  21. corems/mass_spectra/calc/GC_RI_Calibration.py +44 -0
  22. corems/mass_spectra/calc/MZSearch.py +249 -0
  23. corems/mass_spectra/calc/SignalProcessing.py +656 -0
  24. corems/mass_spectra/calc/__init__.py +0 -0
  25. corems/mass_spectra/calc/lc_calc.py +5790 -0
  26. corems/mass_spectra/calc/lc_calc_operations.py +1127 -0
  27. corems/mass_spectra/factory/GC_Class.py +791 -0
  28. corems/mass_spectra/factory/__init__.py +0 -0
  29. corems/mass_spectra/factory/chromat_data.py +51 -0
  30. corems/mass_spectra/factory/lc_class.py +2721 -0
  31. corems/mass_spectra/input/__init__.py +0 -0
  32. corems/mass_spectra/input/andiNetCDF.py +200 -0
  33. corems/mass_spectra/input/boosterHDF5.py +216 -0
  34. corems/mass_spectra/input/brukerSolarix.py +153 -0
  35. corems/mass_spectra/input/brukerSolarix_utils.py +73 -0
  36. corems/mass_spectra/input/corems_hdf5.py +1710 -0
  37. corems/mass_spectra/input/massList.py +133 -0
  38. corems/mass_spectra/input/mzml.py +668 -0
  39. corems/mass_spectra/input/parserbase.py +239 -0
  40. corems/mass_spectra/input/rawFileReader.py +1839 -0
  41. corems/mass_spectra/output/__init__.py +0 -0
  42. corems/mass_spectra/output/export.py +2800 -0
  43. corems/mass_spectrum/__init__.py +0 -0
  44. corems/mass_spectrum/calc/AutoRecalibration.py +237 -0
  45. corems/mass_spectrum/calc/Calibration.py +602 -0
  46. corems/mass_spectrum/calc/CalibrationCalc.py +253 -0
  47. corems/mass_spectrum/calc/KendrickGroup.py +239 -0
  48. corems/mass_spectrum/calc/MassErrorPrediction.py +436 -0
  49. corems/mass_spectrum/calc/MassSpectrumCalc.py +303 -0
  50. corems/mass_spectrum/calc/MeanResolvingPowerFilter.py +212 -0
  51. corems/mass_spectrum/calc/NoiseCalc.py +371 -0
  52. corems/mass_spectrum/calc/NoiseCalc_Bayes.py +93 -0
  53. corems/mass_spectrum/calc/PeakPicking.py +994 -0
  54. corems/mass_spectrum/calc/__init__.py +0 -0
  55. corems/mass_spectrum/factory/MassSpectrumClasses.py +1753 -0
  56. corems/mass_spectrum/factory/__init__.py +0 -0
  57. corems/mass_spectrum/input/__init__.py +0 -0
  58. corems/mass_spectrum/input/baseClass.py +531 -0
  59. corems/mass_spectrum/input/boosterHDF5.py +161 -0
  60. corems/mass_spectrum/input/coremsHDF5.py +475 -0
  61. corems/mass_spectrum/input/massList.py +402 -0
  62. corems/mass_spectrum/input/numpyArray.py +133 -0
  63. corems/mass_spectrum/output/__init__.py +0 -0
  64. corems/mass_spectrum/output/export.py +841 -0
  65. corems/molecular_formula/__init__.py +0 -0
  66. corems/molecular_formula/calc/MolecularFormulaCalc.py +885 -0
  67. corems/molecular_formula/calc/__init__.py +0 -0
  68. corems/molecular_formula/factory/MolecularFormulaFactory.py +895 -0
  69. corems/molecular_formula/factory/__init__.py +0 -0
  70. corems/molecular_formula/input/__init__.py +0 -0
  71. corems/molecular_formula/input/masslist_ref.py +355 -0
  72. corems/molecular_id/__init__.py +0 -0
  73. corems/molecular_id/calc/ClusterFilter.py +251 -0
  74. corems/molecular_id/calc/MolecularFilter.py +122 -0
  75. corems/molecular_id/calc/SpectralSimilarity.py +632 -0
  76. corems/molecular_id/calc/__init__.py +0 -0
  77. corems/molecular_id/calc/math_distance.py +1637 -0
  78. corems/molecular_id/data/FAMES_REF.msp +980 -0
  79. corems/molecular_id/data/PNNLMetV20191015.msp +157267 -0
  80. corems/molecular_id/factory/EI_SQL.py +650 -0
  81. corems/molecular_id/factory/MolecularLookupTable.py +914 -0
  82. corems/molecular_id/factory/__init__.py +0 -0
  83. corems/molecular_id/factory/classification.py +884 -0
  84. corems/molecular_id/factory/lipid_molecular_metadata.py +50 -0
  85. corems/molecular_id/factory/molecularSQL.py +827 -0
  86. corems/molecular_id/factory/spectrum_search_results.py +119 -0
  87. corems/molecular_id/input/__init__.py +0 -0
  88. corems/molecular_id/input/nistMSI.py +148 -0
  89. corems/molecular_id/search/__init__.py +0 -0
  90. corems/molecular_id/search/compoundSearch.py +214 -0
  91. corems/molecular_id/search/database_interfaces.py +1527 -0
  92. corems/molecular_id/search/findOxygenPeaks.py +330 -0
  93. corems/molecular_id/search/lcms_spectral_search.py +348 -0
  94. corems/molecular_id/search/molecularFormulaSearch.py +1117 -0
  95. corems/molecular_id/search/priorityAssignment.py +723 -0
  96. corems/ms_peak/__init__.py +0 -0
  97. corems/ms_peak/calc/MSPeakCalc.py +1010 -0
  98. corems/ms_peak/calc/__init__.py +0 -0
  99. corems/ms_peak/factory/MSPeakClasses.py +542 -0
  100. corems/ms_peak/factory/__init__.py +0 -0
  101. corems/transient/__init__.py +0 -0
  102. corems/transient/calc/TransientCalc.py +362 -0
  103. corems/transient/calc/__init__.py +0 -0
  104. corems/transient/factory/TransientClasses.py +457 -0
  105. corems/transient/factory/__init__.py +0 -0
  106. corems/transient/input/__init__.py +0 -0
  107. corems/transient/input/brukerSolarix.py +461 -0
  108. corems/transient/input/midasDatFile.py +172 -0
  109. corems-4.0.0.dist-info/METADATA +475 -0
  110. corems-4.0.0.dist-info/RECORD +171 -0
  111. corems-4.0.0.dist-info/WHEEL +5 -0
  112. corems-4.0.0.dist-info/licenses/LICENSE +22 -0
  113. corems-4.0.0.dist-info/top_level.txt +4 -0
  114. examples/archive/scripts/CoreMS_tutorial.py +94 -0
  115. examples/archive/scripts/DI HR-MS Halogens Bruker.py +196 -0
  116. examples/archive/scripts/DI HR-MS MassList.py +385 -0
  117. examples/archive/scripts/GC-MS MetabRef.py +213 -0
  118. examples/archive/scripts/GC-MS NetCDF.py +217 -0
  119. examples/archive/scripts/HR-MS Thermo Raw 21T.py +136 -0
  120. examples/archive/scripts/LC-ICPMS_metal_peaks.py +297 -0
  121. examples/archive/scripts/LCMS-Thermo.py +460 -0
  122. examples/archive/scripts/LCMS_isotopes.py +283 -0
  123. examples/archive/scripts/MSParams_example.py +21 -0
  124. examples/archive/scripts/Molecular Formula Data Aggreation.py +84 -0
  125. examples/archive/scripts/Single Mz Search.py +69 -0
  126. examples/test_notebooks.py +145 -0
  127. ext_lib/ChemstationMSFileReader.dll +0 -0
  128. ext_lib/ChemstationMSFileReader.xml +126 -0
  129. ext_lib/RawFileReaderLicense.doc +0 -0
  130. ext_lib/ThermoFisher.CommonCore.BackgroundSubtraction.dll +0 -0
  131. ext_lib/ThermoFisher.CommonCore.BackgroundSubtraction.xml +2307 -0
  132. ext_lib/ThermoFisher.CommonCore.Data.dll +0 -0
  133. ext_lib/ThermoFisher.CommonCore.Data.xml +28974 -0
  134. ext_lib/ThermoFisher.CommonCore.MassPrecisionEstimator.dll +0 -0
  135. ext_lib/ThermoFisher.CommonCore.MassPrecisionEstimator.xml +241 -0
  136. ext_lib/ThermoFisher.CommonCore.RawFileReader.dll +0 -0
  137. ext_lib/ThermoFisher.CommonCore.RawFileReader.xml +31174 -0
  138. ext_lib/__init__.py +0 -0
  139. ext_lib/dotnet/OpenMcdf.Extensions.dll +0 -0
  140. ext_lib/dotnet/OpenMcdf.dll +0 -0
  141. ext_lib/dotnet/OpenMcdf.xml +1154 -0
  142. ext_lib/dotnet/System.IO.FileSystem.AccessControl.dll +0 -0
  143. ext_lib/dotnet/System.IO.FileSystem.AccessControl.xml +506 -0
  144. ext_lib/dotnet/System.Security.AccessControl.dll +0 -0
  145. ext_lib/dotnet/System.Security.AccessControl.xml +2043 -0
  146. ext_lib/dotnet/System.Security.Principal.Windows.dll +0 -0
  147. ext_lib/dotnet/System.Security.Principal.Windows.xml +1011 -0
  148. ext_lib/dotnet/ThermoFisher.CommonCore.BackgroundSubtraction.dll +0 -0
  149. ext_lib/dotnet/ThermoFisher.CommonCore.BackgroundSubtraction.xml +2307 -0
  150. ext_lib/dotnet/ThermoFisher.CommonCore.Data.dll +0 -0
  151. ext_lib/dotnet/ThermoFisher.CommonCore.Data.xml +29148 -0
  152. ext_lib/dotnet/ThermoFisher.CommonCore.MassPrecisionEstimator.dll +0 -0
  153. ext_lib/dotnet/ThermoFisher.CommonCore.MassPrecisionEstimator.xml +241 -0
  154. ext_lib/dotnet/ThermoFisher.CommonCore.RawFileReader.dll +0 -0
  155. ext_lib/dotnet/ThermoFisher.CommonCore.RawFileReader.xml +31492 -0
  156. ext_lib/version +18 -0
  157. support_code/atom_parsers/AtomsDescription.py +359 -0
  158. support_code/atom_parsers/CreateAtomsDescription.py +56 -0
  159. support_code/nmdc/filefinder.py +90 -0
  160. support_code/nmdc/lipidomics/lipidomics_workflow.py +748 -0
  161. support_code/nmdc/lipidomics/manifest_examples.py +49 -0
  162. support_code/nmdc/metabolomics/gcms_workflow.py +158 -0
  163. support_code/nmdc/metabolomics/lcms_metabolomics_targeted_search.py +59 -0
  164. support_code/nmdc/metabolomics/lcms_metabolomics_workflow.py +248 -0
  165. support_code/nmdc/metabolomics/metabolomics_collection.py +628 -0
  166. support_code/nmdc/metadata/dms_api.py +42 -0
  167. support_code/nmdc/nom/archived_scripts/nmdc_metadata_gen.py +288 -0
  168. support_code/nmdc/nom/archived_scripts/nom_grow_workflow.py +209 -0
  169. support_code/nmdc/nom/nom_workflow.py +312 -0
  170. support_code/windows_only_importers/BrukerCompassXtract.py +180 -0
  171. support_code/windows_only_importers/ThermoMSFileReader.py +405 -0
File without changes
File without changes
@@ -0,0 +1,355 @@
1
+ __author__ = "Yuri E. Corilo"
2
+ __date__ = "Oct 24, 2019"
3
+
4
+ import json
5
+ import re
6
+ import sys
7
+ from pathlib import Path
8
+ from typing import Dict, List
9
+
10
+ import pandas as pd
11
+
12
+ from corems.encapsulation.constant import Atoms, Labels
13
+ from corems.molecular_formula.factory.MolecularFormulaFactory import (
14
+ LCMSLibRefMolecularFormula,
15
+ MolecularFormula,
16
+ )
17
+
18
+
19
+ class MolecularFormulaLinkProxy:
20
+ """Proxy class for MolecularFormulaLink to be used in the molecular formula ref file import
21
+
22
+ Parameters
23
+ ----------
24
+ molecular_formula : MolecularFormula | LCMSLibRefMolecularFormula
25
+ corems MolecularFormula or LCMSLibRefMolecularFormula object
26
+ mz : float
27
+ target m/z
28
+
29
+ Attributes
30
+ ----------
31
+ C : int
32
+ number of carbon atoms
33
+ H : int
34
+ number of hydrogen atoms
35
+ H_C : float
36
+ ratio of hydrogen to carbon atoms
37
+ class_label : str
38
+ molecular formula class label
39
+ mz_calc : float
40
+ calculated m/z
41
+ dbe : int
42
+ double bond equivalent
43
+ formula_dict : dict
44
+ molecular formula dictionary
45
+
46
+ Methods
47
+ -------
48
+ * to_dict().
49
+ return molecular formula dictionary
50
+
51
+ """
52
+
53
+ def __init__(self, molecular_formula, mz):
54
+ self.C = molecular_formula.get("C")
55
+ self.H = molecular_formula.get("H")
56
+ self.H_C = molecular_formula.get("H") / molecular_formula.get("C")
57
+ self.class_label = json.dumps(molecular_formula.class_dict)
58
+ self.mz_calc = float(mz)
59
+ self.dbe = molecular_formula.dbe
60
+ self.formula_dict = molecular_formula.to_dict()
61
+
62
+ def to_dict(self):
63
+ return self.formula_dict
64
+
65
+
66
+ class ImportMassListRef: # Thread
67
+ """Import Mass List from Reference File
68
+
69
+ Parameters
70
+ ----------
71
+ ref_file_location : str
72
+ path to the reference file
73
+
74
+ Attributes
75
+ ----------
76
+ ref_file_location : str
77
+ path to the reference file
78
+
79
+ Methods
80
+ -------
81
+ * molecular_formula_ref(mz, molecular_formula).
82
+ Return MolecularFormulaLinkProxy object
83
+ * from_lcms_lib_file(ion_charge, ion_types).
84
+ Return Dict[standard_name, Dict[m/z, List[MolecularFormula]]] from LCMS library reference file
85
+ * from_bruker_ref_file().
86
+ Return List[MolecularFormula] from Bruker reference file
87
+ * from_corems_ref_file(delimiter).
88
+ Return List[MolecularFormula] from CoreMS reference file
89
+ * split(delimiters, string, maxsplit).
90
+ Splits a string using a list of delimiters.
91
+ * mformula_s_to_dict(s_mformulatring, iontype).
92
+ Converts a molecular formula string to a dict
93
+ """
94
+
95
+ def __init__(self, ref_file_location):
96
+ # Thread.__init__(self)
97
+
98
+ self.ref_file_location = Path(ref_file_location)
99
+
100
+ if not self.ref_file_location.exists():
101
+ tb = sys.exc_info()[2]
102
+ raise FileNotFoundError(ref_file_location).with_traceback(tb)
103
+
104
+ def molecular_formula_ref(self, mz, molecular_formula):
105
+ """Instantiate a MolecularFormulaLinkProxy object
106
+
107
+ Parameters
108
+ ----------
109
+ mz : float
110
+ target m/z
111
+ molecular_formula : MolecularFormula | LCMSLibRefMolecularFormula
112
+ corems MolecularFormula or LCMSLibRefMolecularFormula object
113
+
114
+ Returns
115
+ -------
116
+ MolecularFormulaLinkProxy
117
+ MolecularFormulaLinkProxy object
118
+ """
119
+ return MolecularFormulaLinkProxy(molecular_formula, mz)
120
+
121
+ def from_lcms_lib_file(
122
+ self, ion_charge: float, ion_types: List[str]
123
+ ) -> Dict[str, Dict[float, List[LCMSLibRefMolecularFormula]]]:
124
+ """Create a dictionary of LCMSLibRefMolecularFormula objects from LCMS library reference file
125
+
126
+ Parameters
127
+ ----------
128
+ ion_charge : float
129
+ ion charge
130
+ ion_types : List[str]
131
+ list of ion types
132
+
133
+ Returns
134
+ -------
135
+ Dict
136
+ Dict[standard_name, Dict[m/z, List[MolecularFormula]]] from LCMS library reference file. m/z is the target m/z; standard_name is the name of the molecular standard mix; MolecularFormula is the corems molecular formula class
137
+ """
138
+
139
+ data = {}
140
+
141
+ with open(self.ref_file_location) as ref_f:
142
+ df = pd.read_csv(ref_f, header=0, encoding="unicode_escape")
143
+
144
+ for index, row in df.iterrows():
145
+ formula_s = row["Neutral Formula"]
146
+ formula_dict = self.mformula_s_to_dict(formula_s, Labels.neutral)
147
+ name = row["Compound Name"]
148
+ kegg_id = row["KEGG ID"]
149
+ standard_name = row["NEW MIX"]
150
+ cas = row["KEGG ID"]
151
+ # print(row["Neutral Formula"], formula_dict)
152
+ molf_formula = LCMSLibRefMolecularFormula(
153
+ formula_dict,
154
+ ion_charge,
155
+ Labels.neutral,
156
+ name=name,
157
+ kegg_id=kegg_id,
158
+ cas=cas,
159
+ )
160
+ # if round(molf_formula.mz_calc, 4) != round(row['Mass Adduct -H'],4):
161
+ # print(formula_s)
162
+ # print(round(molf_formula.mz_calc, 4) , round(row['Mass Adduct -H'],4))
163
+
164
+ if standard_name in data.keys():
165
+ # TODO change it to target ion types and add ion type in the data structure
166
+ mz_calc = molf_formula.protonated_mz
167
+
168
+ if mz_calc in data.get(standard_name).keys():
169
+ data.get(standard_name).get(mz_calc).append(molf_formula)
170
+
171
+ else:
172
+ data[standard_name][mz_calc] = [molf_formula]
173
+ else:
174
+ data[standard_name] = {molf_formula.mz_calc: [molf_formula]}
175
+ # print(formula_s, formula_dict)
176
+ # if molf_formula.ion_type != 'de-protonated':
177
+ # print( 'ha', molf_formula.ion_type )
178
+ # print(formula_dict)
179
+ # print(row['c1'], row['c2'])
180
+
181
+ return data
182
+
183
+ def from_bruker_ref_file(self) -> List[MolecularFormula]:
184
+ """Create a list of MolecularFormula objects from Bruker reference file
185
+
186
+ Returns
187
+ -------
188
+ List[MolecularFormula]
189
+ List of MolecularFormula objects from Bruker reference file
190
+ """
191
+
192
+ import csv
193
+
194
+ list_mf_obj = []
195
+
196
+ with open(self.ref_file_location) as ref_f:
197
+ labels = ref_f.readline().strip("\n").split(";")
198
+
199
+ for line in ref_f.readlines():
200
+ if line != "\n":
201
+ list_ref = line.strip("\n").split(" ")
202
+
203
+ if list_ref[2][-1] == "+":
204
+ ion_charge = int(list_ref[2][:-1])
205
+
206
+ else:
207
+ ion_charge = -1 * int(list_ref[2][:-1])
208
+
209
+ ion_mol_formula = list_ref[0]
210
+ mz = float(list_ref[1])
211
+ formula_dict = self.mformula_s_to_dict(ion_mol_formula)
212
+
213
+ list_mf_obj.append(
214
+ MolecularFormula(formula_dict, ion_charge, external_mz=mz)
215
+ )
216
+
217
+ return list_mf_obj
218
+
219
+ def from_corems_ref_file(self, delimiter="\t"): # pragma: no cover
220
+ """Create a list of MolecularFormula objects from CoreMS reference file
221
+
222
+ Not being used
223
+
224
+ Parameters
225
+ ----------
226
+ delimiter : str
227
+ delimiter used in the reference file
228
+
229
+ Returns
230
+ -------
231
+ List[MolecularFormula]
232
+ List of MolecularFormula objects from CoreMS reference file
233
+ """
234
+ # not being used
235
+ import csv
236
+
237
+ list_mf_obj = []
238
+
239
+ with open("res/RefMassLists/Crude-Pos-ESI.ref") as ref_f:
240
+ labels = ref_f.readline().strip("\n").split(delimiter)
241
+
242
+ for line in ref_f.readlines():
243
+ if line != "\n":
244
+ list_ref = line.strip("\n").split(delimiter)
245
+
246
+ formula_string = list_ref[0]
247
+ ion_charge = int(list_ref[1])
248
+ ion_type = list_ref[2]
249
+
250
+ molform = MolecularFormula(
251
+ formula_string, ion_charge, ion_type=ion_type
252
+ )
253
+
254
+ list_mf_obj.append(self.molecular_formula_ref(molform))
255
+
256
+ return list_mf_obj
257
+
258
+ def split(self, delimiters, string, maxsplit=0): # pragma: no cover
259
+ """Splits a string using a list of delimiters.
260
+
261
+ Does not work when formula has atoms with same characters, i.e - C10H21NNa
262
+
263
+ Parameters
264
+ ----------
265
+ delimiters : list
266
+ list of delimiters
267
+ string : str
268
+ string to be split
269
+ maxsplit : int, optional
270
+ maximum number of splits. Default is 0
271
+
272
+ Returns
273
+ -------
274
+ list
275
+ list of strings obtained after splitting the string
276
+ list
277
+ list of counts obtained after splitting the string
278
+ """
279
+ regexPattern = "|".join(map(re.escape, delimiters)) # pragma: no cover
280
+ isotopes = re.findall(regexPattern, string) # pragma: no cover
281
+ counts = re.split(regexPattern, string, maxsplit) # pragma: no cover
282
+ return isotopes, counts
283
+
284
+ def mformula_s_to_dict(self, s_mformulatring, iontype="unknown"):
285
+ """Converts a molecular formula string to a dict
286
+
287
+ Parameters
288
+ ----------
289
+ s_mformulatring : str
290
+ molecular formula string, i.e. 'C10H21NNa'
291
+ iontype : str, optional
292
+ ion type. Default is 'unknown'
293
+
294
+ Returns
295
+ -------
296
+ dict
297
+ molecular formula dictionary
298
+
299
+ Notes
300
+ -----
301
+ Does not work if the atomic mass number is passed i.e. 37Cl, 81Br, convention follow the light isotope labeling 35Cl is Cl, 12C is C, etc.
302
+ If you need to use heavy isotopes please use another reference file format that separate the formula string by a blank space and parse it using the function corems_ref_file
303
+
304
+ Raises
305
+ ------
306
+ TypeError
307
+ Atom does not exist in Atoms.atoms_order list
308
+ Exception
309
+ Empty molecular formula
310
+ """
311
+ if s_mformulatring:
312
+ # find the case C122
313
+ all_atoms = re.findall(r"[A-Z]{1}[0-9]{1,10000}", s_mformulatring)
314
+
315
+ # find the case Br2
316
+ all_atoms2 = re.findall(r"[A-Z]{1}[a-z]{1}[0-9]{1,10000}", s_mformulatring)
317
+ # find the case N
318
+ single_digit_atoms_one = re.findall(
319
+ r"[A-Z]{1}(?![0-9])(?![a-z])", s_mformulatring
320
+ )
321
+ # print(single_digit_atoms_one)
322
+ # find the case Na
323
+ due_digit_atoms_one = re.findall(
324
+ r"[A-Z]{1}[a-z]{1}(?![0-9])", s_mformulatring
325
+ )
326
+
327
+ all_atoms = (
328
+ all_atoms + all_atoms2 + due_digit_atoms_one + single_digit_atoms_one
329
+ )
330
+
331
+ dict_res = {}
332
+
333
+ for each_atom_count in all_atoms:
334
+ count = re.findall(r"[0-9]{1,10000}", each_atom_count)
335
+ atom = "".join(re.findall(r"[A-z]", each_atom_count))
336
+
337
+ if atom in Atoms.atoms_order:
338
+ if count:
339
+ dict_res[atom] = int(count[0])
340
+ else:
341
+ dict_res[atom] = 1
342
+
343
+ else:
344
+ tb = sys.exc_info()[2]
345
+ raise TypeError(
346
+ "Atom %s does not exist in Atoms.atoms_order list" % atom
347
+ ).with_traceback(tb)
348
+
349
+ dict_res[Labels.ion_type] = iontype
350
+
351
+ return dict_res
352
+
353
+ else:
354
+ tb = sys.exc_info()[2]
355
+ raise Exception("Empty molecular formula").with_traceback(tb)
File without changes
@@ -0,0 +1,251 @@
1
+ import pandas as pd
2
+ from sklearn.cluster import DBSCAN
3
+ from sklearn.preprocessing import StandardScaler
4
+
5
+ # import matplotlib.pyplot as plt
6
+
7
+
8
+ class ClusteringFilter:
9
+ """Class for filtering and clustering mass spectra data using various algorithms.
10
+
11
+ Attributes
12
+ -------
13
+ mass_spectrum : MassSpectrum
14
+ Mass spectrum object.
15
+ ms_peaks : list
16
+ List of mass peaks.
17
+ ms_peak_indexes : list
18
+ List of peak indexes.
19
+ min_samples : int
20
+ Minimum number of samples in a cluster.
21
+ eps : float
22
+ The maximum distance between two samples for one to be considered as in the neighborhood of the other.
23
+ bandwidth : float
24
+ Bandwidth used in MeanShift algorithm.
25
+ quantile : float
26
+ Quantile used in estimate_bandwidth function.
27
+ n_samples : int
28
+ Number of samples used in estimate_bandwidth function.
29
+ bin_seeding : bool
30
+ If true, initial kernel locations are not locations of all points, but rather the location of the discretized version of points, where points are binned onto a grid whose coarseness corresponds to the bandwidth. Setting this option to True will speed up the algorithm because fewer seeds will be initialized.
31
+ min_peaks_per_class : int
32
+ Minimum number of peaks per class.
33
+
34
+ Methods
35
+ -------
36
+ * get_mass_error_matrix_data(ms_peaks).
37
+ Get the mass error matrix data from a list of mass peaks.
38
+ * get_kendrick_matrix_data(mass_spectrum).
39
+ Get the Kendrick matrix data from a mass spectrum.
40
+ * filter_kendrick(mass_spectrum).
41
+ Filter the mass spectrum data using the Kendrick algorithm.
42
+ * filter_kendrick_by_index(ms_peak_indexes, mass_spectrum_obj).
43
+ Filter the mass spectrum data using the Kendrick algorithm based on a list of peak indexes.
44
+ * remove_assignment_by_mass_error(mass_spectrum).
45
+ Remove assignments from the mass spectrum based on mass error.
46
+
47
+
48
+ """
49
+
50
+ def get_mass_error_matrix_data(self, ms_peaks):
51
+ """Get the mass error matrix data from a list of mass peaks.
52
+
53
+ Parameters
54
+ ----------
55
+ ms_peaks : list
56
+ List of mass peaks.
57
+
58
+ Returns
59
+ -------
60
+ matrix_data : ndarray
61
+ Matrix data containing mass and error values.
62
+ list_indexes_mass_spec : list
63
+ List of indexes of mass peaks in the original mass spectrum.
64
+ """
65
+ mass_list = list()
66
+ error_list = list()
67
+ list_indexes_mass_spec = []
68
+
69
+ for index, mspeak in enumerate(ms_peaks):
70
+ if mspeak.is_assigned:
71
+ # print(mspeak.mz_exp, len(mspeak))
72
+ for mformula in mspeak:
73
+ mass_list.append(mspeak.mz_exp)
74
+ error_list.append(mformula.mz_error)
75
+ list_indexes_mass_spec.append(index)
76
+
77
+ kendrick_dict = {"mass": mass_list, "error": error_list}
78
+ df = pd.DataFrame(kendrick_dict)
79
+ matrix_data = df.values.astype("float32", copy=False)
80
+ return matrix_data, list_indexes_mass_spec
81
+
82
+ def get_kendrick_matrix_data(self, mass_spectrum):
83
+ """Get the Kendrick matrix data from a mass spectrum.
84
+
85
+ Parameters
86
+ ----------
87
+ mass_spectrum : MassSpectrum
88
+ Mass spectrum object.
89
+
90
+ Returns
91
+ -------
92
+ matrix_data : ndarray
93
+ Matrix data containing Kendrick mass and Kendrick mass defect values.
94
+ """
95
+ km = mass_spectrum.kendrick_mass
96
+ kmd = mass_spectrum.kmd
97
+ kendrick_dict = {"km": km, "kmd": kmd}
98
+ df = pd.DataFrame(kendrick_dict)
99
+ matrix_data = df.values.astype("float32", copy=False)
100
+ return matrix_data
101
+
102
+ def filter_kendrick(self, mass_spectrum):
103
+ """Filter the mass spectrum data using the Kendrick algorithm.
104
+
105
+ Parameters
106
+ ----------
107
+ mass_spectrum : MassSpectrum
108
+ Mass spectrum object.
109
+
110
+ """
111
+ matrix_data = self.get_kendrick_matrix_data(mass_spectrum)
112
+
113
+ stdscaler = StandardScaler().fit(matrix_data)
114
+
115
+ matrix_data_scaled = stdscaler.transform(matrix_data)
116
+
117
+ clusters = DBSCAN(eps=0.75, min_samples=50).fit_predict(matrix_data_scaled)
118
+
119
+ # Number of clusters in labels, ignoring noise if present.
120
+ n_clusters_ = len(set(clusters)) - (1 if -1 in clusters else 0)
121
+ n_noise_ = list(clusters).count(-1)
122
+
123
+ indexes = []
124
+ for i in range(len(clusters)):
125
+ if clusters[i] == -1:
126
+ indexes.append(i)
127
+
128
+ if mass_spectrum.parameters.mass_spectrum.verbose_processing:
129
+ print("Estimated number of clusters: %d" % n_clusters_)
130
+ print("Estimated number of noise points: %d" % n_noise_)
131
+ mass_spectrum.filter_by_index(indexes)
132
+ # from matplotlib import pyplot as plt
133
+ # plt.scatter(matrix_data[:, 0], matrix_data[:, 1], c=clusters, cmap="jet")
134
+ # plt.xlabel("km")
135
+ # plt.ylabel("kmd")
136
+ # plt.show()
137
+ # plt.close()
138
+
139
+ def filter_kendrick_by_index(self, ms_peak_indexes, mass_spectrum_obj):
140
+ """Filter the mass spectrum data using the Kendrick algorithm based on a list of peak indexes.
141
+
142
+ Parameters
143
+ ----------
144
+ ms_peak_indexes : list
145
+ List of peak indexes.
146
+ mass_spectrum_obj : MassSpectrum
147
+ Mass spectrum object.
148
+
149
+ Returns
150
+ -------
151
+ noise_idx : list
152
+ List of indexes of noise points in the mass spectrum.
153
+ """
154
+ min_samples = mass_spectrum_obj.molecular_search_settings.min_peaks_per_class
155
+
156
+ kendrick_dict = {"km": list(), "kmd": list()}
157
+
158
+ if len(ms_peak_indexes) <= 1:
159
+ return []
160
+
161
+ for index, _ in ms_peak_indexes:
162
+ kendrick_dict["km"].append(mass_spectrum_obj[index].kendrick_mass)
163
+ kendrick_dict["kmd"].append(mass_spectrum_obj[index].kmd)
164
+
165
+ # check min data points otherwise StandardScaler().fit(0 will fail
166
+
167
+ df = pd.DataFrame(kendrick_dict)
168
+ matrix_data = df.values.astype("float32", copy=False)
169
+
170
+ stdscaler = StandardScaler().fit(matrix_data)
171
+ matrix_data_scaled = stdscaler.transform(matrix_data)
172
+
173
+ clusters = DBSCAN(eps=0.8, min_samples=min_samples).fit_predict(
174
+ matrix_data_scaled
175
+ )
176
+
177
+ # Number of clusters in labels, ignoring noise if present.
178
+ n_clusters_ = len(set(clusters)) - (1 if -1 in clusters else 0)
179
+ n_noise_ = list(clusters).count(-1)
180
+
181
+ if mass_spectrum_obj.parameters.mass_spectrum.verbose_processing:
182
+ print("Estimated number of clusters: %d" % n_clusters_)
183
+ print("Estimated number of noise points: %d" % n_noise_)
184
+
185
+ noise_idx = []
186
+
187
+ other_peaks_idx = []
188
+
189
+ for i in range(len(clusters)):
190
+ if clusters[i] == -1:
191
+ noise_idx.append(ms_peak_indexes[i])
192
+
193
+ else:
194
+ other_peaks_idx.append(ms_peak_indexes[i])
195
+
196
+ # mfs = [mass_spectrum_obj[index].best_molecular_formula_candidate.string for index in other_peaks_idx]
197
+
198
+ # mfs_noise = [mass_spectrum_obj[index].best_molecular_formula_candidate.string for index in noise_idx]
199
+
200
+ # print(mfs)
201
+ # print(mfs_noise)
202
+
203
+ # from matplotlib import pyplot as plt
204
+ # plt.scatter(matrix_data[:, 0], matrix_data[:, 1], c=clusters, cmap="jet")
205
+ # plt.xlabel("km")
206
+ # plt.ylabel("kmd")
207
+ # plt.show()
208
+ # plt.close()
209
+
210
+ return noise_idx
211
+
212
+ def remove_assignment_by_mass_error(self, mass_spectrum):
213
+ """Remove assignments from the mass spectrum based on mass error.
214
+
215
+ Parameters
216
+ ----------
217
+ mass_spectrum : MassSpectrum
218
+ Mass spectrum object.
219
+
220
+ """
221
+ # data need to be binned by mz unit or more to be able to use clustering
222
+
223
+ matrix_data, list_indexes_mass_spec = self.get_mass_error_matrix_data(
224
+ mass_spectrum
225
+ )
226
+
227
+ stdscaler = StandardScaler().fit(matrix_data)
228
+
229
+ matrix_data_scaled = stdscaler.transform(matrix_data)
230
+
231
+ # bandwidth = estimate_bandwidth(matrix_data_scaled, quantile=0.3, n_samples=int(len(ms_peaks)/3))
232
+
233
+ # clusters = MeanShift(bandwidth=bandwidth, bin_seeding=True).fit_predict(matrix_data_scaled)
234
+
235
+ # eps and min_samp need to be optimized by precision and number of mspeaks
236
+ clusters = DBSCAN(eps=0.15).fit_predict(matrix_data_scaled)
237
+
238
+ indexes = []
239
+
240
+ # from matplotlib import pyplot as plt
241
+ # plt.scatter(matrix_data[:, 0], matrix_data[:, 1], c=clusters, cmap="plasma")
242
+ # plt.xlabel("km")
243
+ # plt.ylabel("kmd")
244
+ # plt.show()
245
+ # plt.close()
246
+
247
+ for i in range(len(clusters)):
248
+ if clusters[i] == -1:
249
+ indexes.append(list_indexes_mass_spec[i])
250
+
251
+ mass_spectrum.remove_assignment_by_index(indexes)