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
|
@@ -0,0 +1,656 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
|
|
3
|
+
from scipy.signal import savgol_filter
|
|
4
|
+
from scipy.signal.windows import boxcar
|
|
5
|
+
from scipy import interpolate
|
|
6
|
+
from matplotlib import pyplot as plt
|
|
7
|
+
from numpy import abs
|
|
8
|
+
from numpy import array, polyfit, asarray
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def peak_detector(tic, max_tic): # TODO remove max_tic argument?
|
|
12
|
+
"""
|
|
13
|
+
Find peaks by detecting minima in the first derivative of the data
|
|
14
|
+
Used in LC/GC data processing
|
|
15
|
+
|
|
16
|
+
Parameters
|
|
17
|
+
----------
|
|
18
|
+
tic : array
|
|
19
|
+
array of data points to find the peaks
|
|
20
|
+
max_tic : float
|
|
21
|
+
maximum value of the data points
|
|
22
|
+
|
|
23
|
+
Returns
|
|
24
|
+
-------
|
|
25
|
+
tuple
|
|
26
|
+
tuple of indexes of the start, apex and final points of the peak
|
|
27
|
+
|
|
28
|
+
"""
|
|
29
|
+
dy = derivate(tic)
|
|
30
|
+
|
|
31
|
+
indexes = np.where((np.hstack((dy, 0)) < 0) & (np.hstack((0, dy)) > 0))[0]
|
|
32
|
+
|
|
33
|
+
for index in indexes:
|
|
34
|
+
start_index = find_minima(index, tic, right=False)
|
|
35
|
+
final_index = find_minima(index, tic)
|
|
36
|
+
|
|
37
|
+
yield (start_index, index, final_index)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def find_nearest_scan(data, nodes):
|
|
41
|
+
"""
|
|
42
|
+
Find nearest data point in a list of nodes (derivated data)
|
|
43
|
+
in LC/GC this is 'scan', in MS this is 'm/z' data point
|
|
44
|
+
|
|
45
|
+
Parameters
|
|
46
|
+
----------
|
|
47
|
+
data : float
|
|
48
|
+
data point to find the nearest node
|
|
49
|
+
nodes : array
|
|
50
|
+
array of nodes to search for the nearest node
|
|
51
|
+
|
|
52
|
+
Returns
|
|
53
|
+
-------
|
|
54
|
+
float
|
|
55
|
+
nearest node to the data point
|
|
56
|
+
"""
|
|
57
|
+
|
|
58
|
+
array_data = asarray(nodes)
|
|
59
|
+
|
|
60
|
+
scan_index = (abs(array_data - data)).argmin()
|
|
61
|
+
|
|
62
|
+
return nodes[scan_index]
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def check_corrected_abundance(
|
|
66
|
+
closest_left,
|
|
67
|
+
closest_right,
|
|
68
|
+
apex_index,
|
|
69
|
+
signal,
|
|
70
|
+
max_signal,
|
|
71
|
+
signal_threshold,
|
|
72
|
+
abun_norm,
|
|
73
|
+
):
|
|
74
|
+
"""
|
|
75
|
+
Check the corrected abundance of the peak
|
|
76
|
+
|
|
77
|
+
Parameters
|
|
78
|
+
----------
|
|
79
|
+
closest_left : int
|
|
80
|
+
index of the closest left node
|
|
81
|
+
closest_right : int
|
|
82
|
+
index of the closest right node
|
|
83
|
+
apex_index : int
|
|
84
|
+
index of the apex node
|
|
85
|
+
signal : array
|
|
86
|
+
array of data points to find the peaks
|
|
87
|
+
max_signal : float
|
|
88
|
+
maximum value of the data points
|
|
89
|
+
signal_threshold : float
|
|
90
|
+
threshold for the signal
|
|
91
|
+
abun_norm : float
|
|
92
|
+
abundance normalization factor
|
|
93
|
+
|
|
94
|
+
Returns
|
|
95
|
+
-------
|
|
96
|
+
float
|
|
97
|
+
corrected abundance of the peak
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
"""
|
|
101
|
+
x = [closest_left, closest_right]
|
|
102
|
+
y = [signal[closest_left], signal[closest_right]]
|
|
103
|
+
|
|
104
|
+
pol = polyfit(x, y, 1) # TODO replace with faster method in this file
|
|
105
|
+
|
|
106
|
+
corrected_peak_height = signal[apex_index] - pol(apex_index)
|
|
107
|
+
|
|
108
|
+
if (corrected_peak_height / max_signal) * abun_norm > signal_threshold:
|
|
109
|
+
return corrected_peak_height
|
|
110
|
+
else:
|
|
111
|
+
return False
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
def peak_picking_first_derivative(
|
|
115
|
+
domain,
|
|
116
|
+
signal,
|
|
117
|
+
max_height,
|
|
118
|
+
max_prominence,
|
|
119
|
+
max_signal,
|
|
120
|
+
min_peak_datapoints,
|
|
121
|
+
peak_derivative_threshold,
|
|
122
|
+
signal_threshold=0.1,
|
|
123
|
+
correct_baseline=True,
|
|
124
|
+
plot_res=False,
|
|
125
|
+
abun_norm=100,
|
|
126
|
+
check_abundance=False,
|
|
127
|
+
apex_indexes=[],
|
|
128
|
+
):
|
|
129
|
+
"""
|
|
130
|
+
Find peaks by detecting minima in the first derivative of the data
|
|
131
|
+
Used in LC/GC and MS data processing
|
|
132
|
+
Optional baseline correction, then peak apex detection via 1st derivative.
|
|
133
|
+
For each apex the peak datapoints surrounding the apex are determined.
|
|
134
|
+
Some basic thresholding is applied (signal, number of datapoints, etc).
|
|
135
|
+
|
|
136
|
+
Parameters
|
|
137
|
+
----------
|
|
138
|
+
domain : array
|
|
139
|
+
array of data points to find the peaks
|
|
140
|
+
signal : array
|
|
141
|
+
array of data points to find the peaks
|
|
142
|
+
max_height : float
|
|
143
|
+
maximum height of the peak
|
|
144
|
+
max_prominence : float
|
|
145
|
+
maximum prominence of the peak
|
|
146
|
+
max_signal : float
|
|
147
|
+
maximum signal of the peak
|
|
148
|
+
min_peak_datapoints : int
|
|
149
|
+
minimum number of data points in the peak
|
|
150
|
+
peak_derivative_threshold : float
|
|
151
|
+
threshold for the peak derivative
|
|
152
|
+
signal_threshold : float
|
|
153
|
+
threshold for the signal
|
|
154
|
+
correct_baseline : bool
|
|
155
|
+
flag to correct the baseline
|
|
156
|
+
plot_res : bool
|
|
157
|
+
flag to plot the results
|
|
158
|
+
abun_norm : float
|
|
159
|
+
abundance normalization factor
|
|
160
|
+
check_abundance : bool
|
|
161
|
+
flag to check the abundance
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
Returns
|
|
165
|
+
-------
|
|
166
|
+
tuple
|
|
167
|
+
tuple of indexes of the start, apex and final points of the peak
|
|
168
|
+
|
|
169
|
+
|
|
170
|
+
"""
|
|
171
|
+
if correct_baseline:
|
|
172
|
+
signal = signal - baseline_detector(signal, domain, max_height, max_prominence)
|
|
173
|
+
|
|
174
|
+
domain = np.array(domain)
|
|
175
|
+
signal = np.array(signal)
|
|
176
|
+
|
|
177
|
+
dy = derivate(signal)
|
|
178
|
+
if len(apex_indexes) == 0:
|
|
179
|
+
# Find apexes
|
|
180
|
+
apex_indexes = np.where((np.hstack((dy, 0)) < 0) & (np.hstack((0, dy)) > 0))[0]
|
|
181
|
+
else:
|
|
182
|
+
apex_indexes = np.array(apex_indexes)
|
|
183
|
+
|
|
184
|
+
if apex_indexes.size and apex_indexes is not None:
|
|
185
|
+
apex_indexes = apex_indexes[
|
|
186
|
+
signal[apex_indexes] / max_signal >= signal_threshold
|
|
187
|
+
]
|
|
188
|
+
|
|
189
|
+
signal = signal / max(signal)
|
|
190
|
+
start_peak = []
|
|
191
|
+
end_peak = []
|
|
192
|
+
|
|
193
|
+
pos_dy_threshold = peak_derivative_threshold # max(dy) * peak_derivative_threshold
|
|
194
|
+
neg_dy_threshold = -peak_derivative_threshold # min(dy) * peak_derivative_threshold
|
|
195
|
+
len_dy = len(dy)
|
|
196
|
+
# take apex_index and move left to find start
|
|
197
|
+
for index in apex_indexes:
|
|
198
|
+
# catch for starting position
|
|
199
|
+
|
|
200
|
+
if index == 0:
|
|
201
|
+
index_start = index
|
|
202
|
+
else:
|
|
203
|
+
index_start = index - 1
|
|
204
|
+
|
|
205
|
+
# catch for ending position
|
|
206
|
+
if (index + 1) >= dy.shape[0]:
|
|
207
|
+
index_end = index - 1
|
|
208
|
+
else:
|
|
209
|
+
index_end = index + 1
|
|
210
|
+
|
|
211
|
+
# while dy[index_start-1] > 0 and index_start != 0:
|
|
212
|
+
while dy[index_start - 1] > pos_dy_threshold and index_start > 0:
|
|
213
|
+
index_start = index_start - 1
|
|
214
|
+
start_peak.append(index_start)
|
|
215
|
+
|
|
216
|
+
# while dy[index_end] < 0 and index_end != (len(dy) - 1):
|
|
217
|
+
while dy[index_end] < neg_dy_threshold and index_end != (len_dy - 1):
|
|
218
|
+
index_end = index_end + 1
|
|
219
|
+
end_peak.append(index_end)
|
|
220
|
+
|
|
221
|
+
start_peak = array(start_peak)
|
|
222
|
+
end_peak = array(end_peak)
|
|
223
|
+
|
|
224
|
+
for apex_index in apex_indexes:
|
|
225
|
+
# index_gt_apex = np.where(end_peak >= apex_index)[0]
|
|
226
|
+
# index_lt_apex = np.where(start_peak <= apex_index)[0]
|
|
227
|
+
index_gt_apex = np.arange(np.searchsorted(end_peak, apex_index), len(end_peak))
|
|
228
|
+
index_lt_apex = np.arange(
|
|
229
|
+
0, np.searchsorted(start_peak, apex_index, side="right")
|
|
230
|
+
)
|
|
231
|
+
|
|
232
|
+
if not index_gt_apex.size == 0 and not index_lt_apex.size == 0:
|
|
233
|
+
closest_right = find_nearest_scan(apex_index, end_peak[index_gt_apex])
|
|
234
|
+
closest_left = find_nearest_scan(apex_index, start_peak[index_lt_apex])
|
|
235
|
+
if check_abundance:
|
|
236
|
+
corrected_peak_height = check_corrected_abundance(
|
|
237
|
+
closest_left,
|
|
238
|
+
closest_right,
|
|
239
|
+
apex_index,
|
|
240
|
+
signal,
|
|
241
|
+
max_signal,
|
|
242
|
+
signal_threshold,
|
|
243
|
+
abun_norm,
|
|
244
|
+
)
|
|
245
|
+
else:
|
|
246
|
+
corrected_peak_height = signal[apex_index]
|
|
247
|
+
|
|
248
|
+
if (closest_right - closest_left) >= min_peak_datapoints:
|
|
249
|
+
if plot_res:
|
|
250
|
+
plt.plot(
|
|
251
|
+
domain[closest_left : closest_right + 1],
|
|
252
|
+
dy[closest_left : closest_right + 1],
|
|
253
|
+
c="red",
|
|
254
|
+
)
|
|
255
|
+
plt.plot(
|
|
256
|
+
domain[closest_left : closest_right + 1],
|
|
257
|
+
signal[closest_left : closest_right + 1],
|
|
258
|
+
c="black",
|
|
259
|
+
)
|
|
260
|
+
plt.title(str((corrected_peak_height / max_signal) * 100))
|
|
261
|
+
plt.show()
|
|
262
|
+
|
|
263
|
+
yield (closest_left, apex_index, closest_right)
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
def find_minima(index, tic, right=True):
|
|
267
|
+
"""
|
|
268
|
+
Find the index of the local minima in the given time-of-flight (TOF) intensity array.
|
|
269
|
+
|
|
270
|
+
Parameters:
|
|
271
|
+
-----------
|
|
272
|
+
index: int
|
|
273
|
+
The starting index to search for the minima.
|
|
274
|
+
tic: list
|
|
275
|
+
TIC data points
|
|
276
|
+
right : bool, optional
|
|
277
|
+
Determines the direction of the search. If True, search to the right of the index. If False, search to the left of the index. Default is True.
|
|
278
|
+
|
|
279
|
+
Returns:
|
|
280
|
+
--------
|
|
281
|
+
int
|
|
282
|
+
The index of the local minima in the TIC array.
|
|
283
|
+
"""
|
|
284
|
+
|
|
285
|
+
j = index
|
|
286
|
+
# apex_abundance = tic[index]
|
|
287
|
+
tic_len = len(tic)
|
|
288
|
+
|
|
289
|
+
if right:
|
|
290
|
+
minima = tic[j] >= tic[j + 1]
|
|
291
|
+
else:
|
|
292
|
+
minima = tic[j] >= tic[j - 1]
|
|
293
|
+
|
|
294
|
+
while minima:
|
|
295
|
+
if j == 1 or j == tic_len - 2:
|
|
296
|
+
break
|
|
297
|
+
|
|
298
|
+
if right:
|
|
299
|
+
j += 1
|
|
300
|
+
|
|
301
|
+
minima = tic[j] >= tic[j + 1]
|
|
302
|
+
|
|
303
|
+
else:
|
|
304
|
+
j -= 1
|
|
305
|
+
minima = tic[j] >= tic[j - 1]
|
|
306
|
+
|
|
307
|
+
if right:
|
|
308
|
+
return j
|
|
309
|
+
else:
|
|
310
|
+
return j
|
|
311
|
+
|
|
312
|
+
|
|
313
|
+
def derivate(data_array):
|
|
314
|
+
"""
|
|
315
|
+
Calculate derivative of the data points.
|
|
316
|
+
Replaces nan with infinity
|
|
317
|
+
|
|
318
|
+
Parameters
|
|
319
|
+
----------
|
|
320
|
+
data_array : array
|
|
321
|
+
array of data points
|
|
322
|
+
|
|
323
|
+
Returns
|
|
324
|
+
-------
|
|
325
|
+
array
|
|
326
|
+
array of the derivative of the data points
|
|
327
|
+
"""
|
|
328
|
+
data_array = np.array(data_array)
|
|
329
|
+
|
|
330
|
+
dy = data_array[1:] - data_array[:-1]
|
|
331
|
+
|
|
332
|
+
# replaces nan for infinity
|
|
333
|
+
indices_nan = np.where(np.isnan(data_array))[0]
|
|
334
|
+
|
|
335
|
+
if indices_nan.size:
|
|
336
|
+
data_array[indices_nan] = np.inf
|
|
337
|
+
dy[np.where(np.isnan(dy))[0]] = np.inf
|
|
338
|
+
|
|
339
|
+
return dy
|
|
340
|
+
|
|
341
|
+
|
|
342
|
+
def minima_detector(tic, max_tic, peak_height_max_percent, peak_max_prominence_percent):
|
|
343
|
+
"""
|
|
344
|
+
Minima detector for the TIC data points.
|
|
345
|
+
|
|
346
|
+
Parameters
|
|
347
|
+
----------
|
|
348
|
+
tic : array
|
|
349
|
+
array of data points to find the peaks
|
|
350
|
+
max_tic : float
|
|
351
|
+
maximum value of the data points
|
|
352
|
+
peak_height_max_percent : float
|
|
353
|
+
maximum height of the peak
|
|
354
|
+
peak_max_prominence_percent : float
|
|
355
|
+
maximum prominence of the peak
|
|
356
|
+
|
|
357
|
+
Returns
|
|
358
|
+
-------
|
|
359
|
+
generator
|
|
360
|
+
generator of the indexes of the minima in the TIC array
|
|
361
|
+
|
|
362
|
+
"""
|
|
363
|
+
peak_height_diff = lambda hi, li: ((tic[hi] - tic[li]) / max_tic) * 100
|
|
364
|
+
|
|
365
|
+
for start_index, index, final_index in peak_detector(tic, max_tic):
|
|
366
|
+
# abundance max threshold
|
|
367
|
+
if (tic[index] / max_tic) * 100 < peak_height_max_percent:
|
|
368
|
+
# calculates prominence and filter
|
|
369
|
+
if (
|
|
370
|
+
peak_height_diff(index, start_index)
|
|
371
|
+
and peak_height_diff(index, final_index) < peak_max_prominence_percent
|
|
372
|
+
):
|
|
373
|
+
yield from (start_index, final_index)
|
|
374
|
+
|
|
375
|
+
|
|
376
|
+
def baseline_detector(
|
|
377
|
+
tic, rt, peak_height_max_percent, peak_max_prominence_percent, do_interpolation=True
|
|
378
|
+
):
|
|
379
|
+
"""
|
|
380
|
+
Baseline detector for the TIC data points.
|
|
381
|
+
For LC/GC data processing
|
|
382
|
+
|
|
383
|
+
Parameters
|
|
384
|
+
----------
|
|
385
|
+
tic : array
|
|
386
|
+
array of data points to find the peaks
|
|
387
|
+
rt : array
|
|
388
|
+
array of retention time data points
|
|
389
|
+
peak_height_max_percent : float
|
|
390
|
+
maximum height of the peak
|
|
391
|
+
peak_max_prominence_percent : float
|
|
392
|
+
maximum prominence of the peak
|
|
393
|
+
do_interpolation : bool, optional
|
|
394
|
+
flag to interpolate the data points. Default is True
|
|
395
|
+
|
|
396
|
+
Returns
|
|
397
|
+
-------
|
|
398
|
+
array
|
|
399
|
+
array of the baseline corrected data points
|
|
400
|
+
|
|
401
|
+
"""
|
|
402
|
+
rt = np.array(rt)
|
|
403
|
+
|
|
404
|
+
max_tic = max(tic)
|
|
405
|
+
|
|
406
|
+
indexes = sorted(
|
|
407
|
+
list(
|
|
408
|
+
set(
|
|
409
|
+
i
|
|
410
|
+
for i in minima_detector(
|
|
411
|
+
tic, max_tic, peak_height_max_percent, peak_max_prominence_percent
|
|
412
|
+
)
|
|
413
|
+
)
|
|
414
|
+
)
|
|
415
|
+
)
|
|
416
|
+
|
|
417
|
+
y = -tic
|
|
418
|
+
|
|
419
|
+
x1 = rt[indexes]
|
|
420
|
+
|
|
421
|
+
y1 = y[indexes]
|
|
422
|
+
|
|
423
|
+
if len(x1) <= 5:
|
|
424
|
+
return tic
|
|
425
|
+
|
|
426
|
+
if not do_interpolation:
|
|
427
|
+
y0 = np.zeros(tic.shape)
|
|
428
|
+
y0[indexes] = y[indexes]
|
|
429
|
+
|
|
430
|
+
return y0
|
|
431
|
+
|
|
432
|
+
else:
|
|
433
|
+
f1 = interpolate.interp1d(x1, y1, kind="quadratic", fill_value="extrapolate")
|
|
434
|
+
|
|
435
|
+
ynew1 = f1(list(rt))
|
|
436
|
+
|
|
437
|
+
# from matplotlib import pyplot as plt
|
|
438
|
+
# if self.deconv_rt_list and self.deconv_mz == 51:
|
|
439
|
+
|
|
440
|
+
# plt.plot(rt, tic-(-1* ynew1), color='green')
|
|
441
|
+
|
|
442
|
+
# plt.plot(rt, -1* ynew1, c='black')
|
|
443
|
+
|
|
444
|
+
# s = self.smooth(s, 10, 'blackman')
|
|
445
|
+
|
|
446
|
+
# plt.plot(self.retention_time, -s)
|
|
447
|
+
|
|
448
|
+
# plt.show()
|
|
449
|
+
|
|
450
|
+
return -1 * ynew1
|
|
451
|
+
|
|
452
|
+
|
|
453
|
+
def peak_detector_generator(
|
|
454
|
+
tic, stds, method, rt, max_height, min_height, max_prominence, min_datapoints
|
|
455
|
+
):
|
|
456
|
+
"""
|
|
457
|
+
Peak detector generator for the TIC data points.
|
|
458
|
+
|
|
459
|
+
Parameters
|
|
460
|
+
----------
|
|
461
|
+
tic : array
|
|
462
|
+
array of data points to find the peaks
|
|
463
|
+
stds : float
|
|
464
|
+
standard deviation
|
|
465
|
+
method : str
|
|
466
|
+
method to detect the peaks
|
|
467
|
+
Available methods: 'manual_relative_abundance', 'auto_relative_abundance', 'second_derivative'
|
|
468
|
+
rt : array
|
|
469
|
+
array of retention time data points
|
|
470
|
+
max_height : float
|
|
471
|
+
maximum height of the peak
|
|
472
|
+
min_height : float
|
|
473
|
+
minimum height of the peak
|
|
474
|
+
max_prominence : float
|
|
475
|
+
maximum prominence of the peak
|
|
476
|
+
min_datapoints : int
|
|
477
|
+
minimum number of data points in the peak
|
|
478
|
+
|
|
479
|
+
Returns
|
|
480
|
+
-------
|
|
481
|
+
generator
|
|
482
|
+
generator of the indexes of the peaks in the TIC array
|
|
483
|
+
|
|
484
|
+
"""
|
|
485
|
+
max_tic = max(tic)
|
|
486
|
+
|
|
487
|
+
if method == "manual_relative_abundance":
|
|
488
|
+
tic = tic - baseline_detector(tic, rt, max_height, max_prominence)
|
|
489
|
+
|
|
490
|
+
norm_tic = (tic / max_tic) * 100
|
|
491
|
+
|
|
492
|
+
remove_indexes = np.where(norm_tic < min_height)[0]
|
|
493
|
+
|
|
494
|
+
# if self.deconv_rt_list and self.deconv_mz == 51:
|
|
495
|
+
# plt.plot(self.deconv_rt_list, tic, label=self.deconv_mz)
|
|
496
|
+
|
|
497
|
+
elif method == "auto_relative_abundance":
|
|
498
|
+
tic = tic - baseline_detector(tic, rt, max_height, max_prominence)
|
|
499
|
+
|
|
500
|
+
baseline = baseline_detector(tic, rt, max_height, max_prominence)
|
|
501
|
+
|
|
502
|
+
peak_detect_threshold = np.nanmean(baseline) + (stds * np.std(baseline))
|
|
503
|
+
|
|
504
|
+
remove_indexes = np.where(tic < peak_detect_threshold)[0]
|
|
505
|
+
|
|
506
|
+
elif method == "second_derivative":
|
|
507
|
+
remove_indexes = second_derivative_threshold(
|
|
508
|
+
tic, stds, rt, max_height, max_prominence
|
|
509
|
+
)
|
|
510
|
+
|
|
511
|
+
else:
|
|
512
|
+
NotImplemented(method)
|
|
513
|
+
|
|
514
|
+
peak_height_diff = lambda hi, li: ((tic[hi] - tic[li]) / max_tic) * 100
|
|
515
|
+
|
|
516
|
+
dy = derivate(tic)
|
|
517
|
+
|
|
518
|
+
include_indexes = np.where((np.hstack((dy, 0)) < 0) & (np.hstack((0, dy)) > 0))[0]
|
|
519
|
+
|
|
520
|
+
final_indexes = sorted(set(include_indexes) - set(remove_indexes))
|
|
521
|
+
|
|
522
|
+
# from matplotlib import pyplot as plt
|
|
523
|
+
|
|
524
|
+
# plt.plot(self.retention_time, tic, color='black')
|
|
525
|
+
# plt.scatter(self.retention_time[remove_indexes], tic[remove_indexes], color='red')
|
|
526
|
+
# plt.scatter(self.retention_time[include_indexes], tic[include_indexes], color='blue')
|
|
527
|
+
# plt.scatter(self.retention_time[final_indexes], tic[final_indexes], color='blue')
|
|
528
|
+
|
|
529
|
+
# plt.show()
|
|
530
|
+
|
|
531
|
+
for index in final_indexes:
|
|
532
|
+
start_index = find_minima(index, tic, right=False)
|
|
533
|
+
final_index = find_minima(index, tic)
|
|
534
|
+
|
|
535
|
+
if final_index - start_index > min_datapoints:
|
|
536
|
+
# if min( peak_height_diff(index,start_index), peak_height_diff(index,final_index) )> self.chromatogram_settings.peak_min_prominence_percent :
|
|
537
|
+
|
|
538
|
+
yield (start_index, index, final_index)
|
|
539
|
+
|
|
540
|
+
|
|
541
|
+
def smooth_signal(x, window_len, window, pol_order, implemented_smooth_method):
|
|
542
|
+
"""
|
|
543
|
+
Smooth the data using a window with requested size.
|
|
544
|
+
|
|
545
|
+
This method is based on the convolution of a scaled window with the signal.
|
|
546
|
+
The signal is prepared by introducing reflected copies of the signal
|
|
547
|
+
(with the window size) in both ends so that transient parts are minimized
|
|
548
|
+
in the begining and end part of the output signal.
|
|
549
|
+
|
|
550
|
+
Parameters
|
|
551
|
+
----------
|
|
552
|
+
x: array
|
|
553
|
+
the input signal
|
|
554
|
+
window_len: int
|
|
555
|
+
the dimension of the smoothing window; should be an odd integer
|
|
556
|
+
window: str
|
|
557
|
+
the type of window from 'flat', 'hanning', 'hamming', 'bartlett', 'blackman'
|
|
558
|
+
pol_order: int
|
|
559
|
+
the order of the polynomial to fit the data
|
|
560
|
+
implemented_smooth_method: list
|
|
561
|
+
list of implemented smoothing methods
|
|
562
|
+
|
|
563
|
+
Returns
|
|
564
|
+
-------
|
|
565
|
+
y: array
|
|
566
|
+
the smoothed signal
|
|
567
|
+
|
|
568
|
+
Notes:
|
|
569
|
+
-----
|
|
570
|
+
See also: numpy.hanning, numpy.hamming, numpy.bartlett, numpy.blackman, numpy.convolve
|
|
571
|
+
scipy.signal.savgol_filter
|
|
572
|
+
|
|
573
|
+
"""
|
|
574
|
+
x = np.array(x)
|
|
575
|
+
|
|
576
|
+
if x.ndim != 1:
|
|
577
|
+
raise ValueError("smooth only accepts 1 dimension arrays.")
|
|
578
|
+
|
|
579
|
+
if x.size < window_len:
|
|
580
|
+
raise ValueError("Input array needs to be bigger than window size")
|
|
581
|
+
|
|
582
|
+
# if window_len < 3:
|
|
583
|
+
# return x
|
|
584
|
+
|
|
585
|
+
if not window in implemented_smooth_method:
|
|
586
|
+
raise ValueError(
|
|
587
|
+
"Window method should be 'flat', 'hanning', 'hamming', 'bartlett', 'blackman'"
|
|
588
|
+
)
|
|
589
|
+
|
|
590
|
+
s = np.r_[x[window_len - 1 : 0 : -1], x, x[-1:-window_len:-1]]
|
|
591
|
+
|
|
592
|
+
if window == "savgol":
|
|
593
|
+
return savgol_filter(x, window_len, pol_order)
|
|
594
|
+
|
|
595
|
+
elif window == "boxcar": # moving average
|
|
596
|
+
w = boxcar(window_len)
|
|
597
|
+
|
|
598
|
+
y = np.convolve(w, s, mode="valid")
|
|
599
|
+
|
|
600
|
+
elif window == "flat": # moving average
|
|
601
|
+
w = np.ones(window_len, "d")
|
|
602
|
+
|
|
603
|
+
y = np.convolve(w / w.sum(), s, mode="valid")
|
|
604
|
+
|
|
605
|
+
else:
|
|
606
|
+
w = eval(window + "(window_len)")
|
|
607
|
+
|
|
608
|
+
y = np.convolve(w / w.sum(), s, mode="valid")
|
|
609
|
+
|
|
610
|
+
return y[int(window_len / 2 - 1) : int(-window_len / 2)]
|
|
611
|
+
|
|
612
|
+
|
|
613
|
+
def second_derivative_threshold(
|
|
614
|
+
tic, stds, rt, peak_height_max_percent, peak_max_prominence_percent
|
|
615
|
+
):
|
|
616
|
+
"""
|
|
617
|
+
Second derivative threshold for the TIC data points.
|
|
618
|
+
For LC/GC data processing
|
|
619
|
+
|
|
620
|
+
Parameters
|
|
621
|
+
----------
|
|
622
|
+
tic : array
|
|
623
|
+
array of data points to find the peaks
|
|
624
|
+
stds : float
|
|
625
|
+
standard deviation
|
|
626
|
+
rt : array
|
|
627
|
+
array of retention time data points
|
|
628
|
+
peak_height_max_percent : float
|
|
629
|
+
maximum height of the peak
|
|
630
|
+
|
|
631
|
+
Returns
|
|
632
|
+
-------
|
|
633
|
+
array
|
|
634
|
+
array of the indexes of the data points to remove
|
|
635
|
+
|
|
636
|
+
"""
|
|
637
|
+
|
|
638
|
+
dy = derivate(tic)
|
|
639
|
+
|
|
640
|
+
dydy = derivate(dy)
|
|
641
|
+
dydy = np.hstack((dydy, 0))
|
|
642
|
+
dydy = np.hstack((0, dydy))
|
|
643
|
+
|
|
644
|
+
baseline = baseline_detector(
|
|
645
|
+
dydy,
|
|
646
|
+
rt,
|
|
647
|
+
peak_height_max_percent,
|
|
648
|
+
peak_max_prominence_percent,
|
|
649
|
+
do_interpolation=False,
|
|
650
|
+
)
|
|
651
|
+
|
|
652
|
+
threshold_median = np.median(baseline) - (stds * np.std(baseline))
|
|
653
|
+
|
|
654
|
+
remove_indexes = np.where(dydy > threshold_median)[0]
|
|
655
|
+
|
|
656
|
+
return remove_indexes
|
|
File without changes
|