CoreMS 4.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (171) hide show
  1. corems/__init__.py +63 -0
  2. corems/chroma_peak/__init__.py +0 -0
  3. corems/chroma_peak/calc/ChromaPeakCalc.py +480 -0
  4. corems/chroma_peak/calc/__init__.py +0 -0
  5. corems/chroma_peak/calc/subset.py +196 -0
  6. corems/chroma_peak/factory/__init__.py +0 -0
  7. corems/chroma_peak/factory/chroma_peak_classes.py +1178 -0
  8. corems/encapsulation/__init__.py +0 -0
  9. corems/encapsulation/constant.py +1283 -0
  10. corems/encapsulation/factory/__init__.py +0 -0
  11. corems/encapsulation/factory/parameters.py +392 -0
  12. corems/encapsulation/factory/processingSetting.py +1244 -0
  13. corems/encapsulation/input/__init__.py +0 -0
  14. corems/encapsulation/input/parameter_from_json.py +579 -0
  15. corems/encapsulation/output/__init__.py +0 -0
  16. corems/encapsulation/output/parameter_to_dict.py +142 -0
  17. corems/encapsulation/output/parameter_to_json.py +332 -0
  18. corems/mass_spectra/__init__.py +0 -0
  19. corems/mass_spectra/calc/GC_Calc.py +84 -0
  20. corems/mass_spectra/calc/GC_Deconvolution.py +558 -0
  21. corems/mass_spectra/calc/GC_RI_Calibration.py +44 -0
  22. corems/mass_spectra/calc/MZSearch.py +249 -0
  23. corems/mass_spectra/calc/SignalProcessing.py +656 -0
  24. corems/mass_spectra/calc/__init__.py +0 -0
  25. corems/mass_spectra/calc/lc_calc.py +5790 -0
  26. corems/mass_spectra/calc/lc_calc_operations.py +1127 -0
  27. corems/mass_spectra/factory/GC_Class.py +791 -0
  28. corems/mass_spectra/factory/__init__.py +0 -0
  29. corems/mass_spectra/factory/chromat_data.py +51 -0
  30. corems/mass_spectra/factory/lc_class.py +2721 -0
  31. corems/mass_spectra/input/__init__.py +0 -0
  32. corems/mass_spectra/input/andiNetCDF.py +200 -0
  33. corems/mass_spectra/input/boosterHDF5.py +216 -0
  34. corems/mass_spectra/input/brukerSolarix.py +153 -0
  35. corems/mass_spectra/input/brukerSolarix_utils.py +73 -0
  36. corems/mass_spectra/input/corems_hdf5.py +1710 -0
  37. corems/mass_spectra/input/massList.py +133 -0
  38. corems/mass_spectra/input/mzml.py +668 -0
  39. corems/mass_spectra/input/parserbase.py +239 -0
  40. corems/mass_spectra/input/rawFileReader.py +1839 -0
  41. corems/mass_spectra/output/__init__.py +0 -0
  42. corems/mass_spectra/output/export.py +2800 -0
  43. corems/mass_spectrum/__init__.py +0 -0
  44. corems/mass_spectrum/calc/AutoRecalibration.py +237 -0
  45. corems/mass_spectrum/calc/Calibration.py +602 -0
  46. corems/mass_spectrum/calc/CalibrationCalc.py +253 -0
  47. corems/mass_spectrum/calc/KendrickGroup.py +239 -0
  48. corems/mass_spectrum/calc/MassErrorPrediction.py +436 -0
  49. corems/mass_spectrum/calc/MassSpectrumCalc.py +303 -0
  50. corems/mass_spectrum/calc/MeanResolvingPowerFilter.py +212 -0
  51. corems/mass_spectrum/calc/NoiseCalc.py +371 -0
  52. corems/mass_spectrum/calc/NoiseCalc_Bayes.py +93 -0
  53. corems/mass_spectrum/calc/PeakPicking.py +994 -0
  54. corems/mass_spectrum/calc/__init__.py +0 -0
  55. corems/mass_spectrum/factory/MassSpectrumClasses.py +1753 -0
  56. corems/mass_spectrum/factory/__init__.py +0 -0
  57. corems/mass_spectrum/input/__init__.py +0 -0
  58. corems/mass_spectrum/input/baseClass.py +531 -0
  59. corems/mass_spectrum/input/boosterHDF5.py +161 -0
  60. corems/mass_spectrum/input/coremsHDF5.py +475 -0
  61. corems/mass_spectrum/input/massList.py +402 -0
  62. corems/mass_spectrum/input/numpyArray.py +133 -0
  63. corems/mass_spectrum/output/__init__.py +0 -0
  64. corems/mass_spectrum/output/export.py +841 -0
  65. corems/molecular_formula/__init__.py +0 -0
  66. corems/molecular_formula/calc/MolecularFormulaCalc.py +885 -0
  67. corems/molecular_formula/calc/__init__.py +0 -0
  68. corems/molecular_formula/factory/MolecularFormulaFactory.py +895 -0
  69. corems/molecular_formula/factory/__init__.py +0 -0
  70. corems/molecular_formula/input/__init__.py +0 -0
  71. corems/molecular_formula/input/masslist_ref.py +355 -0
  72. corems/molecular_id/__init__.py +0 -0
  73. corems/molecular_id/calc/ClusterFilter.py +251 -0
  74. corems/molecular_id/calc/MolecularFilter.py +122 -0
  75. corems/molecular_id/calc/SpectralSimilarity.py +632 -0
  76. corems/molecular_id/calc/__init__.py +0 -0
  77. corems/molecular_id/calc/math_distance.py +1637 -0
  78. corems/molecular_id/data/FAMES_REF.msp +980 -0
  79. corems/molecular_id/data/PNNLMetV20191015.msp +157267 -0
  80. corems/molecular_id/factory/EI_SQL.py +650 -0
  81. corems/molecular_id/factory/MolecularLookupTable.py +914 -0
  82. corems/molecular_id/factory/__init__.py +0 -0
  83. corems/molecular_id/factory/classification.py +884 -0
  84. corems/molecular_id/factory/lipid_molecular_metadata.py +50 -0
  85. corems/molecular_id/factory/molecularSQL.py +827 -0
  86. corems/molecular_id/factory/spectrum_search_results.py +119 -0
  87. corems/molecular_id/input/__init__.py +0 -0
  88. corems/molecular_id/input/nistMSI.py +148 -0
  89. corems/molecular_id/search/__init__.py +0 -0
  90. corems/molecular_id/search/compoundSearch.py +214 -0
  91. corems/molecular_id/search/database_interfaces.py +1527 -0
  92. corems/molecular_id/search/findOxygenPeaks.py +330 -0
  93. corems/molecular_id/search/lcms_spectral_search.py +348 -0
  94. corems/molecular_id/search/molecularFormulaSearch.py +1117 -0
  95. corems/molecular_id/search/priorityAssignment.py +723 -0
  96. corems/ms_peak/__init__.py +0 -0
  97. corems/ms_peak/calc/MSPeakCalc.py +1010 -0
  98. corems/ms_peak/calc/__init__.py +0 -0
  99. corems/ms_peak/factory/MSPeakClasses.py +542 -0
  100. corems/ms_peak/factory/__init__.py +0 -0
  101. corems/transient/__init__.py +0 -0
  102. corems/transient/calc/TransientCalc.py +362 -0
  103. corems/transient/calc/__init__.py +0 -0
  104. corems/transient/factory/TransientClasses.py +457 -0
  105. corems/transient/factory/__init__.py +0 -0
  106. corems/transient/input/__init__.py +0 -0
  107. corems/transient/input/brukerSolarix.py +461 -0
  108. corems/transient/input/midasDatFile.py +172 -0
  109. corems-4.0.0.dist-info/METADATA +475 -0
  110. corems-4.0.0.dist-info/RECORD +171 -0
  111. corems-4.0.0.dist-info/WHEEL +5 -0
  112. corems-4.0.0.dist-info/licenses/LICENSE +22 -0
  113. corems-4.0.0.dist-info/top_level.txt +4 -0
  114. examples/archive/scripts/CoreMS_tutorial.py +94 -0
  115. examples/archive/scripts/DI HR-MS Halogens Bruker.py +196 -0
  116. examples/archive/scripts/DI HR-MS MassList.py +385 -0
  117. examples/archive/scripts/GC-MS MetabRef.py +213 -0
  118. examples/archive/scripts/GC-MS NetCDF.py +217 -0
  119. examples/archive/scripts/HR-MS Thermo Raw 21T.py +136 -0
  120. examples/archive/scripts/LC-ICPMS_metal_peaks.py +297 -0
  121. examples/archive/scripts/LCMS-Thermo.py +460 -0
  122. examples/archive/scripts/LCMS_isotopes.py +283 -0
  123. examples/archive/scripts/MSParams_example.py +21 -0
  124. examples/archive/scripts/Molecular Formula Data Aggreation.py +84 -0
  125. examples/archive/scripts/Single Mz Search.py +69 -0
  126. examples/test_notebooks.py +145 -0
  127. ext_lib/ChemstationMSFileReader.dll +0 -0
  128. ext_lib/ChemstationMSFileReader.xml +126 -0
  129. ext_lib/RawFileReaderLicense.doc +0 -0
  130. ext_lib/ThermoFisher.CommonCore.BackgroundSubtraction.dll +0 -0
  131. ext_lib/ThermoFisher.CommonCore.BackgroundSubtraction.xml +2307 -0
  132. ext_lib/ThermoFisher.CommonCore.Data.dll +0 -0
  133. ext_lib/ThermoFisher.CommonCore.Data.xml +28974 -0
  134. ext_lib/ThermoFisher.CommonCore.MassPrecisionEstimator.dll +0 -0
  135. ext_lib/ThermoFisher.CommonCore.MassPrecisionEstimator.xml +241 -0
  136. ext_lib/ThermoFisher.CommonCore.RawFileReader.dll +0 -0
  137. ext_lib/ThermoFisher.CommonCore.RawFileReader.xml +31174 -0
  138. ext_lib/__init__.py +0 -0
  139. ext_lib/dotnet/OpenMcdf.Extensions.dll +0 -0
  140. ext_lib/dotnet/OpenMcdf.dll +0 -0
  141. ext_lib/dotnet/OpenMcdf.xml +1154 -0
  142. ext_lib/dotnet/System.IO.FileSystem.AccessControl.dll +0 -0
  143. ext_lib/dotnet/System.IO.FileSystem.AccessControl.xml +506 -0
  144. ext_lib/dotnet/System.Security.AccessControl.dll +0 -0
  145. ext_lib/dotnet/System.Security.AccessControl.xml +2043 -0
  146. ext_lib/dotnet/System.Security.Principal.Windows.dll +0 -0
  147. ext_lib/dotnet/System.Security.Principal.Windows.xml +1011 -0
  148. ext_lib/dotnet/ThermoFisher.CommonCore.BackgroundSubtraction.dll +0 -0
  149. ext_lib/dotnet/ThermoFisher.CommonCore.BackgroundSubtraction.xml +2307 -0
  150. ext_lib/dotnet/ThermoFisher.CommonCore.Data.dll +0 -0
  151. ext_lib/dotnet/ThermoFisher.CommonCore.Data.xml +29148 -0
  152. ext_lib/dotnet/ThermoFisher.CommonCore.MassPrecisionEstimator.dll +0 -0
  153. ext_lib/dotnet/ThermoFisher.CommonCore.MassPrecisionEstimator.xml +241 -0
  154. ext_lib/dotnet/ThermoFisher.CommonCore.RawFileReader.dll +0 -0
  155. ext_lib/dotnet/ThermoFisher.CommonCore.RawFileReader.xml +31492 -0
  156. ext_lib/version +18 -0
  157. support_code/atom_parsers/AtomsDescription.py +359 -0
  158. support_code/atom_parsers/CreateAtomsDescription.py +56 -0
  159. support_code/nmdc/filefinder.py +90 -0
  160. support_code/nmdc/lipidomics/lipidomics_workflow.py +748 -0
  161. support_code/nmdc/lipidomics/manifest_examples.py +49 -0
  162. support_code/nmdc/metabolomics/gcms_workflow.py +158 -0
  163. support_code/nmdc/metabolomics/lcms_metabolomics_targeted_search.py +59 -0
  164. support_code/nmdc/metabolomics/lcms_metabolomics_workflow.py +248 -0
  165. support_code/nmdc/metabolomics/metabolomics_collection.py +628 -0
  166. support_code/nmdc/metadata/dms_api.py +42 -0
  167. support_code/nmdc/nom/archived_scripts/nmdc_metadata_gen.py +288 -0
  168. support_code/nmdc/nom/archived_scripts/nom_grow_workflow.py +209 -0
  169. support_code/nmdc/nom/nom_workflow.py +312 -0
  170. support_code/windows_only_importers/BrukerCompassXtract.py +180 -0
  171. support_code/windows_only_importers/ThermoMSFileReader.py +405 -0
File without changes
@@ -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
+ )