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
@@ -0,0 +1,1753 @@
1
+ from pathlib import Path
2
+
3
+ import numpy as np
4
+ from lmfit.models import GaussianModel
5
+
6
+ # from matplotlib import rcParamsDefault, rcParams
7
+ from numpy import array, float64, histogram, where
8
+ try:
9
+ from numpy import trapezoid
10
+ except ImportError: # numpy < 2.0
11
+ from numpy import trapz as trapezoid
12
+ from pandas import DataFrame
13
+
14
+ from corems.encapsulation.constant import Labels
15
+ from corems.encapsulation.factory.parameters import MSParameters
16
+ from corems.encapsulation.input.parameter_from_json import (
17
+ load_and_set_parameters_ms,
18
+ load_and_set_toml_parameters_ms,
19
+ )
20
+ from corems.mass_spectrum.calc.KendrickGroup import KendrickGrouping
21
+ from corems.mass_spectrum.calc.MassSpectrumCalc import MassSpecCalc
22
+ from corems.mass_spectrum.calc.MeanResolvingPowerFilter import MeanResolvingPowerFilter
23
+ from corems.ms_peak.factory.MSPeakClasses import ICRMassPeak as MSPeak
24
+
25
+ __author__ = "Yuri E. Corilo"
26
+ __date__ = "Jun 12, 2019"
27
+
28
+
29
+ def overrides(interface_class):
30
+ """Checks if the method overrides a method from an interface class."""
31
+
32
+ def overrider(method):
33
+ assert method.__name__ in dir(interface_class)
34
+ return method
35
+
36
+ return overrider
37
+
38
+
39
+ class MassSpecBase(MassSpecCalc, KendrickGrouping):
40
+ """A mass spectrum base class, stores the profile data and instrument settings.
41
+
42
+ Iteration over a list of MSPeaks classes stored at the _mspeaks attributes.
43
+ _mspeaks is populated under the hood by calling process_mass_spec method.
44
+ Iteration is null if _mspeaks is empty.
45
+
46
+ Parameters
47
+ ----------
48
+ mz_exp : array_like
49
+ The m/z values of the mass spectrum.
50
+ abundance : array_like
51
+ The abundance values of the mass spectrum.
52
+ d_params : dict
53
+ A dictionary of parameters for the mass spectrum.
54
+ **kwargs
55
+ Additional keyword arguments.
56
+
57
+ Attributes
58
+ ----------
59
+
60
+ mspeaks : list
61
+ A list of mass peaks.
62
+ is_calibrated : bool
63
+ Whether the mass spectrum is calibrated.
64
+ is_centroid : bool
65
+ Whether the mass spectrum is centroided.
66
+ has_frequency : bool
67
+ Whether the mass spectrum has a frequency domain.
68
+ calibration_order : None or int
69
+ The order of the mass spectrum's calibration.
70
+ calibration_points : None or ndarray
71
+ The calibration points of the mass spectrum.
72
+ calibration_ref_mzs: None or ndarray
73
+ The reference m/z values of the mass spectrum's calibration.
74
+ calibration_meas_mzs : None or ndarray
75
+ The measured m/z values of the mass spectrum's calibration.
76
+ calibration_RMS : None or float
77
+ The root mean square of the mass spectrum's calibration.
78
+ calibration_segment : None or CalibrationSegment
79
+ The calibration segment of the mass spectrum.
80
+ _abundance : ndarray
81
+ The abundance values of the mass spectrum.
82
+ _mz_exp : ndarray
83
+ The m/z values of the mass spectrum.
84
+ _mspeaks : list
85
+ A list of mass peaks.
86
+ _dict_nominal_masses_indexes : dict
87
+ A dictionary of nominal masses and their indexes.
88
+ _baseline_noise : float
89
+ The baseline noise of the mass spectrum.
90
+ _baseline_noise_std : float
91
+ The standard deviation of the baseline noise of the mass spectrum.
92
+ _dynamic_range : float or None
93
+ The dynamic range of the mass spectrum.
94
+ _transient_settings : None or TransientSettings
95
+ The transient settings of the mass spectrum.
96
+ _frequency_domain : None or FrequencyDomain
97
+ The frequency domain of the mass spectrum.
98
+ _mz_cal_profile : None or MzCalibrationProfile
99
+ The m/z calibration profile of the mass spectrum.
100
+
101
+ Methods
102
+ -------
103
+ * process_mass_spec(). Main function to process the mass spectrum,
104
+ including calculating the noise threshold, peak picking, and resetting the MSpeak indexes.
105
+
106
+ See also: MassSpecCentroid(), MassSpecfromFreq(), MassSpecProfile()
107
+ """
108
+
109
+ def __init__(self, mz_exp, abundance, d_params, **kwargs):
110
+ self._abundance = array(abundance, dtype=float64)
111
+ self._mz_exp = array(mz_exp, dtype=float64)
112
+
113
+ # objects created after process_mass_spec() function
114
+ self._mspeaks = list()
115
+ self.mspeaks = list()
116
+ self._dict_nominal_masses_indexes = dict()
117
+ self._baseline_noise = 0.001
118
+ self._baseline_noise_std = 0.001
119
+ self._dynamic_range = None
120
+ # set to None: initialization occurs inside subclass MassSpecfromFreq
121
+ self._transient_settings = None
122
+ self._frequency_domain = None
123
+ self._mz_cal_profile = None
124
+ self.is_calibrated = False
125
+
126
+ self._set_parameters_objects(d_params)
127
+ self._init_settings()
128
+
129
+ self.is_centroid = False
130
+ self.has_frequency = False
131
+
132
+ self.calibration_order = None
133
+ self.calibration_points = None
134
+ self.calibration_ref_mzs = None
135
+ self.calibration_meas_mzs = None
136
+ self.calibration_RMS = None
137
+ self.calibration_segment = None
138
+ self.calibration_raw_error_median = None
139
+ self.calibration_raw_error_stdev = None
140
+
141
+ def _init_settings(self):
142
+ """Initializes the settings for the mass spectrum."""
143
+ self._parameters = MSParameters()
144
+
145
+ def __len__(self):
146
+ return len(self.mspeaks)
147
+
148
+ def __getitem__(self, position) -> MSPeak:
149
+ return self.mspeaks[position]
150
+
151
+ def set_indexes(self, list_indexes):
152
+ """Set the mass spectrum to iterate over only the selected MSpeaks indexes.
153
+
154
+ Parameters
155
+ ----------
156
+ list_indexes : list of int
157
+ A list of integers representing the indexes of the MSpeaks to iterate over.
158
+
159
+ """
160
+ self.mspeaks = [self._mspeaks[i] for i in list_indexes]
161
+
162
+ for i, mspeak in enumerate(self.mspeaks):
163
+ mspeak.index = i
164
+
165
+ self._set_nominal_masses_start_final_indexes()
166
+
167
+ def reset_indexes(self):
168
+ """Reset the mass spectrum to iterate over all MSpeaks objects.
169
+
170
+ This method resets the mass spectrum to its original state, allowing iteration over all MSpeaks objects.
171
+ It also sets the index of each MSpeak object to its corresponding position in the mass spectrum.
172
+
173
+ """
174
+ self.mspeaks = self._mspeaks
175
+
176
+ for i, mspeak in enumerate(self.mspeaks):
177
+ mspeak.index = i
178
+
179
+ self._set_nominal_masses_start_final_indexes()
180
+
181
+ def add_mspeak(
182
+ self,
183
+ ion_charge,
184
+ mz_exp,
185
+ abundance,
186
+ resolving_power,
187
+ signal_to_noise,
188
+ massspec_indexes,
189
+ exp_freq=None,
190
+ ms_parent=None,
191
+ ):
192
+ """Add a new MSPeak object to the MassSpectrum object.
193
+
194
+ Parameters
195
+ ----------
196
+ ion_charge : int
197
+ The ion charge of the MSPeak.
198
+ mz_exp : float
199
+ The experimental m/z value of the MSPeak.
200
+ abundance : float
201
+ The abundance of the MSPeak.
202
+ resolving_power : float
203
+ The resolving power of the MSPeak.
204
+ signal_to_noise : float
205
+ The signal-to-noise ratio of the MSPeak.
206
+ massspec_indexes : list
207
+ A list of indexes of the MSPeak in the MassSpectrum object.
208
+ exp_freq : float, optional
209
+ The experimental frequency of the MSPeak. Defaults to None.
210
+ ms_parent : MSParent, optional
211
+ The MSParent object associated with the MSPeak. Defaults to None.
212
+ """
213
+ mspeak = MSPeak(
214
+ ion_charge,
215
+ mz_exp,
216
+ abundance,
217
+ resolving_power,
218
+ signal_to_noise,
219
+ massspec_indexes,
220
+ len(self._mspeaks),
221
+ exp_freq=exp_freq,
222
+ ms_parent=ms_parent,
223
+ )
224
+
225
+ self._mspeaks.append(mspeak)
226
+
227
+ def _set_parameters_objects(self, d_params):
228
+ """Set the parameters of the MassSpectrum object.
229
+
230
+ Parameters
231
+ ----------
232
+ d_params : dict
233
+ A dictionary containing the parameters to set.
234
+
235
+ Notes
236
+ -----
237
+ This method sets the following parameters of the MassSpectrum object:
238
+ - _calibration_terms
239
+ - label
240
+ - analyzer
241
+ - acquisition_time
242
+ - instrument_label
243
+ - polarity
244
+ - scan_number
245
+ - retention_time
246
+ - mobility_rt
247
+ - mobility_scan
248
+ - _filename
249
+ - _dir_location
250
+ - _baseline_noise
251
+ - _baseline_noise_std
252
+ - sample_name
253
+ """
254
+ self._calibration_terms = (
255
+ d_params.get("Aterm"),
256
+ d_params.get("Bterm"),
257
+ d_params.get("Cterm"),
258
+ )
259
+
260
+ self.label = d_params.get(Labels.label)
261
+
262
+ self.analyzer = d_params.get("analyzer")
263
+
264
+ self.acquisition_time = d_params.get("acquisition_time")
265
+
266
+ self.instrument_label = d_params.get("instrument_label")
267
+
268
+ self.polarity = int(d_params.get("polarity"))
269
+
270
+ self.scan_number = d_params.get("scan_number")
271
+
272
+ self.retention_time = d_params.get("rt")
273
+
274
+ self.mobility_rt = d_params.get("mobility_rt")
275
+
276
+ self.mobility_scan = d_params.get("mobility_scan")
277
+
278
+ self._filename = d_params.get("filename_path")
279
+
280
+ self._dir_location = d_params.get("dir_location")
281
+
282
+ self._baseline_noise = d_params.get("baseline_noise")
283
+
284
+ self._baseline_noise_std = d_params.get("baseline_noise_std")
285
+
286
+ if d_params.get("sample_name") != "Unknown":
287
+ self.sample_name = d_params.get("sample_name")
288
+ if not self.sample_name:
289
+ self.sample_name = self.filename.stem
290
+ else:
291
+ self.sample_name = self.filename.stem
292
+
293
+ def reset_cal_therms(self, Aterm, Bterm, C, fas=0):
294
+ """Reset calibration terms and recalculate the mass-to-charge ratio and abundance.
295
+
296
+ Parameters
297
+ ----------
298
+ Aterm : float
299
+ The A-term calibration coefficient.
300
+ Bterm : float
301
+ The B-term calibration coefficient.
302
+ C : float
303
+ The C-term calibration coefficient.
304
+ fas : float, optional
305
+ The frequency amplitude scaling factor. Default is 0.
306
+ """
307
+ self._calibration_terms = (Aterm, Bterm, C)
308
+
309
+ self._mz_exp = self._f_to_mz()
310
+ self._abundance = self._abundance
311
+ self.find_peaks()
312
+ self.reset_indexes()
313
+
314
+ def clear_molecular_formulas(self):
315
+ """Clear the molecular formulas for all mspeaks in the MassSpectrum.
316
+
317
+ Returns
318
+ -------
319
+ numpy.ndarray
320
+ An array of the cleared molecular formulas for each mspeak in the MassSpectrum.
321
+ """
322
+ self.check_mspeaks()
323
+ return array([mspeak.clear_molecular_formulas() for mspeak in self.mspeaks])
324
+
325
+ def process_mass_spec(self, keep_profile=True):
326
+ """Process the mass spectrum.
327
+
328
+ Parameters
329
+ ----------
330
+ keep_profile : bool, optional
331
+ Whether to keep the profile data after processing. Defaults to True.
332
+
333
+ Notes
334
+ -----
335
+ This method does the following:
336
+ - calculates the noise threshold
337
+ - does peak picking (creates mspeak_objs)
338
+ - resets the mspeak_obj indexes
339
+ """
340
+
341
+ # if runned mannually make sure to rerun filter_by_noise_threshold
342
+ # calculates noise threshold
343
+ # do peak picking( create mspeak_objs)
344
+ # reset mspeak_obj the indexes
345
+
346
+ self.cal_noise_threshold()
347
+
348
+ self.find_peaks()
349
+ self.reset_indexes()
350
+
351
+ if self.mspeaks:
352
+ self._dynamic_range = self.max_abundance / self.min_abundance
353
+ else:
354
+ self._dynamic_range = 0
355
+ if not keep_profile:
356
+ self._abundance *= 0
357
+ self._mz_exp *= 0
358
+
359
+ def cal_noise_threshold(self):
360
+ """Calculate the noise threshold of the mass spectrum."""
361
+
362
+ if self.label == Labels.simulated_profile:
363
+ self._baseline_noise, self._baseline_noise_std = 0.1, 1
364
+
365
+ if self.settings.noise_threshold_method == "log":
366
+ self._baseline_noise, self._baseline_noise_std = (
367
+ self.run_log_noise_threshold_calc()
368
+ )
369
+
370
+ else:
371
+ self._baseline_noise, self._baseline_noise_std = (
372
+ self.run_noise_threshold_calc()
373
+ )
374
+
375
+ @property
376
+ def parameters(self):
377
+ """Return the parameters of the mass spectrum."""
378
+ return self._parameters
379
+
380
+ @parameters.setter
381
+ def parameters(self, instance_MSParameters):
382
+ self._parameters = instance_MSParameters
383
+
384
+ def set_parameter_from_json(self, parameters_path):
385
+ """Set the parameters of the mass spectrum from a JSON file.
386
+
387
+ Parameters
388
+ ----------
389
+ parameters_path : str
390
+ The path to the JSON file containing the parameters.
391
+ """
392
+ load_and_set_parameters_ms(self, parameters_path=parameters_path)
393
+
394
+ def set_parameter_from_toml(self, parameters_path):
395
+ load_and_set_toml_parameters_ms(self, parameters_path=parameters_path)
396
+
397
+ @property
398
+ def mspeaks_settings(self):
399
+ """Return the MS peak settings of the mass spectrum."""
400
+ return self.parameters.ms_peak
401
+
402
+ @mspeaks_settings.setter
403
+ def mspeaks_settings(self, instance_MassSpecPeakSetting):
404
+ self.parameters.ms_peak = instance_MassSpecPeakSetting
405
+
406
+ @property
407
+ def settings(self):
408
+ """Return the settings of the mass spectrum."""
409
+ return self.parameters.mass_spectrum
410
+
411
+ @settings.setter
412
+ def settings(self, instance_MassSpectrumSetting):
413
+ self.parameters.mass_spectrum = instance_MassSpectrumSetting
414
+
415
+ @property
416
+ def molecular_search_settings(self):
417
+ """Return the molecular search settings of the mass spectrum."""
418
+ return self.parameters.molecular_search
419
+
420
+ @molecular_search_settings.setter
421
+ def molecular_search_settings(self, instance_MolecularFormulaSearchSettings):
422
+ self.parameters.molecular_search = instance_MolecularFormulaSearchSettings
423
+
424
+ @property
425
+ def mz_cal_profile(self):
426
+ """Return the calibrated m/z profile of the mass spectrum."""
427
+ return self._mz_cal_profile
428
+
429
+ @mz_cal_profile.setter
430
+ def mz_cal_profile(self, mz_cal_list):
431
+ if len(mz_cal_list) == len(self._mz_exp):
432
+ self._mz_cal_profile = mz_cal_list
433
+ else:
434
+ raise Exception(
435
+ "calibrated array (%i) is not of the same size of the data (%i)"
436
+ % (len(mz_cal_list), len(self.mz_exp_profile))
437
+ )
438
+
439
+ @property
440
+ def mz_cal(self):
441
+ """Return the calibrated m/z values of the mass spectrum."""
442
+ return array([mspeak.mz_cal for mspeak in self.mspeaks])
443
+
444
+ @mz_cal.setter
445
+ def mz_cal(self, mz_cal_list):
446
+ if len(mz_cal_list) == len(self.mspeaks):
447
+ self.is_calibrated = True
448
+ for index, mz_cal in enumerate(mz_cal_list):
449
+ self.mspeaks[index].mz_cal = mz_cal
450
+ else:
451
+ raise Exception(
452
+ "calibrated array (%i) is not of the same size of the data (%i)"
453
+ % (len(mz_cal_list), len(self._mspeaks))
454
+ )
455
+
456
+ @property
457
+ def mz_exp(self):
458
+ """Return the experimental m/z values of the mass spectrum."""
459
+ self.check_mspeaks()
460
+
461
+ if self.is_calibrated:
462
+ return array([mspeak.mz_cal for mspeak in self.mspeaks])
463
+
464
+ else:
465
+ return array([mspeak.mz_exp for mspeak in self.mspeaks])
466
+
467
+ @property
468
+ def freq_exp_profile(self):
469
+ """Return the experimental frequency profile of the mass spectrum."""
470
+ return self._frequency_domain
471
+
472
+ @freq_exp_profile.setter
473
+ def freq_exp_profile(self, new_data):
474
+ self._frequency_domain = array(new_data)
475
+
476
+ @property
477
+ def freq_exp_pp(self):
478
+ """Return the experimental frequency values of the mass spectrum that are used for peak picking."""
479
+ _, _, freq = self.prepare_peak_picking_data()
480
+ return freq
481
+
482
+ @property
483
+ def mz_exp_profile(self):
484
+ """Return the experimental m/z profile of the mass spectrum."""
485
+ if self.is_calibrated:
486
+ return self.mz_cal_profile
487
+ else:
488
+ return self._mz_exp
489
+
490
+ @mz_exp_profile.setter
491
+ def mz_exp_profile(self, new_data):
492
+ self._mz_exp = array(new_data)
493
+
494
+ @property
495
+ def mz_exp_pp(self):
496
+ """Return the experimental m/z values of the mass spectrum that are used for peak picking."""
497
+ mz, _, _ = self.prepare_peak_picking_data()
498
+ return mz
499
+
500
+ @property
501
+ def abundance_profile(self):
502
+ """Return the abundance profile of the mass spectrum."""
503
+ return self._abundance
504
+
505
+ @abundance_profile.setter
506
+ def abundance_profile(self, new_data):
507
+ self._abundance = array(new_data)
508
+
509
+ @property
510
+ def abundance_profile_pp(self):
511
+ """Return the abundance profile of the mass spectrum that is used for peak picking."""
512
+ _, abundance, _ = self.prepare_peak_picking_data()
513
+ return abundance
514
+
515
+ @property
516
+ def abundance(self):
517
+ """Return the abundance values of the mass spectrum."""
518
+ self.check_mspeaks()
519
+ return array([mspeak.abundance for mspeak in self.mspeaks])
520
+
521
+ def freq_exp(self):
522
+ """Return the experimental frequency values of the mass spectrum."""
523
+ self.check_mspeaks()
524
+ return array([mspeak.freq_exp for mspeak in self.mspeaks])
525
+
526
+ @property
527
+ def resolving_power(self):
528
+ """Return the resolving power values of the mass spectrum."""
529
+ self.check_mspeaks()
530
+ return array([mspeak.resolving_power for mspeak in self.mspeaks])
531
+
532
+ @property
533
+ def signal_to_noise(self):
534
+ self.check_mspeaks()
535
+ return array([mspeak.signal_to_noise for mspeak in self.mspeaks])
536
+
537
+ @property
538
+ def nominal_mz(self):
539
+ """Return the nominal m/z values of the mass spectrum."""
540
+ if self._dict_nominal_masses_indexes:
541
+ return sorted(list(self._dict_nominal_masses_indexes.keys()))
542
+ else:
543
+ raise ValueError("Nominal indexes not yet set")
544
+
545
+ def get_mz_and_abundance_peaks_tuples(self):
546
+ """Return a list of tuples containing the m/z and abundance values of the mass spectrum."""
547
+ self.check_mspeaks()
548
+ return [(mspeak.mz_exp, mspeak.abundance) for mspeak in self.mspeaks]
549
+
550
+ @property
551
+ def kmd(self):
552
+ """Return the Kendrick mass defect values of the mass spectrum."""
553
+ self.check_mspeaks()
554
+ return array([mspeak.kmd for mspeak in self.mspeaks])
555
+
556
+ @property
557
+ def kendrick_mass(self):
558
+ """Return the Kendrick mass values of the mass spectrum."""
559
+ self.check_mspeaks()
560
+ return array([mspeak.kendrick_mass for mspeak in self.mspeaks])
561
+
562
+ @property
563
+ def max_mz_exp(self):
564
+ """Return the maximum experimental m/z value of the mass spectrum."""
565
+ return max([mspeak.mz_exp for mspeak in self.mspeaks])
566
+
567
+ @property
568
+ def min_mz_exp(self):
569
+ """Return the minimum experimental m/z value of the mass spectrum."""
570
+ return min([mspeak.mz_exp for mspeak in self.mspeaks])
571
+
572
+ @property
573
+ def max_abundance(self):
574
+ """Return the maximum abundance value of the mass spectrum."""
575
+ return max([mspeak.abundance for mspeak in self.mspeaks])
576
+
577
+ @property
578
+ def max_signal_to_noise(self):
579
+ """Return the maximum signal-to-noise ratio of the mass spectrum."""
580
+ return max([mspeak.signal_to_noise for mspeak in self.mspeaks])
581
+
582
+ @property
583
+ def most_abundant_mspeak(self):
584
+ """Return the most abundant MSpeak object of the mass spectrum."""
585
+ return max(self.mspeaks, key=lambda m: m.abundance)
586
+
587
+ @property
588
+ def min_abundance(self):
589
+ """Return the minimum abundance value of the mass spectrum."""
590
+ return min([mspeak.abundance for mspeak in self.mspeaks])
591
+
592
+ # takes too much cpu time
593
+ @property
594
+ def dynamic_range(self):
595
+ """Return the dynamic range of the mass spectrum."""
596
+ return self._dynamic_range
597
+
598
+ @property
599
+ def baseline_noise(self):
600
+ """Return the baseline noise of the mass spectrum."""
601
+ if self._baseline_noise:
602
+ return self._baseline_noise
603
+ else:
604
+ return None
605
+
606
+ @property
607
+ def baseline_noise_std(self):
608
+ """Return the standard deviation of the baseline noise of the mass spectrum."""
609
+ if self._baseline_noise_std == 0:
610
+ return self._baseline_noise_std
611
+ if self._baseline_noise_std:
612
+ return self._baseline_noise_std
613
+ else:
614
+ return None
615
+
616
+ @property
617
+ def Aterm(self):
618
+ """Return the A-term calibration coefficient of the mass spectrum."""
619
+ return self._calibration_terms[0]
620
+
621
+ @property
622
+ def Bterm(self):
623
+ """Return the B-term calibration coefficient of the mass spectrum."""
624
+ return self._calibration_terms[1]
625
+
626
+ @property
627
+ def Cterm(self):
628
+ """Return the C-term calibration coefficient of the mass spectrum."""
629
+ return self._calibration_terms[2]
630
+
631
+ @property
632
+ def filename(self):
633
+ """Return the filename of the mass spectrum."""
634
+ return Path(self._filename)
635
+
636
+ @property
637
+ def dir_location(self):
638
+ """Return the directory location of the mass spectrum."""
639
+ return self._dir_location
640
+
641
+ def sort_by_mz(self):
642
+ """Sort the mass spectrum by m/z values."""
643
+ return sorted(self, key=lambda m: m.mz_exp)
644
+
645
+ def sort_by_abundance(self, reverse=False):
646
+ """Sort the mass spectrum by abundance values."""
647
+ return sorted(self, key=lambda m: m.abundance, reverse=reverse)
648
+
649
+ @property
650
+ def tic(self):
651
+ """Return the total ion current of the mass spectrum."""
652
+ return trapezoid(self.abundance_profile, self.mz_exp_profile)
653
+
654
+ def check_mspeaks_warning(self):
655
+ """Check if the mass spectrum has MSpeaks objects.
656
+
657
+ Raises
658
+ ------
659
+ Warning
660
+ If the mass spectrum has no MSpeaks objects.
661
+ """
662
+ import warnings
663
+
664
+ if self.mspeaks:
665
+ pass
666
+ else:
667
+ warnings.warn("mspeaks list is empty, continuing without filtering data")
668
+
669
+ def check_mspeaks(self):
670
+ """Check if the mass spectrum has MSpeaks objects.
671
+
672
+ Raises
673
+ ------
674
+ Exception
675
+ If the mass spectrum has no MSpeaks objects.
676
+ """
677
+ if self.mspeaks:
678
+ pass
679
+ else:
680
+ raise Exception(
681
+ "mspeaks list is empty, please run process_mass_spec() first"
682
+ )
683
+
684
+ def remove_assignment_by_index(self, indexes):
685
+ """Remove the molecular formula assignment of the MSpeaks objects at the specified indexes.
686
+
687
+ Parameters
688
+ ----------
689
+ indexes : list of int
690
+ A list of indexes of the MSpeaks objects to remove the molecular formula assignment from.
691
+ """
692
+ for i in indexes:
693
+ self.mspeaks[i].clear_molecular_formulas()
694
+
695
+ def filter_by_index(self, list_indexes):
696
+ """Filter the mass spectrum by the specified indexes.
697
+
698
+ Parameters
699
+ ----------
700
+ list_indexes : list of int
701
+ A list of indexes of the MSpeaks objects to drop.
702
+
703
+ """
704
+
705
+ self.mspeaks = [
706
+ self.mspeaks[i] for i in range(len(self.mspeaks)) if i not in list_indexes
707
+ ]
708
+
709
+ for i, mspeak in enumerate(self.mspeaks):
710
+ mspeak.index = i
711
+
712
+ self._set_nominal_masses_start_final_indexes()
713
+
714
+ def filter_by_mz(self, min_mz, max_mz):
715
+ """Filter the mass spectrum by the specified m/z range.
716
+
717
+ Parameters
718
+ ----------
719
+ min_mz : float
720
+ The minimum m/z value to keep.
721
+ max_mz : float
722
+ The maximum m/z value to keep.
723
+
724
+ """
725
+ self.check_mspeaks_warning()
726
+ indexes = [
727
+ index
728
+ for index, mspeak in enumerate(self.mspeaks)
729
+ if not min_mz <= mspeak.mz_exp <= max_mz
730
+ ]
731
+ self.filter_by_index(indexes)
732
+
733
+ def filter_by_s2n(self, min_s2n, max_s2n=False):
734
+ """Filter the mass spectrum by the specified signal-to-noise ratio range.
735
+
736
+ Parameters
737
+ ----------
738
+ min_s2n : float
739
+ The minimum signal-to-noise ratio to keep.
740
+ max_s2n : float, optional
741
+ The maximum signal-to-noise ratio to keep. Defaults to False (no maximum).
742
+
743
+ """
744
+ self.check_mspeaks_warning()
745
+ if max_s2n:
746
+ indexes = [
747
+ index
748
+ for index, mspeak in enumerate(self.mspeaks)
749
+ if not min_s2n <= mspeak.signal_to_noise <= max_s2n
750
+ ]
751
+ else:
752
+ indexes = [
753
+ index
754
+ for index, mspeak in enumerate(self.mspeaks)
755
+ if mspeak.signal_to_noise <= min_s2n
756
+ ]
757
+ self.filter_by_index(indexes)
758
+
759
+ def filter_by_abundance(self, min_abund, max_abund=False):
760
+ """Filter the mass spectrum by the specified abundance range.
761
+
762
+ Parameters
763
+ ----------
764
+ min_abund : float
765
+ The minimum abundance to keep.
766
+ max_abund : float, optional
767
+ The maximum abundance to keep. Defaults to False (no maximum).
768
+
769
+ """
770
+ self.check_mspeaks_warning()
771
+ if max_abund:
772
+ indexes = [
773
+ index
774
+ for index, mspeak in enumerate(self.mspeaks)
775
+ if not min_abund <= mspeak.abundance <= max_abund
776
+ ]
777
+ else:
778
+ indexes = [
779
+ index
780
+ for index, mspeak in enumerate(self.mspeaks)
781
+ if mspeak.abundance <= min_abund
782
+ ]
783
+ self.filter_by_index(indexes)
784
+
785
+ def filter_by_max_resolving_power(self, B, T):
786
+ """Filter the mass spectrum by the specified maximum resolving power.
787
+
788
+ Parameters
789
+ ----------
790
+ B : float
791
+ T : float
792
+
793
+ """
794
+
795
+ rpe = lambda m, z: (1.274e7 * z * B * T) / (m * z)
796
+
797
+ self.check_mspeaks_warning()
798
+
799
+ indexes_to_remove = [
800
+ index
801
+ for index, mspeak in enumerate(self.mspeaks)
802
+ if mspeak.resolving_power >= rpe(mspeak.mz_exp, mspeak.ion_charge)
803
+ ]
804
+ self.filter_by_index(indexes_to_remove)
805
+
806
+ def filter_by_mean_resolving_power(
807
+ self, ndeviations=3, plot=False, guess_pars=False
808
+ ):
809
+ """Filter the mass spectrum by the specified mean resolving power.
810
+
811
+ Parameters
812
+ ----------
813
+ ndeviations : float, optional
814
+ The number of standard deviations to use for filtering. Defaults to 3.
815
+ plot : bool, optional
816
+ Whether to plot the resolving power distribution. Defaults to False.
817
+ guess_pars : bool, optional
818
+ Whether to guess the parameters for the Gaussian model. Defaults to False.
819
+
820
+ """
821
+ self.check_mspeaks_warning()
822
+ indexes_to_remove = MeanResolvingPowerFilter(
823
+ self, ndeviations, plot, guess_pars
824
+ ).main()
825
+ self.filter_by_index(indexes_to_remove)
826
+
827
+ def filter_by_min_resolving_power(self, B, T, apodization_method: str=None, tolerance: float=0):
828
+ """Filter the mass spectrum by the calculated minimum theoretical resolving power.
829
+
830
+ This is currently designed only for FTICR data, and accounts only for magnitude mode data
831
+ Accurate results require passing the apodisaion method used to calculate the resolving power.
832
+ see the ICRMassPeak function `resolving_power_calc` for more details.
833
+
834
+ Parameters
835
+ ----------
836
+ B : Magnetic field strength in Tesla, float
837
+ T : transient length in seconds, float
838
+ apodization_method : str, optional
839
+ The apodization method to use for calculating the resolving power. Defaults to None.
840
+ tolerance : float, optional
841
+ The tolerance for the threshold. Defaults to 0, i.e. no tolerance
842
+
843
+ """
844
+ if self.analyzer != "ICR":
845
+ raise Exception(
846
+ "This method is only applicable to ICR mass spectra. "
847
+ )
848
+
849
+ self.check_mspeaks_warning()
850
+
851
+ indexes_to_remove = [
852
+ index
853
+ for index, mspeak in enumerate(self.mspeaks)
854
+ if mspeak.resolving_power < (1-tolerance) * mspeak.resolving_power_calc(B, T, apodization_method=apodization_method)
855
+ ]
856
+ self.filter_by_index(indexes_to_remove)
857
+
858
+ def filter_by_noise_threshold(self):
859
+ """Filter the mass spectrum by the noise threshold."""
860
+
861
+ threshold = self.get_noise_threshold()[1][0]
862
+
863
+ self.check_mspeaks_warning()
864
+
865
+ indexes_to_remove = [
866
+ index
867
+ for index, mspeak in enumerate(self.mspeaks)
868
+ if mspeak.abundance <= threshold
869
+ ]
870
+ self.filter_by_index(indexes_to_remove)
871
+
872
+ def find_peaks(self):
873
+ """Find the peaks of the mass spectrum."""
874
+ # needs to clear previous results from peak_picking
875
+ self._mspeaks = list()
876
+
877
+ # then do peak picking
878
+ self.do_peak_picking()
879
+ # print("A total of %i peaks were found" % len(self._mspeaks))
880
+
881
+ def change_kendrick_base_all_mspeaks(self, kendrick_dict_base):
882
+ """Change the Kendrick base of all MSpeaks objects.
883
+
884
+ Parameters
885
+ ----------
886
+ kendrick_dict_base : dict
887
+ A dictionary of the Kendrick base to change to.
888
+
889
+ Notes
890
+ -----
891
+ Example of kendrick_dict_base parameter: kendrick_dict_base = {"C": 1, "H": 2} or {"C": 1, "H": 1, "O":1} etc
892
+ """
893
+ self.parameters.ms_peak.kendrick_base = kendrick_dict_base
894
+
895
+ for mspeak in self.mspeaks:
896
+ mspeak.change_kendrick_base(kendrick_dict_base)
897
+
898
+ def get_nominal_mz_first_last_indexes(self, nominal_mass):
899
+ """Return the first and last indexes of the MSpeaks objects with the specified nominal mass.
900
+
901
+ Parameters
902
+ ----------
903
+ nominal_mass : int
904
+ The nominal mass to get the indexes for.
905
+
906
+ Returns
907
+ -------
908
+ tuple
909
+ A tuple containing the first and last indexes of the MSpeaks objects with the specified nominal mass.
910
+ """
911
+ if self._dict_nominal_masses_indexes:
912
+ if nominal_mass in self._dict_nominal_masses_indexes.keys():
913
+ return (
914
+ self._dict_nominal_masses_indexes.get(nominal_mass)[0],
915
+ self._dict_nominal_masses_indexes.get(nominal_mass)[1] + 1,
916
+ )
917
+
918
+ else:
919
+ # import warnings
920
+ # uncomment warn to distribution
921
+ # warnings.warn("Nominal mass not found in _dict_nominal_masses_indexes, returning (0, 0) for nominal mass %i"%nominal_mass)
922
+ return (0, 0)
923
+ else:
924
+ raise Exception(
925
+ "run process_mass_spec() function before trying to access the data"
926
+ )
927
+
928
+ def get_masses_count_by_nominal_mass(self):
929
+ """Return a dictionary of the nominal masses and their counts."""
930
+
931
+ dict_nominal_masses_count = {}
932
+
933
+ all_nominal_masses = list(set([i.nominal_mz_exp for i in self.mspeaks]))
934
+
935
+ for nominal_mass in all_nominal_masses:
936
+ if nominal_mass not in dict_nominal_masses_count:
937
+ dict_nominal_masses_count[nominal_mass] = len(
938
+ list(self.get_nominal_mass_indexes(nominal_mass))
939
+ )
940
+
941
+ return dict_nominal_masses_count
942
+
943
+ def datapoints_count_by_nominal_mz(self, mz_overlay=0.1):
944
+ """Return a dictionary of the nominal masses and their counts.
945
+
946
+ Parameters
947
+ ----------
948
+ mz_overlay : float, optional
949
+ The m/z overlay to use for counting. Defaults to 0.1.
950
+
951
+ Returns
952
+ -------
953
+ dict
954
+ A dictionary of the nominal masses and their counts.
955
+ """
956
+ dict_nominal_masses_count = {}
957
+
958
+ all_nominal_masses = list(set([i.nominal_mz_exp for i in self.mspeaks]))
959
+
960
+ for nominal_mass in all_nominal_masses:
961
+ if nominal_mass not in dict_nominal_masses_count:
962
+ min_mz = nominal_mass - mz_overlay
963
+
964
+ max_mz = nominal_mass + 1 + mz_overlay
965
+
966
+ indexes = indexes = where(
967
+ (self.mz_exp_profile > min_mz) & (self.mz_exp_profile < max_mz)
968
+ )
969
+
970
+ dict_nominal_masses_count[nominal_mass] = indexes[0].size
971
+
972
+ return dict_nominal_masses_count
973
+
974
+ def get_nominal_mass_indexes(self, nominal_mass, overlay=0.1):
975
+ """Return the indexes of the MSpeaks objects with the specified nominal mass.
976
+
977
+ Parameters
978
+ ----------
979
+ nominal_mass : int
980
+ The nominal mass to get the indexes for.
981
+ overlay : float, optional
982
+ The m/z overlay to use for counting. Defaults to 0.1.
983
+
984
+ Returns
985
+ -------
986
+ generator
987
+ A generator of the indexes of the MSpeaks objects with the specified nominal mass.
988
+ """
989
+ min_mz_to_look = nominal_mass - overlay
990
+ max_mz_to_look = nominal_mass + 1 + overlay
991
+
992
+ return (
993
+ i
994
+ for i in range(len(self.mspeaks))
995
+ if min_mz_to_look <= self.mspeaks[i].mz_exp <= max_mz_to_look
996
+ )
997
+
998
+ # indexes = (i for i in range(len(self.mspeaks)) if min_mz_to_look <= self.mspeaks[i].mz_exp <= max_mz_to_look)
999
+ # return indexes
1000
+
1001
+ def _set_nominal_masses_start_final_indexes(self):
1002
+ """Set the start and final indexes of the MSpeaks objects for all nominal masses."""
1003
+ dict_nominal_masses_indexes = {}
1004
+
1005
+ all_nominal_masses = set(i.nominal_mz_exp for i in self.mspeaks)
1006
+
1007
+ for nominal_mass in all_nominal_masses:
1008
+ # indexes = self.get_nominal_mass_indexes(nominal_mass)
1009
+ # Convert the iterator to a list to avoid multiple calls
1010
+ indexes = list(self.get_nominal_mass_indexes(nominal_mass))
1011
+
1012
+ # If the list is not empty, find the first and last; otherwise, set None
1013
+ if indexes:
1014
+ first, last = indexes[0], indexes[-1]
1015
+ else:
1016
+ first = last = None
1017
+ # defaultvalue = None
1018
+ # first = last = next(indexes, defaultvalue)
1019
+ # for last in indexes:
1020
+ # pass
1021
+
1022
+ dict_nominal_masses_indexes[nominal_mass] = (first, last)
1023
+
1024
+ self._dict_nominal_masses_indexes = dict_nominal_masses_indexes
1025
+
1026
+ def plot_centroid(self, ax=None, c="g"):
1027
+ """Plot the centroid data of the mass spectrum.
1028
+
1029
+ Parameters
1030
+ ----------
1031
+ ax : matplotlib.axes.Axes, optional
1032
+ The matplotlib axes to plot on. Defaults to None.
1033
+ c : str, optional
1034
+ The color to use for the plot. Defaults to 'g' (green).
1035
+
1036
+ Returns
1037
+ -------
1038
+ matplotlib.axes.Axes
1039
+ The matplotlib axes containing the plot.
1040
+
1041
+ Raises
1042
+ ------
1043
+ Exception
1044
+ If no centroid data is found.
1045
+ """
1046
+
1047
+ import matplotlib.pyplot as plt
1048
+
1049
+ if self._mspeaks:
1050
+ if ax is None:
1051
+ ax = plt.gca()
1052
+
1053
+ markerline_a, stemlines_a, baseline_a = ax.stem(
1054
+ self.mz_exp, self.abundance, linefmt="-", markerfmt=" "
1055
+ )
1056
+
1057
+ plt.setp(markerline_a, "color", c, "linewidth", 2)
1058
+ plt.setp(stemlines_a, "color", c, "linewidth", 2)
1059
+ plt.setp(baseline_a, "color", c, "linewidth", 2)
1060
+
1061
+ ax.set_xlabel("$\t{m/z}$", fontsize=12)
1062
+ ax.set_ylabel("Abundance", fontsize=12)
1063
+ ax.tick_params(axis="both", which="major", labelsize=12)
1064
+
1065
+ ax.axes.spines["top"].set_visible(False)
1066
+ ax.axes.spines["right"].set_visible(False)
1067
+
1068
+ ax.get_yaxis().set_visible(False)
1069
+ ax.spines["left"].set_visible(False)
1070
+
1071
+ else:
1072
+ raise Exception("No centroid data found, please run process_mass_spec")
1073
+
1074
+ return ax
1075
+
1076
+ def plot_profile_and_noise_threshold(self, ax=None, legend=False):
1077
+ """Plot the profile data and noise threshold of the mass spectrum.
1078
+
1079
+ Parameters
1080
+ ----------
1081
+ ax : matplotlib.axes.Axes, optional
1082
+ The matplotlib axes to plot on. Defaults to None.
1083
+ legend : bool, optional
1084
+ Whether to show the legend. Defaults to False.
1085
+
1086
+ Returns
1087
+ -------
1088
+ matplotlib.axes.Axes
1089
+ The matplotlib axes containing the plot.
1090
+
1091
+ Raises
1092
+ ------
1093
+ Exception
1094
+ If no noise threshold is found.
1095
+ """
1096
+ import matplotlib.pyplot as plt
1097
+
1098
+ if self.baseline_noise_std and self.baseline_noise_std:
1099
+ # x = (self.mz_exp_profile.min(), self.mz_exp_profile.max())
1100
+ baseline = (self.baseline_noise, self.baseline_noise)
1101
+
1102
+ # std = self.parameters.mass_spectrum.noise_threshold_min_std
1103
+ # threshold = self.baseline_noise_std + (std * self.baseline_noise_std)
1104
+ x, y = self.get_noise_threshold()
1105
+
1106
+ if ax is None:
1107
+ ax = plt.gca()
1108
+
1109
+ ax.plot(
1110
+ self.mz_exp_profile,
1111
+ self.abundance_profile,
1112
+ color="green",
1113
+ label="Spectrum",
1114
+ )
1115
+ ax.plot(x, (baseline, baseline), color="yellow", label="Baseline Noise")
1116
+ ax.plot(x, y, color="red", label="Noise Threshold")
1117
+
1118
+ ax.set_xlabel("$\t{m/z}$", fontsize=12)
1119
+ ax.set_ylabel("Abundance", fontsize=12)
1120
+ ax.tick_params(axis="both", which="major", labelsize=12)
1121
+
1122
+ ax.axes.spines["top"].set_visible(False)
1123
+ ax.axes.spines["right"].set_visible(False)
1124
+
1125
+ ax.get_yaxis().set_visible(False)
1126
+ ax.spines["left"].set_visible(False)
1127
+ if legend:
1128
+ ax.legend()
1129
+
1130
+ else:
1131
+ raise Exception("Calculate noise threshold first")
1132
+
1133
+ return ax
1134
+
1135
+ def plot_mz_domain_profile(self, color="green", ax=None):
1136
+ """Plot the m/z domain profile of the mass spectrum.
1137
+
1138
+ Parameters
1139
+ ----------
1140
+ color : str, optional
1141
+ The color to use for the plot. Defaults to 'green'.
1142
+ ax : matplotlib.axes.Axes, optional
1143
+ The matplotlib axes to plot on. Defaults to None.
1144
+
1145
+ Returns
1146
+ -------
1147
+ matplotlib.axes.Axes
1148
+ The matplotlib axes containing the plot.
1149
+ """
1150
+
1151
+ import matplotlib.pyplot as plt
1152
+
1153
+ if ax is None:
1154
+ ax = plt.gca()
1155
+ ax.plot(self.mz_exp_profile, self.abundance_profile, color=color)
1156
+ ax.set(xlabel="m/z", ylabel="abundance")
1157
+
1158
+ return ax
1159
+
1160
+ def to_excel(self, out_file_path, write_metadata=True):
1161
+ """Export the mass spectrum to an Excel file.
1162
+
1163
+ Parameters
1164
+ ----------
1165
+ out_file_path : str
1166
+ The path to the Excel file to export to.
1167
+ write_metadata : bool, optional
1168
+ Whether to write the metadata to the Excel file. Defaults to True.
1169
+
1170
+ Returns
1171
+ -------
1172
+ None
1173
+ """
1174
+ from corems.mass_spectrum.output.export import HighResMassSpecExport
1175
+
1176
+ exportMS = HighResMassSpecExport(out_file_path, self)
1177
+ exportMS.to_excel(write_metadata=write_metadata)
1178
+
1179
+ def to_hdf(self, out_file_path):
1180
+ """Export the mass spectrum to an HDF file.
1181
+
1182
+ Parameters
1183
+ ----------
1184
+ out_file_path : str
1185
+ The path to the HDF file to export to.
1186
+
1187
+ Returns
1188
+ -------
1189
+ None
1190
+ """
1191
+ from corems.mass_spectrum.output.export import HighResMassSpecExport
1192
+
1193
+ exportMS = HighResMassSpecExport(out_file_path, self)
1194
+ exportMS.to_hdf()
1195
+
1196
+ def to_csv(self, out_file_path, write_metadata=True):
1197
+ """Export the mass spectrum to a CSV file.
1198
+
1199
+ Parameters
1200
+ ----------
1201
+ out_file_path : str
1202
+ The path to the CSV file to export to.
1203
+ write_metadata : bool, optional
1204
+ Whether to write the metadata to the CSV file. Defaults to True.
1205
+
1206
+ """
1207
+ from corems.mass_spectrum.output.export import HighResMassSpecExport
1208
+
1209
+ exportMS = HighResMassSpecExport(out_file_path, self)
1210
+ exportMS.to_csv(write_metadata=write_metadata)
1211
+
1212
+ def to_pandas(self, out_file_path, write_metadata=True):
1213
+ """Export the mass spectrum to a Pandas dataframe with pkl extension.
1214
+
1215
+ Parameters
1216
+ ----------
1217
+ out_file_path : str
1218
+ The path to the CSV file to export to.
1219
+ write_metadata : bool, optional
1220
+ Whether to write the metadata to the CSV file. Defaults to True.
1221
+
1222
+ """
1223
+ from corems.mass_spectrum.output.export import HighResMassSpecExport
1224
+
1225
+ exportMS = HighResMassSpecExport(out_file_path, self)
1226
+ exportMS.to_pandas(write_metadata=write_metadata)
1227
+
1228
+ def to_dataframe(self, additional_columns=None):
1229
+ """Return the mass spectrum as a Pandas dataframe.
1230
+
1231
+ Parameters
1232
+ ----------
1233
+ additional_columns : list, optional
1234
+ A list of additional columns to include in the dataframe. Defaults to None.
1235
+ Suitable columns are: "Aromaticity Index", "Aromaticity Index (modified)", and "NOSC"
1236
+
1237
+ Returns
1238
+ -------
1239
+ pandas.DataFrame
1240
+ The mass spectrum as a Pandas dataframe.
1241
+ """
1242
+ from corems.mass_spectrum.output.export import HighResMassSpecExport
1243
+
1244
+ exportMS = HighResMassSpecExport(self.filename, self)
1245
+ return exportMS.get_pandas_df(additional_columns=additional_columns)
1246
+
1247
+ def to_json(self):
1248
+ """Return the mass spectrum as a JSON file."""
1249
+ from corems.mass_spectrum.output.export import HighResMassSpecExport
1250
+
1251
+ exportMS = HighResMassSpecExport(self.filename, self)
1252
+ return exportMS.to_json()
1253
+
1254
+ def parameters_json(self):
1255
+ """Return the parameters of the mass spectrum as a JSON string."""
1256
+ from corems.mass_spectrum.output.export import HighResMassSpecExport
1257
+
1258
+ exportMS = HighResMassSpecExport(self.filename, self)
1259
+ return exportMS.parameters_to_json()
1260
+
1261
+ def parameters_toml(self):
1262
+ """Return the parameters of the mass spectrum as a TOML string."""
1263
+ from corems.mass_spectrum.output.export import HighResMassSpecExport
1264
+
1265
+ exportMS = HighResMassSpecExport(self.filename, self)
1266
+ return exportMS.parameters_to_toml()
1267
+
1268
+
1269
+ class MassSpecProfile(MassSpecBase):
1270
+ """A mass spectrum class when the entry point is on profile format
1271
+
1272
+ Notes
1273
+ -----
1274
+ Stores the profile data and instrument settings.
1275
+ Iteration over a list of MSPeaks classes stored at the _mspeaks attributes.
1276
+ _mspeaks is populated under the hood by calling process_mass_spec method.
1277
+ Iteration is null if _mspeaks is empty. Many more attributes and methods inherited from MassSpecBase().
1278
+
1279
+ Parameters
1280
+ ----------
1281
+ data_dict : dict
1282
+ A dictionary containing the profile data.
1283
+ d_params : dict{'str': float, int or str}
1284
+ contains the instrument settings and processing settings
1285
+ auto_process : bool, optional
1286
+ Whether to automatically process the mass spectrum. Defaults to True.
1287
+
1288
+
1289
+ Attributes
1290
+ ----------
1291
+ _abundance : ndarray
1292
+ The abundance values of the mass spectrum.
1293
+ _mz_exp : ndarray
1294
+ The m/z values of the mass spectrum.
1295
+ _mspeaks : list
1296
+ A list of mass peaks.
1297
+
1298
+ Methods
1299
+ ----------
1300
+ * process_mass_spec(). Process the mass spectrum.
1301
+
1302
+ see also: MassSpecBase(), MassSpecfromFreq(), MassSpecCentroid()
1303
+ """
1304
+
1305
+ def __init__(self, data_dict, d_params, auto_process=True):
1306
+ # print(data_dict.keys())
1307
+ super().__init__(
1308
+ data_dict.get(Labels.mz), data_dict.get(Labels.abundance), d_params
1309
+ )
1310
+
1311
+ if auto_process:
1312
+ self.process_mass_spec()
1313
+
1314
+
1315
+ class MassSpecfromFreq(MassSpecBase):
1316
+ """A mass spectrum class when data entry is on frequency domain
1317
+
1318
+ Notes
1319
+ -----
1320
+ - Transform to m/z based on the settings stored at d_params
1321
+ - Stores the profile data and instrument settings
1322
+ - Iteration over a list of MSPeaks classes stored at the _mspeaks attributes
1323
+ - _mspeaks is populated under the hood by calling process_mass_spec method
1324
+ - iteration is null if _mspeaks is empty
1325
+
1326
+ Parameters
1327
+ ----------
1328
+ frequency_domain : list(float)
1329
+ all datapoints in frequency domain in Hz
1330
+ magnitude : frequency_domain : list(float)
1331
+ all datapoints in for magnitude of each frequency datapoint
1332
+ d_params : dict{'str': float, int or str}
1333
+ contains the instrument settings and processing settings
1334
+ auto_process : bool, optional
1335
+ Whether to automatically process the mass spectrum. Defaults to True.
1336
+ keep_profile : bool, optional
1337
+ Whether to keep the profile data. Defaults to True.
1338
+
1339
+ Attributes
1340
+ ----------
1341
+ has_frequency : bool
1342
+ Whether the mass spectrum has frequency data.
1343
+ _frequency_domain : list(float)
1344
+ Frequency domain in Hz
1345
+ label : str
1346
+ store label (Bruker, Midas Transient, see Labels class ). It across distinct processing points
1347
+ _abundance : ndarray
1348
+ The abundance values of the mass spectrum.
1349
+ _mz_exp : ndarray
1350
+ The m/z values of the mass spectrum.
1351
+ _mspeaks : list
1352
+ A list of mass peaks.
1353
+ See Also: all the attributes of MassSpecBase class
1354
+
1355
+ Methods
1356
+ ----------
1357
+ * _set_mz_domain().
1358
+ calculates the m_z based on the setting of d_params
1359
+ * process_mass_spec(). Process the mass spectrum.
1360
+
1361
+ see also: MassSpecBase(), MassSpecProfile(), MassSpecCentroid()
1362
+ """
1363
+
1364
+ def __init__(
1365
+ self,
1366
+ frequency_domain,
1367
+ magnitude,
1368
+ d_params,
1369
+ auto_process=True,
1370
+ keep_profile=True,
1371
+ ):
1372
+ super().__init__(None, magnitude, d_params)
1373
+
1374
+ self._frequency_domain = frequency_domain
1375
+ self.has_frequency = True
1376
+ self._set_mz_domain()
1377
+ self._sort_mz_domain()
1378
+
1379
+ self.magnetron_frequency = None
1380
+ self.magnetron_frequency_sigma = None
1381
+
1382
+ # use this call to automatically process data as the object is created, Setting need to be changed before initiating the class to be in effect
1383
+
1384
+ if auto_process:
1385
+ self.process_mass_spec(keep_profile=keep_profile)
1386
+
1387
+ def _sort_mz_domain(self):
1388
+ """Sort the mass spectrum by m/z values."""
1389
+
1390
+ if self._mz_exp[0] > self._mz_exp[-1]:
1391
+ self._mz_exp = self._mz_exp[::-1]
1392
+ self._abundance = self._abundance[::-1]
1393
+ self._frequency_domain = self._frequency_domain[::-1]
1394
+
1395
+ def _set_mz_domain(self):
1396
+ """Set the m/z domain of the mass spectrum based on the settings of d_params."""
1397
+ if self.label == Labels.bruker_frequency:
1398
+ self._mz_exp = self._f_to_mz_bruker()
1399
+
1400
+ else:
1401
+ self._mz_exp = self._f_to_mz()
1402
+
1403
+ @property
1404
+ def transient_settings(self):
1405
+ """Return the transient settings of the mass spectrum."""
1406
+ return self.parameters.transient
1407
+
1408
+ @transient_settings.setter
1409
+ def transient_settings(self, instance_TransientSetting):
1410
+ self.parameters.transient = instance_TransientSetting
1411
+
1412
+ def calc_magnetron_freq(self, max_magnetron_freq=50, magnetron_freq_bins=300):
1413
+ """Calculates the magnetron frequency of the mass spectrum.
1414
+
1415
+ Parameters
1416
+ ----------
1417
+ max_magnetron_freq : float, optional
1418
+ The maximum magnetron frequency. Defaults to 50.
1419
+ magnetron_freq_bins : int, optional
1420
+ The number of bins to use for the histogram. Defaults to 300.
1421
+
1422
+ Returns
1423
+ -------
1424
+ None
1425
+
1426
+ Notes
1427
+ -----
1428
+ Calculates the magnetron frequency by examining all the picked peaks and the distances between them in the frequency domain.
1429
+ A histogram of those values below the threshold 'max_magnetron_freq' with the 'magnetron_freq_bins' number of bins is calculated.
1430
+ A gaussian model is fit to this histogram - the center value of this (statistically probably) the magnetron frequency.
1431
+ This appears to work well or nOmega datasets, but may not work well for 1x datasets or those with very low magnetron peaks.
1432
+ """
1433
+ ms_df = DataFrame(self.freq_exp(), columns=["Freq"])
1434
+ ms_df["FreqDelta"] = ms_df["Freq"].diff()
1435
+
1436
+ freq_hist = histogram(
1437
+ ms_df[ms_df["FreqDelta"] < max_magnetron_freq]["FreqDelta"],
1438
+ bins=magnetron_freq_bins,
1439
+ )
1440
+
1441
+ mod = GaussianModel()
1442
+ pars = mod.guess(freq_hist[0], x=freq_hist[1][:-1])
1443
+ out = mod.fit(freq_hist[0], pars, x=freq_hist[1][:-1])
1444
+ self.magnetron_frequency = out.best_values["center"]
1445
+ self.magnetron_frequency_sigma = out.best_values["sigma"]
1446
+
1447
+
1448
+ class MassSpecCentroid(MassSpecBase):
1449
+ """A mass spectrum class when the entry point is on centroid format
1450
+
1451
+ Notes
1452
+ -----
1453
+ - Stores the centroid data and instrument settings
1454
+ - Simulate profile data based on Gaussian or Lorentzian peak shape
1455
+ - Iteration over a list of MSPeaks classes stored at the _mspeaks attributes
1456
+ - _mspeaks is populated under the hood by calling process_mass_spec method
1457
+ - iteration is null if _mspeaks is empty
1458
+
1459
+ Parameters
1460
+ ----------
1461
+ data_dict : dict {string: numpy array float64 )
1462
+ contains keys [m/z, Abundance, Resolving Power, S/N]
1463
+ d_params : dict{'str': float, int or str}
1464
+ contains the instrument settings and processing settings
1465
+ auto_process : bool, optional
1466
+ Whether to automatically process the mass spectrum. Defaults to True.
1467
+
1468
+ Attributes
1469
+ ----------
1470
+ label : str
1471
+ store label (Bruker, Midas Transient, see Labels class)
1472
+ _baseline_noise : float
1473
+ store baseline noise
1474
+ _baseline_noise_std : float
1475
+ store baseline noise std
1476
+ _abundance : ndarray
1477
+ The abundance values of the mass spectrum.
1478
+ _mz_exp : ndarray
1479
+ The m/z values of the mass spectrum.
1480
+ _mspeaks : list
1481
+ A list of mass peaks.
1482
+
1483
+
1484
+ Methods
1485
+ ----------
1486
+ * process_mass_spec().
1487
+ Process the mass spectrum. Overriden from MassSpecBase. Populates the _mspeaks list with MSpeaks class using the centroid data.
1488
+ * __simulate_profile__data__().
1489
+ Simulate profile data based on Gaussian or Lorentzian peak shape. Needs theoretical resolving power calculation and define peak shape, intended for plotting and inspection purposes only.
1490
+
1491
+ see also: MassSpecBase(), MassSpecfromFreq(), MassSpecProfile()
1492
+ """
1493
+
1494
+ def __init__(self, data_dict, d_params, auto_process=True):
1495
+ super().__init__([], [], d_params)
1496
+
1497
+ self._set_parameters_objects(d_params)
1498
+
1499
+ if self.label == Labels.thermo_centroid:
1500
+ self._baseline_noise = d_params.get("baseline_noise")
1501
+ self._baseline_noise_std = d_params.get("baseline_noise_std")
1502
+
1503
+ self.is_centroid = True
1504
+ self.data_dict = data_dict
1505
+ self._mz_exp = data_dict[Labels.mz]
1506
+ self._abundance = data_dict[Labels.abundance]
1507
+
1508
+ if auto_process:
1509
+ self.process_mass_spec()
1510
+
1511
+ def __simulate_profile__data__(self, exp_mz_centroid, magnitude_centroid):
1512
+ """Simulate profile data based on Gaussian or Lorentzian peak shape
1513
+
1514
+ Notes
1515
+ -----
1516
+ Needs theoretical resolving power calculation and define peak shape.
1517
+ This is a quick fix to trick a line plot be able to plot as sticks for plotting and inspection purposes only.
1518
+
1519
+ Parameters
1520
+ ----------
1521
+ exp_mz_centroid : list(float)
1522
+ list of m/z values
1523
+ magnitude_centroid : list(float)
1524
+ list of abundance values
1525
+
1526
+
1527
+ Returns
1528
+ -------
1529
+ x : list(float)
1530
+ list of m/z values
1531
+ y : list(float)
1532
+ list of abundance values
1533
+ """
1534
+
1535
+ x, y = [], []
1536
+ for i in range(len(exp_mz_centroid)):
1537
+ x.append(exp_mz_centroid[i] - 0.0000001)
1538
+ x.append(exp_mz_centroid[i])
1539
+ x.append(exp_mz_centroid[i] + 0.0000001)
1540
+ y.append(0)
1541
+ y.append(magnitude_centroid[i])
1542
+ y.append(0)
1543
+ return x, y
1544
+
1545
+ @property
1546
+ def mz_exp_profile(self):
1547
+ """Return the m/z profile of the mass spectrum."""
1548
+ mz_list = []
1549
+ for mz in self.mz_exp:
1550
+ mz_list.append(mz - 0.0000001)
1551
+ mz_list.append(mz)
1552
+ mz_list.append(mz + 0.0000001)
1553
+ return mz_list
1554
+
1555
+ @mz_exp_profile.setter
1556
+ def mz_exp_profile(self, _mz_exp):
1557
+ self._mz_exp = _mz_exp
1558
+
1559
+ @property
1560
+ def abundance_profile(self):
1561
+ """Return the abundance profile of the mass spectrum."""
1562
+ ab_list = []
1563
+ for ab in self.abundance:
1564
+ ab_list.append(0)
1565
+ ab_list.append(ab)
1566
+ ab_list.append(0)
1567
+ return ab_list
1568
+
1569
+ @abundance_profile.setter
1570
+ def abundance_profile(self, abundance):
1571
+ self._abundance = abundance
1572
+
1573
+ @property
1574
+ def tic(self):
1575
+ """Return the total ion current of the mass spectrum."""
1576
+ return sum(self.abundance)
1577
+
1578
+ def process_mass_spec(self):
1579
+ """Process the mass spectrum."""
1580
+ import tqdm
1581
+
1582
+ # overwrite process_mass_spec
1583
+ # mspeak objs are usually added inside the PeaKPicking class
1584
+ # for profile and freq based data
1585
+ data_dict = self.data_dict
1586
+ ion_charge = self.polarity
1587
+
1588
+ # Check if resolving power is present
1589
+ rp_present = True
1590
+ if not data_dict.get(Labels.rp):
1591
+ rp_present = False
1592
+ if rp_present and list(data_dict.get(Labels.rp)) == [None] * len(
1593
+ data_dict.get(Labels.rp)
1594
+ ):
1595
+ rp_present = False
1596
+
1597
+ # Check if s2n is present
1598
+ s2n_present = True
1599
+ if not data_dict.get(Labels.s2n):
1600
+ s2n_present = False
1601
+ if s2n_present and list(data_dict.get(Labels.s2n)) == [None] * len(
1602
+ data_dict.get(Labels.s2n)
1603
+ ):
1604
+ s2n_present = False
1605
+
1606
+ # Warning if no s2n data but noise thresholding is set to signal_noise
1607
+ if (
1608
+ not s2n_present
1609
+ and self.parameters.mass_spectrum.noise_threshold_method == "signal_noise"
1610
+ ):
1611
+ raise Exception("Signal to Noise data is missing for noise thresholding")
1612
+
1613
+ # Pull out abundance data
1614
+ abun = array(data_dict.get(Labels.abundance)).astype(float)
1615
+
1616
+ # Get the threshold for filtering if using minima, relative, or absolute abundance thresholding
1617
+ abundance_threshold, factor = self.get_threshold(abun)
1618
+
1619
+ # Set rp_i and s2n_i to None which will be overwritten if present
1620
+ rp_i, s2n_i = np.nan, np.nan
1621
+ for index, mz in enumerate(data_dict.get(Labels.mz)):
1622
+ if rp_present:
1623
+ if not data_dict.get(Labels.rp)[index]:
1624
+ rp_i = np.nan
1625
+ else:
1626
+ rp_i = float(data_dict.get(Labels.rp)[index])
1627
+ if s2n_present:
1628
+ if not data_dict.get(Labels.s2n)[index]:
1629
+ s2n_i = np.nan
1630
+ else:
1631
+ s2n_i = float(data_dict.get(Labels.s2n)[index])
1632
+
1633
+ # centroid peak does not have start and end peak index pos
1634
+ massspec_indexes = (index, index, index)
1635
+
1636
+ # Add peaks based on the noise thresholding method
1637
+ if (
1638
+ self.parameters.mass_spectrum.noise_threshold_method
1639
+ in ["minima", "relative_abundance", "absolute_abundance"]
1640
+ and abun[index] / factor >= abundance_threshold
1641
+ ):
1642
+ self.add_mspeak(
1643
+ ion_charge,
1644
+ mz,
1645
+ abun[index],
1646
+ rp_i,
1647
+ s2n_i,
1648
+ massspec_indexes,
1649
+ ms_parent=self,
1650
+ )
1651
+ if (
1652
+ self.parameters.mass_spectrum.noise_threshold_method == "signal_noise"
1653
+ and s2n_i >= self.parameters.mass_spectrum.noise_threshold_min_s2n
1654
+ ):
1655
+ self.add_mspeak(
1656
+ ion_charge,
1657
+ mz,
1658
+ abun[index],
1659
+ rp_i,
1660
+ s2n_i,
1661
+ massspec_indexes,
1662
+ ms_parent=self,
1663
+ )
1664
+
1665
+ self.mspeaks = self._mspeaks
1666
+ self._dynamic_range = self.max_abundance / self.min_abundance
1667
+ self._set_nominal_masses_start_final_indexes()
1668
+
1669
+ if self.label != Labels.thermo_centroid:
1670
+ if self.settings.noise_threshold_method == "log":
1671
+ raise Exception("log noise Not tested for centroid data")
1672
+ # self._baseline_noise, self._baseline_noise_std = self.run_log_noise_threshold_calc()
1673
+
1674
+ else:
1675
+ self._baseline_noise, self._baseline_noise_std = (
1676
+ self.run_noise_threshold_calc()
1677
+ )
1678
+
1679
+ del self.data_dict
1680
+
1681
+
1682
+ class MassSpecCentroidLowRes(MassSpecCentroid):
1683
+ """A mass spectrum class when the entry point is on low resolution centroid format
1684
+
1685
+ Notes
1686
+ -----
1687
+ Does not store MSPeak Objs, will iterate over mz, abundance pairs instead
1688
+
1689
+ Parameters
1690
+ ----------
1691
+ data_dict : dict {string: numpy array float64 )
1692
+ contains keys [m/z, Abundance, Resolving Power, S/N]
1693
+ d_params : dict{'str': float, int or str}
1694
+ contains the instrument settings and processing settings
1695
+
1696
+ Attributes
1697
+ ----------
1698
+ _processed_tic : float
1699
+ store processed total ion current
1700
+ _abundance : ndarray
1701
+ The abundance values of the mass spectrum.
1702
+ _mz_exp : ndarray
1703
+ The m/z values of the mass spectrum.
1704
+ """
1705
+
1706
+ def __init__(self, data_dict, d_params):
1707
+ self._set_parameters_objects(d_params)
1708
+ self._mz_exp = array(data_dict.get(Labels.mz))
1709
+ self._abundance = array(data_dict.get(Labels.abundance))
1710
+ self._processed_tic = None
1711
+
1712
+ def __len__(self):
1713
+ return len(self.mz_exp)
1714
+
1715
+ def __getitem__(self, position):
1716
+ return (self.mz_exp[position], self.abundance[position])
1717
+
1718
+ @property
1719
+ def mz_exp(self):
1720
+ """Return the m/z values of the mass spectrum."""
1721
+ return self._mz_exp
1722
+
1723
+ @property
1724
+ def abundance(self):
1725
+ """Return the abundance values of the mass spectrum."""
1726
+ return self._abundance
1727
+
1728
+ @property
1729
+ def processed_tic(self):
1730
+ """Return the processed total ion current of the mass spectrum."""
1731
+ return sum(self._processed_tic)
1732
+
1733
+ @property
1734
+ def tic(self):
1735
+ """Return the total ion current of the mass spectrum."""
1736
+ if self._processed_tic:
1737
+ return self._processed_tic
1738
+ else:
1739
+ return sum(self.abundance)
1740
+
1741
+ @property
1742
+ def mz_abun_tuples(self):
1743
+ """Return the m/z and abundance values of the mass spectrum as a list of tuples."""
1744
+ r = lambda x: (int(round(x[0], 0), int(round(x[1], 0))))
1745
+
1746
+ return [r(i) for i in self]
1747
+
1748
+ @property
1749
+ def mz_abun_dict(self):
1750
+ """Return the m/z and abundance values of the mass spectrum as a dictionary."""
1751
+ r = lambda x: int(round(x, 0))
1752
+
1753
+ return {r(i[0]): r(i[1]) for i in self}