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
|
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
__author__ = "Yuri E. Corilo"
|
|
2
|
+
__date__ = "Feb 12, 2020"
|
|
3
|
+
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from threading import Thread
|
|
6
|
+
# from io import BytesIO
|
|
7
|
+
|
|
8
|
+
from netCDF4 import Dataset
|
|
9
|
+
from s3path import S3Path
|
|
10
|
+
|
|
11
|
+
from corems.encapsulation.constant import Labels
|
|
12
|
+
from corems.encapsulation.factory.parameters import default_parameters
|
|
13
|
+
from corems.mass_spectra.factory.GC_Class import GCMSBase
|
|
14
|
+
from corems.mass_spectrum.factory.MassSpectrumClasses import MassSpecCentroidLowRes
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class ReadAndiNetCDF(Thread):
|
|
18
|
+
"""
|
|
19
|
+
A class for reading AndiNetCDF files and extracting mass spectra data.
|
|
20
|
+
|
|
21
|
+
Parameters
|
|
22
|
+
-----------
|
|
23
|
+
file_location : str or Path
|
|
24
|
+
The location of the AndiNetCDF file.
|
|
25
|
+
analyzer : str, optional
|
|
26
|
+
The type of analyzer used (default is 'Quadruple').
|
|
27
|
+
instrument_label : str, optional
|
|
28
|
+
The label of the instrument (default is 'GCMS-Agilent').
|
|
29
|
+
auto_process : bool, optional
|
|
30
|
+
Whether to automatically process the data (default is True).
|
|
31
|
+
|
|
32
|
+
Attributes
|
|
33
|
+
-----------
|
|
34
|
+
file_location : Path
|
|
35
|
+
The path to the AndiNetCDF file.
|
|
36
|
+
net_cdf_obj : Dataset
|
|
37
|
+
The NetCDF dataset object.
|
|
38
|
+
ionization_type : str
|
|
39
|
+
The ionization type used in the experiment.
|
|
40
|
+
experiment_type : str
|
|
41
|
+
The type of experiment.
|
|
42
|
+
list_scans : range
|
|
43
|
+
The range of scan numbers in the dataset.
|
|
44
|
+
initial_scan_number : int
|
|
45
|
+
The number of the initial scan.
|
|
46
|
+
final_scan_number : int
|
|
47
|
+
The number of the final scan.
|
|
48
|
+
analyzer : str
|
|
49
|
+
The type of analyzer used.
|
|
50
|
+
instrument_label : str
|
|
51
|
+
The label of the instrument.
|
|
52
|
+
gcms : GCMSBase
|
|
53
|
+
The GCMSBase object for storing mass spectra data.
|
|
54
|
+
|
|
55
|
+
Methods
|
|
56
|
+
--------
|
|
57
|
+
* polarity().
|
|
58
|
+
Get the polarity of the ionization.
|
|
59
|
+
* get_mass_spectrum(mz, abun, rp, d_params).
|
|
60
|
+
Add a mass spectrum to the GCMSBase object.
|
|
61
|
+
* run().
|
|
62
|
+
Populate the GCMSBase object with mass spectra data.
|
|
63
|
+
* import_mass_spectra(d_params).
|
|
64
|
+
Import mass spectra data from the AndiNetCDF file.
|
|
65
|
+
* get_gcms_obj().
|
|
66
|
+
Get the GCMSBase object.
|
|
67
|
+
|
|
68
|
+
"""
|
|
69
|
+
|
|
70
|
+
def __init__(
|
|
71
|
+
self,
|
|
72
|
+
file_location: str | Path,
|
|
73
|
+
analyzer="Quadruple",
|
|
74
|
+
instrument_label="GCMS-Agilent",
|
|
75
|
+
auto_process=True,
|
|
76
|
+
):
|
|
77
|
+
Thread.__init__(self)
|
|
78
|
+
|
|
79
|
+
if isinstance(file_location, str):
|
|
80
|
+
self.file_location = Path(file_location)
|
|
81
|
+
else:
|
|
82
|
+
self.file_location = file_location
|
|
83
|
+
|
|
84
|
+
if not self.file_location.exists():
|
|
85
|
+
raise FileNotFoundError("File does not exist at %s", file_location)
|
|
86
|
+
|
|
87
|
+
if isinstance(file_location, S3Path):
|
|
88
|
+
bytes_io = self.file_location.open("rb").read()
|
|
89
|
+
self.net_cdf_obj = Dataset(
|
|
90
|
+
self.file_location.name,
|
|
91
|
+
"r",
|
|
92
|
+
diskless=True,
|
|
93
|
+
memory=bytes_io,
|
|
94
|
+
format="NETCDF3_CLASSIC",
|
|
95
|
+
)
|
|
96
|
+
else:
|
|
97
|
+
self.net_cdf_obj = Dataset(
|
|
98
|
+
self.file_location, "r", format="NETCDF3_CLASSIC"
|
|
99
|
+
)
|
|
100
|
+
|
|
101
|
+
self.ionization_type = self.net_cdf_obj.test_ionization_mode
|
|
102
|
+
self.experiment_type = self.net_cdf_obj.experiment_type
|
|
103
|
+
self.list_scans = range(
|
|
104
|
+
len(self.net_cdf_obj.variables.get("actual_scan_number")[:])
|
|
105
|
+
)
|
|
106
|
+
self.initial_scan_number = self.list_scans[0]
|
|
107
|
+
self.final_scan_number = self.list_scans[-1]
|
|
108
|
+
self.analyzer = analyzer
|
|
109
|
+
self.instrument_label = instrument_label
|
|
110
|
+
self.gcms = GCMSBase(self.file_location, analyzer, instrument_label)
|
|
111
|
+
|
|
112
|
+
@property
|
|
113
|
+
def polarity(self):
|
|
114
|
+
"""
|
|
115
|
+
Get the polarity of the ionization.
|
|
116
|
+
|
|
117
|
+
"""
|
|
118
|
+
polarity = str(self.net_cdf_obj.test_ionization_polarity)
|
|
119
|
+
if polarity == "Positive Polarity":
|
|
120
|
+
return +1
|
|
121
|
+
else:
|
|
122
|
+
return -1
|
|
123
|
+
|
|
124
|
+
def get_mass_spectrum(self, mz, abun, rp, d_params):
|
|
125
|
+
"""
|
|
126
|
+
Add a mass spectrum to the GCMSBase object.
|
|
127
|
+
|
|
128
|
+
Parameters
|
|
129
|
+
-----------
|
|
130
|
+
mz : array-like
|
|
131
|
+
The m/z values of the mass spectrum.
|
|
132
|
+
abun : array-like
|
|
133
|
+
The abundance values of the mass spectrum.
|
|
134
|
+
rp : array-like
|
|
135
|
+
The resolution values of the mass spectrum.
|
|
136
|
+
d_params : dict
|
|
137
|
+
Additional parameters for the mass spectrum.
|
|
138
|
+
|
|
139
|
+
"""
|
|
140
|
+
data_dict = {
|
|
141
|
+
Labels.mz: mz,
|
|
142
|
+
Labels.abundance: abun,
|
|
143
|
+
Labels.rp: rp,
|
|
144
|
+
Labels.s2n: None,
|
|
145
|
+
}
|
|
146
|
+
mass_spec = MassSpecCentroidLowRes(data_dict, d_params)
|
|
147
|
+
self.gcms.add_mass_spectrum(mass_spec)
|
|
148
|
+
|
|
149
|
+
def run(self):
|
|
150
|
+
"""
|
|
151
|
+
Populate the GCMSBase object with mass spectra data.
|
|
152
|
+
"""
|
|
153
|
+
d_parameters = default_parameters(self.file_location)
|
|
154
|
+
self.import_mass_spectra(d_parameters)
|
|
155
|
+
|
|
156
|
+
def import_mass_spectra(self, d_params):
|
|
157
|
+
"""
|
|
158
|
+
Import mass spectra data from the AndiNetCDF file.
|
|
159
|
+
|
|
160
|
+
Parameters
|
|
161
|
+
-----------
|
|
162
|
+
d_params : dict
|
|
163
|
+
Additional parameters for the mass spectra.
|
|
164
|
+
|
|
165
|
+
"""
|
|
166
|
+
ms_datapoints_per_scans = self.net_cdf_obj.variables.get("point_count")[:]
|
|
167
|
+
list_tic = self.net_cdf_obj.variables.get("total_intensity")[:]
|
|
168
|
+
list_rt = self.net_cdf_obj.variables.get("scan_acquisition_time")[:] / 60
|
|
169
|
+
mass_values = self.net_cdf_obj.variables.get("mass_values")[:]
|
|
170
|
+
intensity_values = self.net_cdf_obj.variables.get("intensity_values")[:]
|
|
171
|
+
resolution = self.net_cdf_obj.variables.get("resolution")[:]
|
|
172
|
+
individual_rp = len(mass_values) == len(resolution)
|
|
173
|
+
finish_location = -1
|
|
174
|
+
for scan_index in self.list_scans:
|
|
175
|
+
datapoints = ms_datapoints_per_scans[scan_index]
|
|
176
|
+
finish_location += datapoints
|
|
177
|
+
start_location = finish_location - datapoints + 1
|
|
178
|
+
d_params["rt"] = list_rt[scan_index]
|
|
179
|
+
d_params["scan_number"] = scan_index
|
|
180
|
+
d_params["label"] = Labels.gcms_centroid
|
|
181
|
+
d_params["polarity"] = self.polarity
|
|
182
|
+
d_params["analyzer"] = self.analyzer
|
|
183
|
+
d_params["instrument_label"] = self.instrument_label
|
|
184
|
+
mz = mass_values[start_location:finish_location]
|
|
185
|
+
abun = intensity_values[start_location:finish_location]
|
|
186
|
+
if individual_rp:
|
|
187
|
+
rp = resolution[start_location:finish_location]
|
|
188
|
+
else:
|
|
189
|
+
rp = [resolution[scan_index]] * datapoints
|
|
190
|
+
self.get_mass_spectrum(mz, abun, rp, d_params)
|
|
191
|
+
self.gcms.retention_time = list_rt
|
|
192
|
+
self.gcms.tic = list_tic
|
|
193
|
+
self.gcms.scans_number = self.list_scans
|
|
194
|
+
|
|
195
|
+
def get_gcms_obj(self):
|
|
196
|
+
"""
|
|
197
|
+
Get the GCMSBase object.
|
|
198
|
+
|
|
199
|
+
"""
|
|
200
|
+
return self.gcms
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
__author__ = "Yuri E. Corilo"
|
|
2
|
+
__date__ = "Oct 29, 2019"
|
|
3
|
+
|
|
4
|
+
from threading import Thread
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from io import BytesIO
|
|
7
|
+
|
|
8
|
+
import h5py
|
|
9
|
+
from s3path import S3Path
|
|
10
|
+
|
|
11
|
+
from corems.encapsulation.constant import Labels
|
|
12
|
+
from corems.mass_spectrum.factory.MassSpectrumClasses import MassSpecProfile
|
|
13
|
+
from corems.mass_spectra.factory.lc_class import LCMSBase
|
|
14
|
+
from corems.encapsulation.factory.parameters import default_parameters
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class ReadHDF_BoosterMassSpectra(Thread):
|
|
18
|
+
"""
|
|
19
|
+
Class for reading HDF5 files containing booster mass spectra.
|
|
20
|
+
|
|
21
|
+
Parameters
|
|
22
|
+
----------
|
|
23
|
+
file_location : Path or S3Path
|
|
24
|
+
The full path to the HDF5 file.
|
|
25
|
+
analyzer : str, optional
|
|
26
|
+
The type of analyzer used for the mass spectra. Defaults to "ICR".
|
|
27
|
+
instrument_label : str, optional
|
|
28
|
+
The label of the instrument. Defaults to "21T".
|
|
29
|
+
auto_process : bool, optional
|
|
30
|
+
Whether to automatically process the mass spectra. Defaults to True.
|
|
31
|
+
"""
|
|
32
|
+
|
|
33
|
+
def __init__(
|
|
34
|
+
self,
|
|
35
|
+
file_location: Path | S3Path,
|
|
36
|
+
analyzer="ICR",
|
|
37
|
+
instrument_label="21T",
|
|
38
|
+
auto_process=True,
|
|
39
|
+
):
|
|
40
|
+
"""
|
|
41
|
+
Initialize the ReadHDF_BoosterMassSpectra class.
|
|
42
|
+
|
|
43
|
+
Parameters
|
|
44
|
+
----------
|
|
45
|
+
file_location : Path or S3Path
|
|
46
|
+
The full path to the HDF5 file.
|
|
47
|
+
analyzer : str, optional
|
|
48
|
+
The type of analyzer used for the mass spectra. Defaults to "ICR".
|
|
49
|
+
instrument_label : str, optional
|
|
50
|
+
The label of the instrument. Defaults to "21T".
|
|
51
|
+
auto_process : bool, optional
|
|
52
|
+
Whether to automatically process the mass spectra. Defaults to True.
|
|
53
|
+
"""
|
|
54
|
+
Thread.__init__(self)
|
|
55
|
+
|
|
56
|
+
if isinstance(file_location, str):
|
|
57
|
+
# if obj is a string it defaults to create a Path obj, pass the S3Path if needed
|
|
58
|
+
self.file_location = Path(file_location)
|
|
59
|
+
|
|
60
|
+
self.lcms = LCMSBase(
|
|
61
|
+
file_location, analyzer=analyzer, instrument_label=instrument_label
|
|
62
|
+
)
|
|
63
|
+
|
|
64
|
+
if isinstance(file_location, S3Path):
|
|
65
|
+
data = BytesIO(file_location.open("rb").read())
|
|
66
|
+
else:
|
|
67
|
+
data = file_location
|
|
68
|
+
|
|
69
|
+
self.hdf_obj = h5py.File(data, "r")
|
|
70
|
+
|
|
71
|
+
self.list_scans = sorted([int(i) for i in list(self.hdf_obj.keys())])
|
|
72
|
+
|
|
73
|
+
self.initial_scan_number = self.list_scans[0]
|
|
74
|
+
|
|
75
|
+
self.final_scan_number = self.list_scans[-1]
|
|
76
|
+
|
|
77
|
+
self.file_location = file_location
|
|
78
|
+
|
|
79
|
+
self.auto_process = True
|
|
80
|
+
|
|
81
|
+
self.analyzer = analyzer
|
|
82
|
+
|
|
83
|
+
self.instrument_label = instrument_label
|
|
84
|
+
|
|
85
|
+
def get_polarity(self, file_location: Path | S3Path, scan: int):
|
|
86
|
+
"""
|
|
87
|
+
Get the polarity of a scan.
|
|
88
|
+
|
|
89
|
+
Parameters
|
|
90
|
+
----------
|
|
91
|
+
file_location : Path or S3Path
|
|
92
|
+
The full path to the HDF5 file.
|
|
93
|
+
scan : int
|
|
94
|
+
The scan number.
|
|
95
|
+
|
|
96
|
+
"""
|
|
97
|
+
if isinstance(file_location, S3Path):
|
|
98
|
+
data = BytesIO(file_location.open("rb").read())
|
|
99
|
+
else:
|
|
100
|
+
data = file_location
|
|
101
|
+
|
|
102
|
+
self.h5pydata = h5py.File(data, "r")
|
|
103
|
+
|
|
104
|
+
self.scans = list(self.h5pydata.keys())
|
|
105
|
+
|
|
106
|
+
polarity = self.get_attr_data(scan, "r_h_polarity")
|
|
107
|
+
|
|
108
|
+
if polarity == "negative scan":
|
|
109
|
+
return -1
|
|
110
|
+
else:
|
|
111
|
+
return +1
|
|
112
|
+
|
|
113
|
+
def get_attr_data(self, scan, attr_srt):
|
|
114
|
+
"""
|
|
115
|
+
Get the attribute data of a scan.
|
|
116
|
+
|
|
117
|
+
Parameters
|
|
118
|
+
----------
|
|
119
|
+
scan : int
|
|
120
|
+
The scan number.
|
|
121
|
+
attr_srt : str
|
|
122
|
+
The attribute name.
|
|
123
|
+
|
|
124
|
+
"""
|
|
125
|
+
return self.hdf_obj[str(scan)].attrs[attr_srt]
|
|
126
|
+
|
|
127
|
+
def import_mass_spectra(self, d_params: dict):
|
|
128
|
+
"""
|
|
129
|
+
Import the mass spectra from the HDF5 file.
|
|
130
|
+
|
|
131
|
+
Parameters
|
|
132
|
+
----------
|
|
133
|
+
d_params : dict
|
|
134
|
+
The parameters for importing the mass spectra.
|
|
135
|
+
"""
|
|
136
|
+
list_rt, list_tic = list(), list()
|
|
137
|
+
|
|
138
|
+
for scan_number in self.list_scans:
|
|
139
|
+
d_params["rt"] = list_rt.append(
|
|
140
|
+
self.get_attr_data(scan_number, "r_h_start_time")
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
d_params["scan_number"] = scan_number
|
|
144
|
+
|
|
145
|
+
d_params["label"] = Labels.booster_profile
|
|
146
|
+
|
|
147
|
+
d_params["polarity"] = self.get_polarity(self.file_location, scan_number)
|
|
148
|
+
|
|
149
|
+
d_params["Aterm"] = self.get_attr_data(scan_number, "r_cparams")[0]
|
|
150
|
+
|
|
151
|
+
d_params["Bterm"] = self.get_attr_data(scan_number, "r_cparams")[1]
|
|
152
|
+
|
|
153
|
+
d_params["analyzer"] = self.analyzer
|
|
154
|
+
|
|
155
|
+
d_params["instrument_label"] = self.instrument_label
|
|
156
|
+
|
|
157
|
+
list_rt.append(d_params["rt"])
|
|
158
|
+
|
|
159
|
+
list_tic.append(self.get_attr_data(scan_number, "r_h_tic"))
|
|
160
|
+
|
|
161
|
+
mass_spec = self.get_mass_spectrum(scan_number, d_params)
|
|
162
|
+
|
|
163
|
+
self.lcms.add_mass_spectrum(mass_spec)
|
|
164
|
+
|
|
165
|
+
self.lcms.retention_time = list_rt
|
|
166
|
+
self.lcms.tic = list_tic
|
|
167
|
+
self.lcms.scans_number = self.list_scans
|
|
168
|
+
|
|
169
|
+
def get_mass_spectrum(self, scan: int, d_params: dict):
|
|
170
|
+
"""
|
|
171
|
+
Get the mass spectrum for a scan.
|
|
172
|
+
|
|
173
|
+
Parameters
|
|
174
|
+
----------
|
|
175
|
+
scan : int
|
|
176
|
+
The scan number.
|
|
177
|
+
d_params : dict
|
|
178
|
+
The parameters for creating the mass spectrum.
|
|
179
|
+
|
|
180
|
+
"""
|
|
181
|
+
booster_data = self.hdf_obj[str(scan)]
|
|
182
|
+
|
|
183
|
+
if booster_data.shape[0] != 2:
|
|
184
|
+
raise NotImplementedError(
|
|
185
|
+
"opening transient, needs read raw file here, get bandwidth, create transient class and then the mass spectrum"
|
|
186
|
+
)
|
|
187
|
+
else:
|
|
188
|
+
data_dict = {
|
|
189
|
+
Labels.mz: booster_data[0],
|
|
190
|
+
Labels.abundance: booster_data[1],
|
|
191
|
+
Labels.rp: None,
|
|
192
|
+
Labels.s2n: None,
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
mass_spec = MassSpecProfile(
|
|
196
|
+
data_dict, d_params, auto_process=self.auto_process
|
|
197
|
+
)
|
|
198
|
+
|
|
199
|
+
return mass_spec
|
|
200
|
+
|
|
201
|
+
def run(self):
|
|
202
|
+
"""
|
|
203
|
+
Run the thread to create the LCMS object.
|
|
204
|
+
"""
|
|
205
|
+
d_parameters = default_parameters(self.file_location)
|
|
206
|
+
self.import_mass_spectra(d_parameters)
|
|
207
|
+
|
|
208
|
+
def get_lcms_obj(self):
|
|
209
|
+
"""
|
|
210
|
+
Get the LCMS object.
|
|
211
|
+
|
|
212
|
+
"""
|
|
213
|
+
if len(self.lcms) > 0:
|
|
214
|
+
return self.lcms
|
|
215
|
+
else:
|
|
216
|
+
raise Exception("Returning an empty LCMS class")
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
__author__ = "Yuri E. Corilo"
|
|
2
|
+
__date__ = "Oct 29, 2019"
|
|
3
|
+
|
|
4
|
+
from threading import Thread
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from s3path import S3Path
|
|
7
|
+
|
|
8
|
+
# import h5py
|
|
9
|
+
|
|
10
|
+
# from corems.encapsulation.constant import Labels
|
|
11
|
+
from corems.mass_spectra.factory.lc_class import LCMSBase
|
|
12
|
+
|
|
13
|
+
# from corems.encapsulation.factory.parameters import default_parameters
|
|
14
|
+
from corems.transient.input.brukerSolarix import ReadBrukerSolarix
|
|
15
|
+
|
|
16
|
+
from corems.mass_spectra.input.brukerSolarix_utils import get_scan_attributes
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class ReadBruker_SolarixTransientMassSpectra(Thread):
|
|
20
|
+
"""
|
|
21
|
+
Class for reading Bruker Solarix Transient Mass Spectra.
|
|
22
|
+
|
|
23
|
+
Parameters
|
|
24
|
+
----------
|
|
25
|
+
d_directory_location : str, pathlib.Path, or s3path.S3Path
|
|
26
|
+
Path object from pathlib containing the file location.
|
|
27
|
+
analyzer : str, optional
|
|
28
|
+
Type of analyzer used in the mass spectrometer. Defaults to "ICR".
|
|
29
|
+
instrument_label : str, optional
|
|
30
|
+
Label for the instrument. Defaults to "15T".
|
|
31
|
+
auto_process : bool, optional
|
|
32
|
+
Flag indicating whether to automatically process the mass spectra. Defaults to True.
|
|
33
|
+
keep_profile : bool, optional
|
|
34
|
+
Flag indicating whether to keep the profile data in the mass spectra. Defaults to False.
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
def __init__(
|
|
38
|
+
self,
|
|
39
|
+
d_directory_location: str | Path | S3Path,
|
|
40
|
+
analyzer="ICR",
|
|
41
|
+
instrument_label="15T",
|
|
42
|
+
auto_process=True,
|
|
43
|
+
keep_profile=False,
|
|
44
|
+
):
|
|
45
|
+
Thread.__init__(self)
|
|
46
|
+
|
|
47
|
+
if isinstance(d_directory_location, str):
|
|
48
|
+
# if obj is a string it defaults to create a Path obj, pass the S3Path if needed
|
|
49
|
+
d_directory_location = Path(d_directory_location)
|
|
50
|
+
|
|
51
|
+
if not d_directory_location.exists():
|
|
52
|
+
raise FileNotFoundError("File does not exist: " + str(d_directory_location))
|
|
53
|
+
|
|
54
|
+
self.scan_attr = d_directory_location / "scan.xml"
|
|
55
|
+
self.imaging_info_attr = d_directory_location / "ImagingInfo.xml"
|
|
56
|
+
|
|
57
|
+
if not self.scan_attr.exists():
|
|
58
|
+
raise FileExistsError(
|
|
59
|
+
"%s does not seem to be a valid Solarix Mass Spectra Experiment,\
|
|
60
|
+
maybe an Imaging experiment?\
|
|
61
|
+
please ReadBruker_SolarixTransientImage class for Imaging dataset "
|
|
62
|
+
% d_directory_location
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
self.lcms = LCMSBase(d_directory_location, analyzer, instrument_label)
|
|
66
|
+
|
|
67
|
+
self.auto_process = auto_process
|
|
68
|
+
self.keep_profile = keep_profile
|
|
69
|
+
|
|
70
|
+
def get_scan_attr(self) -> dict:
|
|
71
|
+
"""
|
|
72
|
+
Get the scan attributes from the scan.xml or ImagingInfo.xml file.
|
|
73
|
+
If the scan.xml file exists, it will be used; otherwise, it will look for ImagingInfo.xml.
|
|
74
|
+
If neither file exists, a FileNotFoundError will be raised.
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
TODO: - This function is replicated in the corems.transient.input.brukerSolarix module,
|
|
78
|
+
consider refactoring to avoid duplication.
|
|
79
|
+
|
|
80
|
+
Returns
|
|
81
|
+
-------
|
|
82
|
+
dict
|
|
83
|
+
Dictionary containing the scan number as key and a tuple of retention time and TIC as value.
|
|
84
|
+
"""
|
|
85
|
+
return get_scan_attributes(self.scan_attr, self.imaging_info_attr)
|
|
86
|
+
|
|
87
|
+
def import_mass_spectra(self) -> None:
|
|
88
|
+
"""
|
|
89
|
+
Import the mass spectra from the scan.xml file.
|
|
90
|
+
"""
|
|
91
|
+
dict_scan_rt_tic = self.get_scan_attr()
|
|
92
|
+
|
|
93
|
+
list_rt, list_tic = (
|
|
94
|
+
list(),
|
|
95
|
+
list(),
|
|
96
|
+
)
|
|
97
|
+
|
|
98
|
+
list_scans = sorted(list(dict_scan_rt_tic.keys()))
|
|
99
|
+
|
|
100
|
+
for scan_number in list_scans:
|
|
101
|
+
mass_spec = self.get_mass_spectrum(scan_number)
|
|
102
|
+
|
|
103
|
+
self.lcms.add_mass_spectrum(mass_spec)
|
|
104
|
+
|
|
105
|
+
list_rt.append(dict_scan_rt_tic.get(scan_number)[0])
|
|
106
|
+
|
|
107
|
+
list_tic.append(dict_scan_rt_tic.get(scan_number)[1])
|
|
108
|
+
|
|
109
|
+
self.lcms.retention_time = list_rt
|
|
110
|
+
self.lcms.tic = list_tic
|
|
111
|
+
self.lcms.scans_number = list_scans
|
|
112
|
+
|
|
113
|
+
def get_mass_spectrum(self, scan_number: int):
|
|
114
|
+
"""
|
|
115
|
+
Get the mass spectrum for a given scan number.
|
|
116
|
+
|
|
117
|
+
Parameters
|
|
118
|
+
----------
|
|
119
|
+
scan_number : int
|
|
120
|
+
Scan number.
|
|
121
|
+
|
|
122
|
+
"""
|
|
123
|
+
bruker_reader = ReadBrukerSolarix(self.lcms.file_location)
|
|
124
|
+
|
|
125
|
+
bruker_transient = bruker_reader.get_transient(scan_number)
|
|
126
|
+
|
|
127
|
+
mass_spec = bruker_transient.get_mass_spectrum(
|
|
128
|
+
plot_result=False,
|
|
129
|
+
auto_process=self.auto_process,
|
|
130
|
+
keep_profile=self.keep_profile,
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
return mass_spec
|
|
134
|
+
|
|
135
|
+
def run(self):
|
|
136
|
+
"""
|
|
137
|
+
Run the import_mass_spectra method.
|
|
138
|
+
"""
|
|
139
|
+
self.import_mass_spectra()
|
|
140
|
+
|
|
141
|
+
def get_lcms_obj(self):
|
|
142
|
+
"""
|
|
143
|
+
Get the LCMSBase object.
|
|
144
|
+
|
|
145
|
+
Raises
|
|
146
|
+
------
|
|
147
|
+
Exception
|
|
148
|
+
If the LCMSBase object is empty.
|
|
149
|
+
"""
|
|
150
|
+
if self.lcms:
|
|
151
|
+
return self.lcms
|
|
152
|
+
else:
|
|
153
|
+
raise Exception("Returning an empty LCMSBase class.")
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"""Utility functions for Bruker data processing."""
|
|
2
|
+
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from s3path import S3Path
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def get_scan_attributes(scan_attr, imaging_info_attr) -> dict:
|
|
8
|
+
"""
|
|
9
|
+
Get the scan attributes from the scan.xml or ImagingInfo.xml file.
|
|
10
|
+
|
|
11
|
+
Parameters
|
|
12
|
+
----------
|
|
13
|
+
d_directory_location : str, Path, or S3Path
|
|
14
|
+
Directory containing the XML files
|
|
15
|
+
|
|
16
|
+
Returns
|
|
17
|
+
-------
|
|
18
|
+
dict
|
|
19
|
+
Dictionary containing the scan number as key and a tuple of retention time, TIC,
|
|
20
|
+
and optionally maxpeak and spotname as values.
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
TODO: We need to reformat the dictionary to actually include keys and values so it is self-descriptive.
|
|
24
|
+
TODO: This will break the code, so a new version is needed.
|
|
25
|
+
TODO: Will need to make sure theres tests which capture this change.
|
|
26
|
+
|
|
27
|
+
"""
|
|
28
|
+
from bs4 import BeautifulSoup
|
|
29
|
+
|
|
30
|
+
scan_xml_exists = scan_attr.exists()
|
|
31
|
+
imaging_info_exists = imaging_info_attr.exists()
|
|
32
|
+
|
|
33
|
+
if scan_xml_exists:
|
|
34
|
+
try:
|
|
35
|
+
soup = BeautifulSoup(scan_attr.open(), "xml")
|
|
36
|
+
list_rt = [float(rt.text) for rt in soup.find_all("minutes")]
|
|
37
|
+
list_tic = [float(tic.text) for tic in soup.find_all("tic")]
|
|
38
|
+
list_scan = [int(scan.text) for scan in soup.find_all("count")]
|
|
39
|
+
|
|
40
|
+
# Check if maxpeak exists (more comprehensive version)
|
|
41
|
+
# TODO: Enable this, but it could break code so a new version is needed
|
|
42
|
+
enable_maxpeak = False
|
|
43
|
+
if enable_maxpeak:
|
|
44
|
+
maxpeak_elements = soup.find_all("maxpeak")
|
|
45
|
+
if maxpeak_elements:
|
|
46
|
+
list_maxpeak = [float(maxpeak.text) for maxpeak in maxpeak_elements]
|
|
47
|
+
dict_scan_rt_tic = dict(zip(list_scan, zip(list_rt, list_tic, list_maxpeak)))
|
|
48
|
+
else:
|
|
49
|
+
dict_scan_rt_tic = dict(zip(list_scan, zip(list_rt, list_tic)))
|
|
50
|
+
|
|
51
|
+
dict_scan_rt_tic = dict(zip(list_scan, zip(list_rt, list_tic)))
|
|
52
|
+
|
|
53
|
+
return dict_scan_rt_tic
|
|
54
|
+
except Exception as e:
|
|
55
|
+
raise FileNotFoundError(f"Error reading scan.xml: {e}")
|
|
56
|
+
elif imaging_info_exists:
|
|
57
|
+
try:
|
|
58
|
+
soup = BeautifulSoup(imaging_info_attr.open(), "xml")
|
|
59
|
+
list_rt = [float(rt.text) for rt in soup.find_all("minutes")]
|
|
60
|
+
list_tic = [float(tic.text) for tic in soup.find_all("tic")]
|
|
61
|
+
list_maxpeak = [float(maxpeak.text) for maxpeak in soup.find_all("maxpeak")]
|
|
62
|
+
list_scan = [int(scan.find("count").text) for scan in soup.find_all("scan")]
|
|
63
|
+
list_spotname = [
|
|
64
|
+
scan.find("spotName").text for scan in soup.find_all("scan")
|
|
65
|
+
]
|
|
66
|
+
dict_scan_rt_tic = dict(zip(list_scan, zip(list_rt, list_tic, list_maxpeak, list_spotname)))
|
|
67
|
+
return dict_scan_rt_tic
|
|
68
|
+
except Exception as e:
|
|
69
|
+
raise FileNotFoundError(f"Error reading ImagingInfo.xml: {e}")
|
|
70
|
+
else:
|
|
71
|
+
raise FileNotFoundError(
|
|
72
|
+
"Dataset does not contain a 'scan.xml' or 'ImagingInfo.xml' file."
|
|
73
|
+
)
|