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.
- corems/__init__.py +63 -0
- corems/chroma_peak/__init__.py +0 -0
- corems/chroma_peak/calc/ChromaPeakCalc.py +480 -0
- corems/chroma_peak/calc/__init__.py +0 -0
- corems/chroma_peak/calc/subset.py +196 -0
- corems/chroma_peak/factory/__init__.py +0 -0
- corems/chroma_peak/factory/chroma_peak_classes.py +1178 -0
- corems/encapsulation/__init__.py +0 -0
- corems/encapsulation/constant.py +1283 -0
- corems/encapsulation/factory/__init__.py +0 -0
- corems/encapsulation/factory/parameters.py +392 -0
- corems/encapsulation/factory/processingSetting.py +1244 -0
- corems/encapsulation/input/__init__.py +0 -0
- corems/encapsulation/input/parameter_from_json.py +579 -0
- corems/encapsulation/output/__init__.py +0 -0
- corems/encapsulation/output/parameter_to_dict.py +142 -0
- corems/encapsulation/output/parameter_to_json.py +332 -0
- corems/mass_spectra/__init__.py +0 -0
- corems/mass_spectra/calc/GC_Calc.py +84 -0
- corems/mass_spectra/calc/GC_Deconvolution.py +558 -0
- corems/mass_spectra/calc/GC_RI_Calibration.py +44 -0
- corems/mass_spectra/calc/MZSearch.py +249 -0
- corems/mass_spectra/calc/SignalProcessing.py +656 -0
- corems/mass_spectra/calc/__init__.py +0 -0
- corems/mass_spectra/calc/lc_calc.py +5790 -0
- corems/mass_spectra/calc/lc_calc_operations.py +1127 -0
- corems/mass_spectra/factory/GC_Class.py +791 -0
- corems/mass_spectra/factory/__init__.py +0 -0
- corems/mass_spectra/factory/chromat_data.py +51 -0
- corems/mass_spectra/factory/lc_class.py +2721 -0
- corems/mass_spectra/input/__init__.py +0 -0
- corems/mass_spectra/input/andiNetCDF.py +200 -0
- corems/mass_spectra/input/boosterHDF5.py +216 -0
- corems/mass_spectra/input/brukerSolarix.py +153 -0
- corems/mass_spectra/input/brukerSolarix_utils.py +73 -0
- corems/mass_spectra/input/corems_hdf5.py +1710 -0
- corems/mass_spectra/input/massList.py +133 -0
- corems/mass_spectra/input/mzml.py +668 -0
- corems/mass_spectra/input/parserbase.py +239 -0
- corems/mass_spectra/input/rawFileReader.py +1839 -0
- corems/mass_spectra/output/__init__.py +0 -0
- corems/mass_spectra/output/export.py +2800 -0
- corems/mass_spectrum/__init__.py +0 -0
- corems/mass_spectrum/calc/AutoRecalibration.py +237 -0
- corems/mass_spectrum/calc/Calibration.py +602 -0
- corems/mass_spectrum/calc/CalibrationCalc.py +253 -0
- corems/mass_spectrum/calc/KendrickGroup.py +239 -0
- corems/mass_spectrum/calc/MassErrorPrediction.py +436 -0
- corems/mass_spectrum/calc/MassSpectrumCalc.py +303 -0
- corems/mass_spectrum/calc/MeanResolvingPowerFilter.py +212 -0
- corems/mass_spectrum/calc/NoiseCalc.py +371 -0
- corems/mass_spectrum/calc/NoiseCalc_Bayes.py +93 -0
- corems/mass_spectrum/calc/PeakPicking.py +994 -0
- corems/mass_spectrum/calc/__init__.py +0 -0
- corems/mass_spectrum/factory/MassSpectrumClasses.py +1753 -0
- corems/mass_spectrum/factory/__init__.py +0 -0
- corems/mass_spectrum/input/__init__.py +0 -0
- corems/mass_spectrum/input/baseClass.py +531 -0
- corems/mass_spectrum/input/boosterHDF5.py +161 -0
- corems/mass_spectrum/input/coremsHDF5.py +475 -0
- corems/mass_spectrum/input/massList.py +402 -0
- corems/mass_spectrum/input/numpyArray.py +133 -0
- corems/mass_spectrum/output/__init__.py +0 -0
- corems/mass_spectrum/output/export.py +841 -0
- corems/molecular_formula/__init__.py +0 -0
- corems/molecular_formula/calc/MolecularFormulaCalc.py +885 -0
- corems/molecular_formula/calc/__init__.py +0 -0
- corems/molecular_formula/factory/MolecularFormulaFactory.py +895 -0
- corems/molecular_formula/factory/__init__.py +0 -0
- corems/molecular_formula/input/__init__.py +0 -0
- corems/molecular_formula/input/masslist_ref.py +355 -0
- corems/molecular_id/__init__.py +0 -0
- corems/molecular_id/calc/ClusterFilter.py +251 -0
- corems/molecular_id/calc/MolecularFilter.py +122 -0
- corems/molecular_id/calc/SpectralSimilarity.py +632 -0
- corems/molecular_id/calc/__init__.py +0 -0
- corems/molecular_id/calc/math_distance.py +1637 -0
- corems/molecular_id/data/FAMES_REF.msp +980 -0
- corems/molecular_id/data/PNNLMetV20191015.msp +157267 -0
- corems/molecular_id/factory/EI_SQL.py +650 -0
- corems/molecular_id/factory/MolecularLookupTable.py +914 -0
- corems/molecular_id/factory/__init__.py +0 -0
- corems/molecular_id/factory/classification.py +884 -0
- corems/molecular_id/factory/lipid_molecular_metadata.py +50 -0
- corems/molecular_id/factory/molecularSQL.py +827 -0
- corems/molecular_id/factory/spectrum_search_results.py +119 -0
- corems/molecular_id/input/__init__.py +0 -0
- corems/molecular_id/input/nistMSI.py +148 -0
- corems/molecular_id/search/__init__.py +0 -0
- corems/molecular_id/search/compoundSearch.py +214 -0
- corems/molecular_id/search/database_interfaces.py +1527 -0
- corems/molecular_id/search/findOxygenPeaks.py +330 -0
- corems/molecular_id/search/lcms_spectral_search.py +348 -0
- corems/molecular_id/search/molecularFormulaSearch.py +1117 -0
- corems/molecular_id/search/priorityAssignment.py +723 -0
- corems/ms_peak/__init__.py +0 -0
- corems/ms_peak/calc/MSPeakCalc.py +1010 -0
- corems/ms_peak/calc/__init__.py +0 -0
- corems/ms_peak/factory/MSPeakClasses.py +542 -0
- corems/ms_peak/factory/__init__.py +0 -0
- corems/transient/__init__.py +0 -0
- corems/transient/calc/TransientCalc.py +362 -0
- corems/transient/calc/__init__.py +0 -0
- corems/transient/factory/TransientClasses.py +457 -0
- corems/transient/factory/__init__.py +0 -0
- corems/transient/input/__init__.py +0 -0
- corems/transient/input/brukerSolarix.py +461 -0
- corems/transient/input/midasDatFile.py +172 -0
- corems-4.0.0.dist-info/METADATA +475 -0
- corems-4.0.0.dist-info/RECORD +171 -0
- corems-4.0.0.dist-info/WHEEL +5 -0
- corems-4.0.0.dist-info/licenses/LICENSE +22 -0
- corems-4.0.0.dist-info/top_level.txt +4 -0
- examples/archive/scripts/CoreMS_tutorial.py +94 -0
- examples/archive/scripts/DI HR-MS Halogens Bruker.py +196 -0
- examples/archive/scripts/DI HR-MS MassList.py +385 -0
- examples/archive/scripts/GC-MS MetabRef.py +213 -0
- examples/archive/scripts/GC-MS NetCDF.py +217 -0
- examples/archive/scripts/HR-MS Thermo Raw 21T.py +136 -0
- examples/archive/scripts/LC-ICPMS_metal_peaks.py +297 -0
- examples/archive/scripts/LCMS-Thermo.py +460 -0
- examples/archive/scripts/LCMS_isotopes.py +283 -0
- examples/archive/scripts/MSParams_example.py +21 -0
- examples/archive/scripts/Molecular Formula Data Aggreation.py +84 -0
- examples/archive/scripts/Single Mz Search.py +69 -0
- examples/test_notebooks.py +145 -0
- ext_lib/ChemstationMSFileReader.dll +0 -0
- ext_lib/ChemstationMSFileReader.xml +126 -0
- ext_lib/RawFileReaderLicense.doc +0 -0
- ext_lib/ThermoFisher.CommonCore.BackgroundSubtraction.dll +0 -0
- ext_lib/ThermoFisher.CommonCore.BackgroundSubtraction.xml +2307 -0
- ext_lib/ThermoFisher.CommonCore.Data.dll +0 -0
- ext_lib/ThermoFisher.CommonCore.Data.xml +28974 -0
- ext_lib/ThermoFisher.CommonCore.MassPrecisionEstimator.dll +0 -0
- ext_lib/ThermoFisher.CommonCore.MassPrecisionEstimator.xml +241 -0
- ext_lib/ThermoFisher.CommonCore.RawFileReader.dll +0 -0
- ext_lib/ThermoFisher.CommonCore.RawFileReader.xml +31174 -0
- ext_lib/__init__.py +0 -0
- ext_lib/dotnet/OpenMcdf.Extensions.dll +0 -0
- ext_lib/dotnet/OpenMcdf.dll +0 -0
- ext_lib/dotnet/OpenMcdf.xml +1154 -0
- ext_lib/dotnet/System.IO.FileSystem.AccessControl.dll +0 -0
- ext_lib/dotnet/System.IO.FileSystem.AccessControl.xml +506 -0
- ext_lib/dotnet/System.Security.AccessControl.dll +0 -0
- ext_lib/dotnet/System.Security.AccessControl.xml +2043 -0
- ext_lib/dotnet/System.Security.Principal.Windows.dll +0 -0
- ext_lib/dotnet/System.Security.Principal.Windows.xml +1011 -0
- ext_lib/dotnet/ThermoFisher.CommonCore.BackgroundSubtraction.dll +0 -0
- ext_lib/dotnet/ThermoFisher.CommonCore.BackgroundSubtraction.xml +2307 -0
- ext_lib/dotnet/ThermoFisher.CommonCore.Data.dll +0 -0
- ext_lib/dotnet/ThermoFisher.CommonCore.Data.xml +29148 -0
- ext_lib/dotnet/ThermoFisher.CommonCore.MassPrecisionEstimator.dll +0 -0
- ext_lib/dotnet/ThermoFisher.CommonCore.MassPrecisionEstimator.xml +241 -0
- ext_lib/dotnet/ThermoFisher.CommonCore.RawFileReader.dll +0 -0
- ext_lib/dotnet/ThermoFisher.CommonCore.RawFileReader.xml +31492 -0
- ext_lib/version +18 -0
- support_code/atom_parsers/AtomsDescription.py +359 -0
- support_code/atom_parsers/CreateAtomsDescription.py +56 -0
- support_code/nmdc/filefinder.py +90 -0
- support_code/nmdc/lipidomics/lipidomics_workflow.py +748 -0
- support_code/nmdc/lipidomics/manifest_examples.py +49 -0
- support_code/nmdc/metabolomics/gcms_workflow.py +158 -0
- support_code/nmdc/metabolomics/lcms_metabolomics_targeted_search.py +59 -0
- support_code/nmdc/metabolomics/lcms_metabolomics_workflow.py +248 -0
- support_code/nmdc/metabolomics/metabolomics_collection.py +628 -0
- support_code/nmdc/metadata/dms_api.py +42 -0
- support_code/nmdc/nom/archived_scripts/nmdc_metadata_gen.py +288 -0
- support_code/nmdc/nom/archived_scripts/nom_grow_workflow.py +209 -0
- support_code/nmdc/nom/nom_workflow.py +312 -0
- support_code/windows_only_importers/BrukerCompassXtract.py +180 -0
- support_code/windows_only_importers/ThermoMSFileReader.py +405 -0
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,531 @@
|
|
|
1
|
+
__author__ = "Yuri E. Corilo"
|
|
2
|
+
__date__ = "Nov 11, 2019"
|
|
3
|
+
|
|
4
|
+
from copy import deepcopy
|
|
5
|
+
from io import BytesIO
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
import chardet
|
|
9
|
+
from bs4 import BeautifulSoup
|
|
10
|
+
from pandas import read_csv, read_excel, read_pickle
|
|
11
|
+
from pandas.core.frame import DataFrame
|
|
12
|
+
from s3path import S3Path
|
|
13
|
+
|
|
14
|
+
from corems.encapsulation.constant import Labels
|
|
15
|
+
from corems.encapsulation.factory.parameters import default_parameters
|
|
16
|
+
from corems.encapsulation.factory.processingSetting import DataInputSetting
|
|
17
|
+
from corems.encapsulation.input.parameter_from_json import (
|
|
18
|
+
load_and_set_parameters_class,
|
|
19
|
+
load_and_set_parameters_ms,
|
|
20
|
+
load_and_set_toml_parameters_class,
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class MassListBaseClass:
|
|
25
|
+
"""The MassListBaseClass object reads mass list data types and returns the mass spectrum obj
|
|
26
|
+
|
|
27
|
+
Parameters
|
|
28
|
+
----------
|
|
29
|
+
file_location : Path or S3Path
|
|
30
|
+
Full data path.
|
|
31
|
+
isCentroid : bool, optional
|
|
32
|
+
Determines the mass spectrum data structure. If set to True, it assumes centroid mode. If set to False, it assumes profile mode and attempts to peak pick. Default is True.
|
|
33
|
+
analyzer : str, optional
|
|
34
|
+
The analyzer used for the mass spectrum. Default is 'Unknown'.
|
|
35
|
+
instrument_label : str, optional
|
|
36
|
+
The label of the instrument used for the mass spectrum. Default is 'Unknown'.
|
|
37
|
+
sample_name : str, optional
|
|
38
|
+
The name of the sample. Default is None.
|
|
39
|
+
header_lines : int, optional
|
|
40
|
+
The number of lines to skip in the file, including the column labels line. Default is 0.
|
|
41
|
+
isThermoProfile : bool, optional
|
|
42
|
+
Determines the number of expected columns in the file. If set to True, only m/z and intensity columns are expected. Signal-to-noise ratio (S/N) and resolving power (RP) will be calculated based on the data. Default is False.
|
|
43
|
+
headerless : bool, optional
|
|
44
|
+
If True, assumes that there are no headers present in the file (e.g., a .xy file from Bruker) and assumes two columns: m/z and intensity. Default is False.
|
|
45
|
+
|
|
46
|
+
Attributes
|
|
47
|
+
----------
|
|
48
|
+
parameters : DataInputSetting
|
|
49
|
+
The data input settings for the mass spectrum.
|
|
50
|
+
data_type : str
|
|
51
|
+
The type of data in the file.
|
|
52
|
+
delimiter : str
|
|
53
|
+
The delimiter used to read text-based files.
|
|
54
|
+
|
|
55
|
+
Methods
|
|
56
|
+
-------
|
|
57
|
+
* set_parameter_from_toml(parameters_path). Sets the data input settings from a TOML file.
|
|
58
|
+
* set_parameter_from_json(parameters_path). Sets the data input settings from a JSON file.
|
|
59
|
+
* get_dataframe(). Reads the file and returns the data as a pandas DataFrame.
|
|
60
|
+
* load_settings(mass_spec_obj, output_parameters). Loads the settings for the mass spectrum.
|
|
61
|
+
* get_output_parameters(polarity, scan_index=0). Returns the output parameters for the mass spectrum.
|
|
62
|
+
* clean_data_frame(dataframe). Cleans the data frame by removing columns that are not in the expected columns set.
|
|
63
|
+
|
|
64
|
+
"""
|
|
65
|
+
|
|
66
|
+
def __init__(
|
|
67
|
+
self,
|
|
68
|
+
file_location: Path | S3Path,
|
|
69
|
+
isCentroid: bool = True,
|
|
70
|
+
analyzer: str = "Unknown",
|
|
71
|
+
instrument_label: str = "Unknown",
|
|
72
|
+
sample_name: str = None,
|
|
73
|
+
header_lines: int = 0,
|
|
74
|
+
isThermoProfile: bool = False,
|
|
75
|
+
headerless: bool = False,
|
|
76
|
+
):
|
|
77
|
+
self.file_location = (
|
|
78
|
+
Path(file_location) if isinstance(file_location, str) else file_location
|
|
79
|
+
)
|
|
80
|
+
|
|
81
|
+
if not self.file_location.exists():
|
|
82
|
+
raise FileExistsError("File does not exist: %s" % file_location)
|
|
83
|
+
|
|
84
|
+
# (newline="\n")
|
|
85
|
+
|
|
86
|
+
self.header_lines = header_lines
|
|
87
|
+
|
|
88
|
+
if isThermoProfile:
|
|
89
|
+
self._expected_columns = {Labels.mz, Labels.abundance}
|
|
90
|
+
|
|
91
|
+
else:
|
|
92
|
+
self._expected_columns = {
|
|
93
|
+
Labels.mz,
|
|
94
|
+
Labels.abundance,
|
|
95
|
+
Labels.s2n,
|
|
96
|
+
Labels.rp,
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
self._delimiter = None
|
|
100
|
+
|
|
101
|
+
self.isCentroid = isCentroid
|
|
102
|
+
|
|
103
|
+
self.isThermoProfile = isThermoProfile
|
|
104
|
+
|
|
105
|
+
self.headerless = headerless
|
|
106
|
+
|
|
107
|
+
self._data_type = None
|
|
108
|
+
|
|
109
|
+
self.analyzer = analyzer
|
|
110
|
+
|
|
111
|
+
self.instrument_label = instrument_label
|
|
112
|
+
|
|
113
|
+
self.sample_name = sample_name
|
|
114
|
+
|
|
115
|
+
self._parameters = deepcopy(DataInputSetting())
|
|
116
|
+
|
|
117
|
+
@property
|
|
118
|
+
def parameters(self):
|
|
119
|
+
return self._parameters
|
|
120
|
+
|
|
121
|
+
@parameters.setter
|
|
122
|
+
def parameters(self, instance_DataInputSetting):
|
|
123
|
+
self._parameters = instance_DataInputSetting
|
|
124
|
+
|
|
125
|
+
def set_parameter_from_toml(self, parameters_path):
|
|
126
|
+
self._parameters = load_and_set_toml_parameters_class(
|
|
127
|
+
"DataInput", self.parameters, parameters_path=parameters_path
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
def set_parameter_from_json(self, parameters_path):
|
|
131
|
+
self._parameters = load_and_set_parameters_class(
|
|
132
|
+
"DataInput", self.parameters, parameters_path=parameters_path
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
@property
|
|
136
|
+
def data_type(self):
|
|
137
|
+
return self._data_type
|
|
138
|
+
|
|
139
|
+
@data_type.setter
|
|
140
|
+
def data_type(self, data_type):
|
|
141
|
+
self._data_type = data_type
|
|
142
|
+
|
|
143
|
+
@property
|
|
144
|
+
def delimiter(self):
|
|
145
|
+
return self._delimiter
|
|
146
|
+
|
|
147
|
+
@delimiter.setter
|
|
148
|
+
def delimiter(self, delimiter):
|
|
149
|
+
self._delimiter = delimiter
|
|
150
|
+
|
|
151
|
+
def encoding_detector(self, file_location) -> str:
|
|
152
|
+
"""
|
|
153
|
+
Detects the encoding of a file.
|
|
154
|
+
|
|
155
|
+
Parameters
|
|
156
|
+
--------
|
|
157
|
+
file_location : str
|
|
158
|
+
The location of the file to be analyzed.
|
|
159
|
+
|
|
160
|
+
Returns
|
|
161
|
+
--------
|
|
162
|
+
str
|
|
163
|
+
The detected encoding of the file.
|
|
164
|
+
"""
|
|
165
|
+
|
|
166
|
+
with file_location.open("rb") as rawdata:
|
|
167
|
+
result = chardet.detect(rawdata.read(10000))
|
|
168
|
+
return result["encoding"]
|
|
169
|
+
|
|
170
|
+
def set_data_type(self):
|
|
171
|
+
"""
|
|
172
|
+
Set the data type and delimiter based on the file extension.
|
|
173
|
+
|
|
174
|
+
Raises
|
|
175
|
+
------
|
|
176
|
+
TypeError
|
|
177
|
+
If the data type could not be automatically recognized.
|
|
178
|
+
"""
|
|
179
|
+
if self.file_location.suffix == ".csv":
|
|
180
|
+
self.data_type = "txt"
|
|
181
|
+
self.delimiter = ","
|
|
182
|
+
elif self.file_location.suffix == ".txt":
|
|
183
|
+
self.data_type = "txt"
|
|
184
|
+
self.delimiter = "\t"
|
|
185
|
+
elif self.file_location.suffix == ".tsv":
|
|
186
|
+
self.data_type = "txt"
|
|
187
|
+
self.delimiter = "\t"
|
|
188
|
+
elif self.file_location.suffix == ".xlsx":
|
|
189
|
+
self.data_type = "excel"
|
|
190
|
+
elif self.file_location.suffix == ".ascii":
|
|
191
|
+
self.data_type = "txt"
|
|
192
|
+
self.delimiter = " "
|
|
193
|
+
elif self.file_location.suffix == ".pkl":
|
|
194
|
+
self.data_type = "dataframe"
|
|
195
|
+
elif self.file_location.suffix == ".pks":
|
|
196
|
+
self.data_type = "pks"
|
|
197
|
+
self.delimiter = " "
|
|
198
|
+
self.header_lines = 9
|
|
199
|
+
elif self.file_location.suffix == ".xml":
|
|
200
|
+
self.data_type = "xml"
|
|
201
|
+
# self.delimiter = None
|
|
202
|
+
# self.header_lines = None
|
|
203
|
+
elif self.file_location.suffix == ".xy":
|
|
204
|
+
self.data_type = "txt"
|
|
205
|
+
self.delimiter = " "
|
|
206
|
+
self.header_lines = None
|
|
207
|
+
else:
|
|
208
|
+
raise TypeError(
|
|
209
|
+
"Data type could not be automatically recognized for %s; please set data type and delimiter manually."
|
|
210
|
+
% self.file_location.name
|
|
211
|
+
)
|
|
212
|
+
|
|
213
|
+
def get_dataframe(self) -> DataFrame:
|
|
214
|
+
"""
|
|
215
|
+
Get the data as a pandas DataFrame.
|
|
216
|
+
|
|
217
|
+
Returns
|
|
218
|
+
-------
|
|
219
|
+
pandas.DataFrame
|
|
220
|
+
The data as a pandas DataFrame.
|
|
221
|
+
|
|
222
|
+
Raises
|
|
223
|
+
------
|
|
224
|
+
TypeError
|
|
225
|
+
If the data type is not supported.
|
|
226
|
+
"""
|
|
227
|
+
|
|
228
|
+
if not self.data_type or not self.delimiter:
|
|
229
|
+
self.set_data_type()
|
|
230
|
+
|
|
231
|
+
if isinstance(self.file_location, S3Path):
|
|
232
|
+
data = BytesIO(self.file_location.open("rb").read())
|
|
233
|
+
else:
|
|
234
|
+
data = self.file_location
|
|
235
|
+
|
|
236
|
+
if self.data_type == "txt":
|
|
237
|
+
if self.headerless:
|
|
238
|
+
dataframe = read_csv(
|
|
239
|
+
data,
|
|
240
|
+
skiprows=self.header_lines,
|
|
241
|
+
delimiter=self.delimiter,
|
|
242
|
+
header=None,
|
|
243
|
+
names=["m/z", "I"],
|
|
244
|
+
encoding=self.encoding_detector(self.file_location),
|
|
245
|
+
engine="python",
|
|
246
|
+
)
|
|
247
|
+
else:
|
|
248
|
+
dataframe = read_csv(
|
|
249
|
+
data,
|
|
250
|
+
skiprows=self.header_lines,
|
|
251
|
+
delimiter=self.delimiter,
|
|
252
|
+
encoding=self.encoding_detector(self.file_location),
|
|
253
|
+
engine="python",
|
|
254
|
+
)
|
|
255
|
+
|
|
256
|
+
elif self.data_type == "pks":
|
|
257
|
+
# Predator .pks columns are positional: peak location (m/z), relative
|
|
258
|
+
# peak height (normalized 0-100), absolute abundance, resolving power,
|
|
259
|
+
# frequency, S/N. Use the absolute abundance as the intensity -- the
|
|
260
|
+
# relative peak height is per-spectrum normalized and not comparable
|
|
261
|
+
# across spectra, so it is named so header_translate drops it.
|
|
262
|
+
names = [
|
|
263
|
+
"m/z",
|
|
264
|
+
"Relative Abundance",
|
|
265
|
+
"Abundance",
|
|
266
|
+
"Resolving Power",
|
|
267
|
+
"Frequency",
|
|
268
|
+
"S/N"
|
|
269
|
+
]
|
|
270
|
+
|
|
271
|
+
|
|
272
|
+
clean_data = []
|
|
273
|
+
with self.file_location.open() as maglabfile:
|
|
274
|
+
for i in maglabfile.readlines()[8:-1]:
|
|
275
|
+
clean_data.append(i.split())
|
|
276
|
+
dataframe = DataFrame(clean_data, columns=names)
|
|
277
|
+
|
|
278
|
+
elif self.data_type == "dataframe":
|
|
279
|
+
dataframe = read_pickle(data)
|
|
280
|
+
|
|
281
|
+
elif self.data_type == "excel":
|
|
282
|
+
dataframe = read_excel(data)
|
|
283
|
+
|
|
284
|
+
elif self.data_type == "xml":
|
|
285
|
+
dataframe = self.read_xml_peaks(data)
|
|
286
|
+
|
|
287
|
+
else:
|
|
288
|
+
raise TypeError("Data type %s is not supported" % self.data_type)
|
|
289
|
+
|
|
290
|
+
return dataframe
|
|
291
|
+
|
|
292
|
+
def load_settings(self, mass_spec_obj, output_parameters):
|
|
293
|
+
"""
|
|
294
|
+
#TODO loading output parameters from json file is not functional
|
|
295
|
+
Load settings from a JSON file and apply them to the given mass_spec_obj.
|
|
296
|
+
|
|
297
|
+
Parameters
|
|
298
|
+
----------
|
|
299
|
+
mass_spec_obj : MassSpec
|
|
300
|
+
The mass spectrum object to apply the settings to.
|
|
301
|
+
|
|
302
|
+
"""
|
|
303
|
+
import json
|
|
304
|
+
import warnings
|
|
305
|
+
|
|
306
|
+
settings_file_path = self.file_location.with_suffix(".json")
|
|
307
|
+
|
|
308
|
+
if settings_file_path.exists():
|
|
309
|
+
self._parameters = load_and_set_parameters_class(
|
|
310
|
+
"DataInput", self._parameters, parameters_path=settings_file_path
|
|
311
|
+
)
|
|
312
|
+
|
|
313
|
+
load_and_set_parameters_ms(
|
|
314
|
+
mass_spec_obj, parameters_path=settings_file_path
|
|
315
|
+
)
|
|
316
|
+
|
|
317
|
+
else:
|
|
318
|
+
warnings.warn(
|
|
319
|
+
"auto settings loading is enabled but could not locate the file: %s. Please load the settings manually"
|
|
320
|
+
% settings_file_path
|
|
321
|
+
)
|
|
322
|
+
|
|
323
|
+
# TODO this will load the setting from SettingCoreMS.json
|
|
324
|
+
# coreMSHFD5 overrides this function to import the attrs stored in the h5 file
|
|
325
|
+
# loaded_settings = {}
|
|
326
|
+
# loaded_settings['MoleculaSearch'] = self.get_scan_group_attr_data(scan_index, time_index, 'MoleculaSearchSetting')
|
|
327
|
+
# loaded_settings['MassSpecPeak'] = self.get_scan_group_attr_data(scan_index, time_index, 'MassSpecPeakSetting')
|
|
328
|
+
|
|
329
|
+
# loaded_settings['MassSpectrum'] = self.get_scan_group_attr_data(scan_index, time_index, 'MassSpectrumSetting')
|
|
330
|
+
# loaded_settings['Transient'] = self.get_scan_group_attr_data(scan_index, time_index, 'TransientSetting')
|
|
331
|
+
|
|
332
|
+
def get_output_parameters(self, polarity: int, scan_index: int = 0) -> dict:
|
|
333
|
+
"""
|
|
334
|
+
Get the output parameters for the mass spectrum.
|
|
335
|
+
|
|
336
|
+
Parameters
|
|
337
|
+
----------
|
|
338
|
+
polarity : int
|
|
339
|
+
The polarity of the mass spectrum +1 or -1.
|
|
340
|
+
scan_index : int, optional
|
|
341
|
+
The index of the scan. Default is 0.
|
|
342
|
+
|
|
343
|
+
Returns
|
|
344
|
+
-------
|
|
345
|
+
dict
|
|
346
|
+
A dictionary containing the output parameters.
|
|
347
|
+
|
|
348
|
+
"""
|
|
349
|
+
from copy import deepcopy
|
|
350
|
+
|
|
351
|
+
output_parameters = default_parameters(self.file_location)
|
|
352
|
+
|
|
353
|
+
if self.isCentroid:
|
|
354
|
+
output_parameters["label"] = Labels.corems_centroid
|
|
355
|
+
else:
|
|
356
|
+
output_parameters["label"] = Labels.bruker_profile
|
|
357
|
+
|
|
358
|
+
output_parameters["analyzer"] = self.analyzer
|
|
359
|
+
|
|
360
|
+
output_parameters["instrument_label"] = self.instrument_label
|
|
361
|
+
|
|
362
|
+
output_parameters["sample_name"] = self.sample_name
|
|
363
|
+
|
|
364
|
+
output_parameters["Aterm"] = None
|
|
365
|
+
|
|
366
|
+
output_parameters["Bterm"] = None
|
|
367
|
+
|
|
368
|
+
output_parameters["Cterm"] = None
|
|
369
|
+
|
|
370
|
+
output_parameters["polarity"] = polarity
|
|
371
|
+
|
|
372
|
+
# scan_number and rt will be need to lc ms====
|
|
373
|
+
|
|
374
|
+
output_parameters["mobility_scan"] = 0
|
|
375
|
+
|
|
376
|
+
output_parameters["mobility_rt"] = 0
|
|
377
|
+
|
|
378
|
+
output_parameters["scan_number"] = scan_index
|
|
379
|
+
|
|
380
|
+
output_parameters["rt"] = 0
|
|
381
|
+
|
|
382
|
+
return output_parameters
|
|
383
|
+
|
|
384
|
+
def clean_data_frame(self, dataframe):
|
|
385
|
+
"""
|
|
386
|
+
Clean the input dataframe by removing columns that are not expected.
|
|
387
|
+
|
|
388
|
+
Parameters
|
|
389
|
+
----------
|
|
390
|
+
pandas.DataFrame
|
|
391
|
+
The input dataframe to be cleaned.
|
|
392
|
+
|
|
393
|
+
"""
|
|
394
|
+
|
|
395
|
+
for column_name in dataframe.columns:
|
|
396
|
+
expected_column_name = self.parameters.header_translate.get(column_name)
|
|
397
|
+
if expected_column_name not in self._expected_columns:
|
|
398
|
+
del dataframe[column_name]
|
|
399
|
+
|
|
400
|
+
def check_columns(self, header_labels: list[str]):
|
|
401
|
+
"""
|
|
402
|
+
Check if the given header labels match the expected columns.
|
|
403
|
+
|
|
404
|
+
Parameters
|
|
405
|
+
----------
|
|
406
|
+
header_labels : list
|
|
407
|
+
The header labels to be checked.
|
|
408
|
+
|
|
409
|
+
Raises
|
|
410
|
+
------
|
|
411
|
+
Exception
|
|
412
|
+
If any expected column is not found in the header labels.
|
|
413
|
+
"""
|
|
414
|
+
found_label = set()
|
|
415
|
+
|
|
416
|
+
for label in header_labels:
|
|
417
|
+
if not label in self._expected_columns:
|
|
418
|
+
user_column_name = self.parameters.header_translate.get(label)
|
|
419
|
+
if user_column_name in self._expected_columns:
|
|
420
|
+
found_label.add(user_column_name)
|
|
421
|
+
else:
|
|
422
|
+
found_label.add(label)
|
|
423
|
+
|
|
424
|
+
not_found = self._expected_columns - found_label
|
|
425
|
+
|
|
426
|
+
if len(not_found) > 0:
|
|
427
|
+
raise Exception(
|
|
428
|
+
"Please make sure to include the columns %s" % ", ".join(not_found)
|
|
429
|
+
)
|
|
430
|
+
|
|
431
|
+
def read_xml_peaks(self, data: str) -> DataFrame:
|
|
432
|
+
"""
|
|
433
|
+
Read peaks from a Bruker .xml file and return a pandas DataFrame.
|
|
434
|
+
|
|
435
|
+
Parameters
|
|
436
|
+
----------
|
|
437
|
+
data : str
|
|
438
|
+
The path to the .xml file.
|
|
439
|
+
|
|
440
|
+
Returns
|
|
441
|
+
-------
|
|
442
|
+
pandas.DataFrame
|
|
443
|
+
A DataFrame containing the peak data with columns: 'm/z', 'I', 'Resolving Power', 'Area', 'S/N', 'fwhm'.
|
|
444
|
+
"""
|
|
445
|
+
from numpy import nan
|
|
446
|
+
|
|
447
|
+
with open(data, "r") as file:
|
|
448
|
+
content = file.readlines()
|
|
449
|
+
content = "".join(content)
|
|
450
|
+
bs_content = BeautifulSoup(content, features="xml")
|
|
451
|
+
peaks_xml = bs_content.find_all("pk")
|
|
452
|
+
|
|
453
|
+
# initialise lists of the peak variables
|
|
454
|
+
areas = []
|
|
455
|
+
fwhms = []
|
|
456
|
+
intensities = []
|
|
457
|
+
mzs = []
|
|
458
|
+
res = []
|
|
459
|
+
sn = []
|
|
460
|
+
# iterate through the peaks appending to each list
|
|
461
|
+
for peak in peaks_xml:
|
|
462
|
+
areas.append(
|
|
463
|
+
float(peak.get("a", nan))
|
|
464
|
+
) # Use a default value if key 'a' is missing
|
|
465
|
+
fwhms.append(
|
|
466
|
+
float(peak.get("fwhm", nan))
|
|
467
|
+
) # Use a default value if key 'fwhm' is missing
|
|
468
|
+
intensities.append(
|
|
469
|
+
float(peak.get("i", nan))
|
|
470
|
+
) # Use a default value if key 'i' is missing
|
|
471
|
+
mzs.append(
|
|
472
|
+
float(peak.get("mz", nan))
|
|
473
|
+
) # Use a default value if key 'mz' is missing
|
|
474
|
+
res.append(
|
|
475
|
+
float(peak.get("res", nan))
|
|
476
|
+
) # Use a default value if key 'res' is missing
|
|
477
|
+
sn.append(
|
|
478
|
+
float(peak.get("sn", nan))
|
|
479
|
+
) # Use a default value if key 'sn' is missing
|
|
480
|
+
|
|
481
|
+
# Compile pandas dataframe of these values
|
|
482
|
+
names = ["m/z", "I", "Resolving Power", "Area", "S/N", "fwhm"]
|
|
483
|
+
df = DataFrame(columns=names, dtype=float)
|
|
484
|
+
df["m/z"] = mzs
|
|
485
|
+
df["I"] = intensities
|
|
486
|
+
df["Resolving Power"] = res
|
|
487
|
+
df["Area"] = areas
|
|
488
|
+
df["S/N"] = sn
|
|
489
|
+
df["fwhm"] = fwhms
|
|
490
|
+
return df
|
|
491
|
+
|
|
492
|
+
def get_xml_polarity(self):
|
|
493
|
+
"""
|
|
494
|
+
Get the polarity from an XML peaklist.
|
|
495
|
+
|
|
496
|
+
Returns
|
|
497
|
+
-------
|
|
498
|
+
int
|
|
499
|
+
The polarity of the XML peaklist. Returns -1 for negative polarity, +1 for positive polarity.
|
|
500
|
+
|
|
501
|
+
Raises
|
|
502
|
+
------
|
|
503
|
+
Exception
|
|
504
|
+
If the data type is not XML peaklist in Bruker format or if the polarity is unhandled.
|
|
505
|
+
"""
|
|
506
|
+
|
|
507
|
+
# Check its an actual xml
|
|
508
|
+
if not self.data_type or not self.delimiter:
|
|
509
|
+
self.set_data_type()
|
|
510
|
+
|
|
511
|
+
if isinstance(self.file_location, S3Path):
|
|
512
|
+
# data = self.file_location.open('rb').read()
|
|
513
|
+
data = BytesIO(self.file_location.open("rb").read())
|
|
514
|
+
|
|
515
|
+
else:
|
|
516
|
+
data = self.file_location
|
|
517
|
+
|
|
518
|
+
if self.data_type != "xml":
|
|
519
|
+
raise Exception("This function is only for XML peaklists (Bruker format)")
|
|
520
|
+
|
|
521
|
+
with open(data, "r") as file:
|
|
522
|
+
content = file.readlines()
|
|
523
|
+
content = "".join(content)
|
|
524
|
+
bs_content = BeautifulSoup(content, features="xml")
|
|
525
|
+
polarity = bs_content.find_all("ms_spectrum")[0]["polarity"]
|
|
526
|
+
if polarity == "-":
|
|
527
|
+
return -1
|
|
528
|
+
elif polarity == "+":
|
|
529
|
+
return +1
|
|
530
|
+
else:
|
|
531
|
+
raise Exception("Polarity %s unhandled" % polarity)
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
from io import BytesIO
|
|
2
|
+
|
|
3
|
+
import h5py
|
|
4
|
+
from s3path import S3Path
|
|
5
|
+
|
|
6
|
+
from corems.encapsulation.constant import Labels
|
|
7
|
+
from corems.encapsulation.factory.parameters import default_parameters
|
|
8
|
+
from corems.mass_spectrum.factory.MassSpectrumClasses import MassSpecProfile
|
|
9
|
+
from corems.mass_spectrum.input.baseClass import MassListBaseClass
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class ReadHDF_BoosterMassSpectrum(MassListBaseClass):
|
|
13
|
+
"""The ReadHDF_BoosterMassSpectrum class parses the mass spectrum data from an HDF file and generate a mass spectrum object.
|
|
14
|
+
|
|
15
|
+
Parameters
|
|
16
|
+
----------
|
|
17
|
+
file_location : str
|
|
18
|
+
The path to the HDF file.
|
|
19
|
+
isCentroid : bool, optional
|
|
20
|
+
Specifies whether the mass spectrum is centroided or not. Default is False.
|
|
21
|
+
|
|
22
|
+
Attributes
|
|
23
|
+
----------
|
|
24
|
+
polarity : int
|
|
25
|
+
The polarity of the mass spectrum.
|
|
26
|
+
h5pydata : h5py.File
|
|
27
|
+
The HDF file object.
|
|
28
|
+
scans : list
|
|
29
|
+
The list of scan names in the HDF file.
|
|
30
|
+
|
|
31
|
+
Methods
|
|
32
|
+
-------
|
|
33
|
+
* get_data_profile(mz, abundance, auto_process). Returns a MassSpecProfile object from the given m/z and abundance arrays.
|
|
34
|
+
* get_attr_data(scan, attr_srt). Returns the attribute value for the given scan and attribute name.
|
|
35
|
+
* get_polarity(file_location). Returns the polarity of the mass spectrum.
|
|
36
|
+
* get_mass_spectrum(auto_process). Returns the mass spectrum as a MassSpecProfile object.
|
|
37
|
+
* get_output_parameters(). Returns the default output parameters for the mass spectrum.
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
def __init__(self, file_location, isCentroid=False):
|
|
41
|
+
self.polarity = self.get_polarity(file_location)
|
|
42
|
+
super().__init__(file_location, isCentroid=False)
|
|
43
|
+
|
|
44
|
+
def get_data_profile(self, mz, abundance, auto_process) -> MassSpecProfile:
|
|
45
|
+
"""
|
|
46
|
+
Returns a MassSpecProfile object from the given m/z and abundance arrays.
|
|
47
|
+
|
|
48
|
+
Parameters
|
|
49
|
+
----------
|
|
50
|
+
mz : array_like
|
|
51
|
+
The m/z values.
|
|
52
|
+
abundance : array_like
|
|
53
|
+
The abundance values.
|
|
54
|
+
auto_process : bool
|
|
55
|
+
Specifies whether to automatically process the mass spectrum.
|
|
56
|
+
|
|
57
|
+
Returns
|
|
58
|
+
-------
|
|
59
|
+
MassSpecProfile
|
|
60
|
+
The MassSpecProfile object.
|
|
61
|
+
|
|
62
|
+
"""
|
|
63
|
+
data_dict = {Labels.mz: mz, Labels.abundance: abundance}
|
|
64
|
+
output_parameters = self.get_output_parameters()
|
|
65
|
+
return MassSpecProfile(data_dict, output_parameters, auto_process=auto_process)
|
|
66
|
+
|
|
67
|
+
def get_attr_data(self, scan, attr_srt):
|
|
68
|
+
"""
|
|
69
|
+
Returns the attribute value for the given scan and attribute name.
|
|
70
|
+
|
|
71
|
+
Parameters
|
|
72
|
+
----------
|
|
73
|
+
scan : int
|
|
74
|
+
The scan index.
|
|
75
|
+
attr_srt : str
|
|
76
|
+
The attribute name.
|
|
77
|
+
|
|
78
|
+
Returns
|
|
79
|
+
-------
|
|
80
|
+
object
|
|
81
|
+
The attribute value.
|
|
82
|
+
|
|
83
|
+
"""
|
|
84
|
+
return self.h5pydata[self.scans[scan]].attrs[attr_srt]
|
|
85
|
+
|
|
86
|
+
def get_polarity(self, file_location: str | S3Path) -> int:
|
|
87
|
+
"""
|
|
88
|
+
Returns the polarity of the mass spectrum.
|
|
89
|
+
|
|
90
|
+
Parameters
|
|
91
|
+
----------
|
|
92
|
+
file_location : str
|
|
93
|
+
The path to the HDF file.
|
|
94
|
+
|
|
95
|
+
Returns
|
|
96
|
+
-------
|
|
97
|
+
int
|
|
98
|
+
The polarity of the mass spectrum.
|
|
99
|
+
|
|
100
|
+
"""
|
|
101
|
+
if isinstance(file_location, S3Path):
|
|
102
|
+
data = BytesIO(file_location.open("rb").read())
|
|
103
|
+
else:
|
|
104
|
+
data = file_location
|
|
105
|
+
|
|
106
|
+
self.h5pydata = h5py.File(data, "r")
|
|
107
|
+
self.scans = list(self.h5pydata.keys())
|
|
108
|
+
|
|
109
|
+
polarity = self.get_attr_data(0, "r_h_polarity")
|
|
110
|
+
|
|
111
|
+
if polarity == "negative scan":
|
|
112
|
+
return -1
|
|
113
|
+
else:
|
|
114
|
+
return +1
|
|
115
|
+
|
|
116
|
+
def get_mass_spectrum(self, auto_process=True) -> MassSpecProfile:
|
|
117
|
+
"""
|
|
118
|
+
Returns the mass spectrum as a MassSpecProfile object.
|
|
119
|
+
|
|
120
|
+
Parameters
|
|
121
|
+
----------
|
|
122
|
+
auto_process : bool, optional
|
|
123
|
+
Specifies whether to automatically process the mass spectrum. Default is True.
|
|
124
|
+
|
|
125
|
+
Returns
|
|
126
|
+
-------
|
|
127
|
+
MassSpecProfile
|
|
128
|
+
The MassSpecProfile object.
|
|
129
|
+
|
|
130
|
+
"""
|
|
131
|
+
if len(self.scans) == 1:
|
|
132
|
+
booster_data = self.h5pydata[self.scans[0]]
|
|
133
|
+
|
|
134
|
+
if self.isCentroid:
|
|
135
|
+
raise NotImplementedError
|
|
136
|
+
else:
|
|
137
|
+
mz = booster_data[0]
|
|
138
|
+
abun = booster_data[1]
|
|
139
|
+
return self.get_data_profile(mz, abun, auto_process)
|
|
140
|
+
|
|
141
|
+
def get_output_parameters(self) -> dict:
|
|
142
|
+
"""
|
|
143
|
+
Returns the default output parameters for the mass spectrum.
|
|
144
|
+
|
|
145
|
+
Returns
|
|
146
|
+
-------
|
|
147
|
+
dict
|
|
148
|
+
The default output parameters.
|
|
149
|
+
|
|
150
|
+
"""
|
|
151
|
+
d_params = default_parameters(self.file_location)
|
|
152
|
+
d_params["polarity"] = self.polarity
|
|
153
|
+
d_params["filename_path"] = self.file_location
|
|
154
|
+
d_params["mobility_scan"] = 0
|
|
155
|
+
d_params["mobility_rt"] = 0
|
|
156
|
+
d_params["scan_number"] = 0
|
|
157
|
+
d_params["rt"] = self.get_attr_data(0, "r_h_start_time")
|
|
158
|
+
d_params["label"] = Labels.booster_profile
|
|
159
|
+
d_params["Aterm"] = self.get_attr_data(0, "r_cparams")[0]
|
|
160
|
+
d_params["Bterm"] = self.get_attr_data(0, "r_cparams")[1]
|
|
161
|
+
return d_params
|