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,371 @@
|
|
|
1
|
+
import warnings
|
|
2
|
+
from typing import Tuple
|
|
3
|
+
|
|
4
|
+
from numpy import average, histogram, hstack, inf, isnan, log10, median, nan, std, where
|
|
5
|
+
|
|
6
|
+
from corems import chunks
|
|
7
|
+
|
|
8
|
+
# from matplotlib import pyplot
|
|
9
|
+
__author__ = "Yuri E. Corilo"
|
|
10
|
+
__date__ = "Jun 27, 2019"
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class NoiseThresholdCalc:
|
|
14
|
+
"""Class for noise threshold calculation.
|
|
15
|
+
|
|
16
|
+
Parameters
|
|
17
|
+
----------
|
|
18
|
+
mass_spectrum : MassSpectrum
|
|
19
|
+
The mass spectrum object.
|
|
20
|
+
settings : MSParameters
|
|
21
|
+
The mass spectrum parameters object.
|
|
22
|
+
is_centroid : bool
|
|
23
|
+
Flag indicating whether the mass spectrum is centroid or profile.
|
|
24
|
+
baseline_noise : float
|
|
25
|
+
The baseline noise.
|
|
26
|
+
baseline_noise_std : float
|
|
27
|
+
The baseline noise standard deviation.
|
|
28
|
+
max_signal_to_noise : float
|
|
29
|
+
The maximum signal to noise.
|
|
30
|
+
max_abundance : float
|
|
31
|
+
The maximum abundance.
|
|
32
|
+
abundance : np.array
|
|
33
|
+
The abundance array.
|
|
34
|
+
abundance_profile : np.array
|
|
35
|
+
The abundance profile array.
|
|
36
|
+
mz_exp : np.array
|
|
37
|
+
The experimental m/z array.
|
|
38
|
+
mz_exp_profile : np.array
|
|
39
|
+
The experimental m/z profile array.
|
|
40
|
+
|
|
41
|
+
Attributes
|
|
42
|
+
----------
|
|
43
|
+
None
|
|
44
|
+
|
|
45
|
+
Methods
|
|
46
|
+
-------
|
|
47
|
+
* get_noise_threshold(). Get the noise threshold.
|
|
48
|
+
* cut_mz_domain_noise(). Cut the m/z domain to the noise threshold regions.
|
|
49
|
+
* get_noise_average(ymincentroid).
|
|
50
|
+
Get the average noise and standard deviation.
|
|
51
|
+
* get_abundance_minima_centroid(abun_cut)
|
|
52
|
+
Get the abundance minima for centroid data.
|
|
53
|
+
* run_log_noise_threshold_calc().
|
|
54
|
+
Run the log noise threshold calculation.
|
|
55
|
+
* run_noise_threshold_calc().
|
|
56
|
+
Run the noise threshold calculation.
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
def get_noise_threshold(self) -> Tuple[Tuple[float, float], Tuple[float, float]]:
|
|
60
|
+
"""Get the noise threshold.
|
|
61
|
+
|
|
62
|
+
Returns
|
|
63
|
+
-------
|
|
64
|
+
Tuple[Tuple[float, float], Tuple[float, float]]
|
|
65
|
+
A tuple containing the m/z and abundance noise thresholds.
|
|
66
|
+
(min_mz, max_mz), (noise_threshold, noise_threshold)
|
|
67
|
+
"""
|
|
68
|
+
|
|
69
|
+
if self.is_centroid:
|
|
70
|
+
x = min(self.mz_exp), max((self.mz_exp))
|
|
71
|
+
|
|
72
|
+
if self.settings.noise_threshold_method == "minima":
|
|
73
|
+
abundance_threshold = self.baseline_noise + (
|
|
74
|
+
self.settings.noise_threshold_min_std * self.baseline_noise_std
|
|
75
|
+
)
|
|
76
|
+
y = (abundance_threshold, abundance_threshold)
|
|
77
|
+
|
|
78
|
+
elif self.settings.noise_threshold_method == "signal_noise":
|
|
79
|
+
normalized_threshold = (
|
|
80
|
+
self.max_abundance * self.settings.noise_threshold_min_s2n
|
|
81
|
+
) / self.max_signal_to_noise
|
|
82
|
+
y = (normalized_threshold, normalized_threshold)
|
|
83
|
+
|
|
84
|
+
elif self.settings.noise_threshold_method == "relative_abundance":
|
|
85
|
+
normalized_threshold = (
|
|
86
|
+
max(self.abundance) / 100
|
|
87
|
+
) * self.settings.noise_threshold_min_relative_abundance
|
|
88
|
+
y = (normalized_threshold, normalized_threshold)
|
|
89
|
+
|
|
90
|
+
elif self.settings.noise_threshold_method == "absolute_abundance":
|
|
91
|
+
normalized_threshold = (
|
|
92
|
+
self.abundance * self.settings.noise_threshold_absolute_abundance
|
|
93
|
+
)
|
|
94
|
+
y = (normalized_threshold, normalized_threshold)
|
|
95
|
+
# log noise method not tested for centroid data
|
|
96
|
+
else:
|
|
97
|
+
raise Exception(
|
|
98
|
+
"%s method was not implemented, please refer to corems.mass_spectrum.calc.NoiseCalc Class"
|
|
99
|
+
% self.settings.noise_threshold_method
|
|
100
|
+
)
|
|
101
|
+
|
|
102
|
+
return x, y
|
|
103
|
+
|
|
104
|
+
else:
|
|
105
|
+
if self.baseline_noise and self.baseline_noise_std:
|
|
106
|
+
x = (self.mz_exp_profile.min(), self.mz_exp_profile.max())
|
|
107
|
+
y = (self.baseline_noise_std, self.baseline_noise_std)
|
|
108
|
+
|
|
109
|
+
if self.settings.noise_threshold_method == "minima":
|
|
110
|
+
# print(self.settings.noise_threshold_min_std)
|
|
111
|
+
abundance_threshold = self.baseline_noise + (
|
|
112
|
+
self.settings.noise_threshold_min_std * self.baseline_noise_std
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
y = (abundance_threshold, abundance_threshold)
|
|
116
|
+
|
|
117
|
+
elif self.settings.noise_threshold_method == "signal_noise":
|
|
118
|
+
max_sn = self.abundance_profile.max() / self.baseline_noise_std
|
|
119
|
+
|
|
120
|
+
normalized_threshold = (
|
|
121
|
+
self.abundance_profile.max()
|
|
122
|
+
* self.settings.noise_threshold_min_s2n
|
|
123
|
+
) / max_sn
|
|
124
|
+
y = (normalized_threshold, normalized_threshold)
|
|
125
|
+
|
|
126
|
+
elif self.settings.noise_threshold_method == "relative_abundance":
|
|
127
|
+
normalized_threshold = (
|
|
128
|
+
self.abundance_profile.max() / 100
|
|
129
|
+
) * self.settings.noise_threshold_min_relative_abundance
|
|
130
|
+
y = (normalized_threshold, normalized_threshold)
|
|
131
|
+
|
|
132
|
+
elif self.settings.noise_threshold_method == "absolute_abundance":
|
|
133
|
+
normalized_threshold = (
|
|
134
|
+
self.settings.noise_threshold_absolute_abundance
|
|
135
|
+
)
|
|
136
|
+
y = (normalized_threshold, normalized_threshold)
|
|
137
|
+
|
|
138
|
+
elif self.settings.noise_threshold_method == "log":
|
|
139
|
+
normalized_threshold = (
|
|
140
|
+
self.settings.noise_threshold_log_nsigma
|
|
141
|
+
* self.baseline_noise_std
|
|
142
|
+
)
|
|
143
|
+
y = (normalized_threshold, normalized_threshold)
|
|
144
|
+
|
|
145
|
+
else:
|
|
146
|
+
raise Exception(
|
|
147
|
+
"%s method was not implemented, \
|
|
148
|
+
please refer to corems.mass_spectrum.calc.NoiseCalc Class"
|
|
149
|
+
% self.settings.noise_threshold_method
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
return x, y
|
|
153
|
+
|
|
154
|
+
else:
|
|
155
|
+
warnings.warn(
|
|
156
|
+
"Noise Baseline and Noise std not specified,\
|
|
157
|
+
defaulting to 0,0 run process_mass_spec() ?"
|
|
158
|
+
)
|
|
159
|
+
return (0, 0), (0, 0)
|
|
160
|
+
|
|
161
|
+
def cut_mz_domain_noise(self):
|
|
162
|
+
"""Cut the m/z domain to the noise threshold regions.
|
|
163
|
+
|
|
164
|
+
Returns
|
|
165
|
+
-------
|
|
166
|
+
Tuple[np.array, np.array]
|
|
167
|
+
A tuple containing the m/z and abundance arrays of the truncated spectrum region.
|
|
168
|
+
"""
|
|
169
|
+
min_mz_whole_ms = self.mz_exp_profile.min()
|
|
170
|
+
max_mz_whole_ms = self.mz_exp_profile.max()
|
|
171
|
+
|
|
172
|
+
if self.settings.noise_threshold_method == "minima":
|
|
173
|
+
# this calculation is taking too long (about 2 seconds)
|
|
174
|
+
number_average_molecular_weight = self.weight_average_molecular_weight(
|
|
175
|
+
profile=True
|
|
176
|
+
)
|
|
177
|
+
|
|
178
|
+
# +-200 is a guess for testing only, it needs adjustment for each type of analysis
|
|
179
|
+
# need to check min mz here or it will break
|
|
180
|
+
min_mz_noise = number_average_molecular_weight - 100
|
|
181
|
+
# need to check max mz here or it will break
|
|
182
|
+
max_mz_noise = number_average_molecular_weight + 100
|
|
183
|
+
|
|
184
|
+
else:
|
|
185
|
+
min_mz_noise = self.settings.noise_min_mz
|
|
186
|
+
max_mz_noise = self.settings.noise_max_mz
|
|
187
|
+
|
|
188
|
+
if min_mz_noise < min_mz_whole_ms:
|
|
189
|
+
min_mz_noise = min_mz_whole_ms
|
|
190
|
+
|
|
191
|
+
if max_mz_noise > max_mz_whole_ms:
|
|
192
|
+
max_mz_noise = max_mz_whole_ms
|
|
193
|
+
|
|
194
|
+
if min_mz_noise > max_mz_noise:
|
|
195
|
+
warnings.warn(
|
|
196
|
+
"Empty noise ROI: min_mz_noise is greater than max_mz_noise; returning empty arrays."
|
|
197
|
+
)
|
|
198
|
+
return self.mz_exp_profile[0:0], self.abundance_profile[0:0]
|
|
199
|
+
|
|
200
|
+
# Inclusive ROI boundaries to preserve current threshold behavior.
|
|
201
|
+
mz_mask = (self.mz_exp_profile >= min_mz_noise) & (
|
|
202
|
+
self.mz_exp_profile <= max_mz_noise
|
|
203
|
+
)
|
|
204
|
+
indices = where(mz_mask)[0]
|
|
205
|
+
|
|
206
|
+
if indices.size == 0:
|
|
207
|
+
warnings.warn(
|
|
208
|
+
"Empty noise ROI: no m/z points found within inclusive range; returning empty arrays."
|
|
209
|
+
)
|
|
210
|
+
return self.mz_exp_profile[0:0], self.abundance_profile[0:0]
|
|
211
|
+
|
|
212
|
+
start_index = indices.min()
|
|
213
|
+
end_index = indices.max() + 1
|
|
214
|
+
|
|
215
|
+
return (
|
|
216
|
+
self.mz_exp_profile[start_index:end_index],
|
|
217
|
+
self.abundance_profile[start_index:end_index],
|
|
218
|
+
)
|
|
219
|
+
|
|
220
|
+
def get_noise_average(self, ymincentroid):
|
|
221
|
+
"""Get the average noise and standard deviation.
|
|
222
|
+
|
|
223
|
+
Parameters
|
|
224
|
+
----------
|
|
225
|
+
ymincentroid : np.array
|
|
226
|
+
The ymincentroid array.
|
|
227
|
+
|
|
228
|
+
Returns
|
|
229
|
+
-------
|
|
230
|
+
Tuple[float, float]
|
|
231
|
+
A tuple containing the average noise and standard deviation.
|
|
232
|
+
|
|
233
|
+
"""
|
|
234
|
+
# assumes noise to be gaussian and estimate noise level by
|
|
235
|
+
# calculating the valley.
|
|
236
|
+
|
|
237
|
+
auto = True if self.settings.noise_threshold_method == "minima" else False
|
|
238
|
+
|
|
239
|
+
average_noise = median((ymincentroid)) * 2 if auto else median(ymincentroid)
|
|
240
|
+
|
|
241
|
+
s_deviation = ymincentroid.std() * 3 if auto else ymincentroid.std()
|
|
242
|
+
|
|
243
|
+
return average_noise, s_deviation
|
|
244
|
+
|
|
245
|
+
def get_abundance_minima_centroid(self, abun_cut):
|
|
246
|
+
"""Get the abundance minima for centroid data.
|
|
247
|
+
|
|
248
|
+
Parameters
|
|
249
|
+
----------
|
|
250
|
+
abun_cut : np.array
|
|
251
|
+
The abundance cut array.
|
|
252
|
+
|
|
253
|
+
Returns
|
|
254
|
+
-------
|
|
255
|
+
np.array
|
|
256
|
+
The abundance minima array.
|
|
257
|
+
"""
|
|
258
|
+
maximum = self.abundance_profile.max()
|
|
259
|
+
threshold_min = maximum * 1.00
|
|
260
|
+
|
|
261
|
+
y = -abun_cut
|
|
262
|
+
|
|
263
|
+
dy = y[1:] - y[:-1]
|
|
264
|
+
"""replaces NaN for Infinity"""
|
|
265
|
+
indices_nan = where(isnan(y))[0]
|
|
266
|
+
|
|
267
|
+
if indices_nan.size:
|
|
268
|
+
y[indices_nan] = inf
|
|
269
|
+
dy[where(isnan(dy))[0]] = inf
|
|
270
|
+
|
|
271
|
+
indices = where((hstack((dy, 0)) < 0) & (hstack((0, dy)) > 0))[0]
|
|
272
|
+
|
|
273
|
+
if indices.size and threshold_min is not None:
|
|
274
|
+
indices = indices[abun_cut[indices] <= threshold_min]
|
|
275
|
+
|
|
276
|
+
return abun_cut[indices]
|
|
277
|
+
|
|
278
|
+
def run_log_noise_threshold_calc(self):
|
|
279
|
+
"""Run the log noise threshold calculation.
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
Returns
|
|
283
|
+
-------
|
|
284
|
+
Tuple[float, float]
|
|
285
|
+
A tuple containing the average noise and standard deviation.
|
|
286
|
+
|
|
287
|
+
Notes
|
|
288
|
+
--------
|
|
289
|
+
Method for estimating the noise based on decimal log of all the data point
|
|
290
|
+
|
|
291
|
+
Idea is that you calculate a histogram of of the log10(abundance) values.
|
|
292
|
+
The maximum of the histogram == the standard deviation of the noise.
|
|
293
|
+
|
|
294
|
+
|
|
295
|
+
For aFT data it is a gaussian distribution of noise - not implemented here!
|
|
296
|
+
For mFT data it is a Rayleigh distribution, and the value is actually 10^(abu_max)*0.463.
|
|
297
|
+
|
|
298
|
+
|
|
299
|
+
See the publication cited above for the derivation of this.
|
|
300
|
+
|
|
301
|
+
References
|
|
302
|
+
--------
|
|
303
|
+
1. dx.doi.org/10.1021/ac403278t | Anal. Chem. 2014, 86, 3308−3316
|
|
304
|
+
|
|
305
|
+
"""
|
|
306
|
+
|
|
307
|
+
if self.is_centroid:
|
|
308
|
+
raise Exception("log noise Not tested for centroid data")
|
|
309
|
+
else:
|
|
310
|
+
# cut the spectrum to ROI
|
|
311
|
+
mz_cut, abundance_cut = self.cut_mz_domain_noise()
|
|
312
|
+
# If there are 0 values, the log will fail
|
|
313
|
+
# But we may have negative values for aFT data, so we check if 0 exists
|
|
314
|
+
# Need to make a copy of the abundance cut values so we dont overwrite it....
|
|
315
|
+
tmp_abundance = abundance_cut.copy()
|
|
316
|
+
if 0 in tmp_abundance:
|
|
317
|
+
tmp_abundance[tmp_abundance == 0] = nan
|
|
318
|
+
tmp_abundance = tmp_abundance[~isnan(tmp_abundance)]
|
|
319
|
+
# It seems there are edge cases of sparse but high S/N data where the wrong values may be determined.
|
|
320
|
+
# Hard to generalise - needs more investigation.
|
|
321
|
+
|
|
322
|
+
# calculate a histogram of the log10 of the abundance data
|
|
323
|
+
hist_values = histogram(
|
|
324
|
+
log10(tmp_abundance), bins=self.settings.noise_threshold_log_nsigma_bins
|
|
325
|
+
)
|
|
326
|
+
# find the apex of this histogram
|
|
327
|
+
maxvalidx = where(hist_values[0] == max(hist_values[0]))
|
|
328
|
+
# get the value of this apex (note - still in log10 units)
|
|
329
|
+
log_sigma = hist_values[1][maxvalidx]
|
|
330
|
+
# If the histogram had more than one maximum frequency bin, we need to reduce that to one entry
|
|
331
|
+
if len(log_sigma) > 1:
|
|
332
|
+
log_sigma = average(log_sigma)
|
|
333
|
+
else:
|
|
334
|
+
log_sigma = log_sigma[0]
|
|
335
|
+
## To do : check if aFT or mFT and adjust method
|
|
336
|
+
noise_mid = 10**log_sigma
|
|
337
|
+
noise_1std = (
|
|
338
|
+
noise_mid * self.settings.noise_threshold_log_nsigma_corr_factor
|
|
339
|
+
) # for mFT 0.463
|
|
340
|
+
return float(noise_mid), float(noise_1std)
|
|
341
|
+
|
|
342
|
+
def run_noise_threshold_calc(self):
|
|
343
|
+
"""Runs noise threshold calculation (not log based method)
|
|
344
|
+
|
|
345
|
+
Returns
|
|
346
|
+
-------
|
|
347
|
+
Tuple[float, float]
|
|
348
|
+
A tuple containing the average noise and standard deviation.
|
|
349
|
+
|
|
350
|
+
"""
|
|
351
|
+
if self.is_centroid:
|
|
352
|
+
# calculates noise_baseline and noise_std
|
|
353
|
+
# needed to run auto noise threshold mode
|
|
354
|
+
# it is not used for signal to noise nor
|
|
355
|
+
# relative abudance methods
|
|
356
|
+
abundances_chunks = chunks(self.abundance, 50)
|
|
357
|
+
each_min_abund = [min(x) for x in abundances_chunks]
|
|
358
|
+
|
|
359
|
+
return average(each_min_abund), std(each_min_abund)
|
|
360
|
+
|
|
361
|
+
else:
|
|
362
|
+
mz_cut, abundance_cut = self.cut_mz_domain_noise()
|
|
363
|
+
|
|
364
|
+
if self.settings.noise_threshold_method == "minima":
|
|
365
|
+
yminima = self.get_abundance_minima_centroid(abundance_cut)
|
|
366
|
+
|
|
367
|
+
return self.get_noise_average(yminima)
|
|
368
|
+
|
|
369
|
+
else:
|
|
370
|
+
# pyplot.show()
|
|
371
|
+
return self.get_noise_average(abundance_cut)
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This code is for Bayesian estimation of the noise levels.
|
|
3
|
+
It is it not implemented or used in the current code base.
|
|
4
|
+
The packages it uses are not part of the requirements.
|
|
5
|
+
If you want to use it, you will need to install them manually.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from corems.mass_spectrum.calc.NoiseCalc import NoiseThresholdCalc
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class BayesNoiseCalc(NoiseThresholdCalc):
|
|
12
|
+
def from_posterior(self, param, samples):
|
|
13
|
+
"""
|
|
14
|
+
# Legacy code for Bayesian efforts - not used.
|
|
15
|
+
pymc3 is not installed by default,
|
|
16
|
+
if have plans to use it manual installation of pymc3
|
|
17
|
+
package before using this method is needed
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
import pymc3 as pm
|
|
21
|
+
import numpy as np
|
|
22
|
+
import theano.tensor as tt
|
|
23
|
+
from theano import as_op
|
|
24
|
+
from scipy.stats import gaussian_kde
|
|
25
|
+
|
|
26
|
+
smin, smax = np.min(samples), np.max(samples)
|
|
27
|
+
width = smax - smin
|
|
28
|
+
x = np.linspace(smin, smax, 100)
|
|
29
|
+
y = gaussian_kde(samples)(x)
|
|
30
|
+
|
|
31
|
+
# what was never sampled should have a small probability but not 0,
|
|
32
|
+
# so we'll extend the domain and use linear approximation of density on it
|
|
33
|
+
x = np.concatenate([[x[0] - 3 * width], x, [x[-1] + 3 * width]])
|
|
34
|
+
y = np.concatenate([[0], y, [0]])
|
|
35
|
+
|
|
36
|
+
return pm.distributions.Interpolated(param, x, y)
|
|
37
|
+
|
|
38
|
+
def error_model_from_trace(self, trace, ymincentroid):
|
|
39
|
+
"""
|
|
40
|
+
# Legacy code for Bayesian efforts - not used.
|
|
41
|
+
pymc3 is not installed by default,
|
|
42
|
+
if have plans to use it manual installation of pymc3
|
|
43
|
+
package before using this method is needed
|
|
44
|
+
"""
|
|
45
|
+
import pymc3 as pm
|
|
46
|
+
# from pymc3 import traceplot, plot_posterior
|
|
47
|
+
|
|
48
|
+
with pm.Model() as model2:
|
|
49
|
+
sd = self.from_posterior("sd", trace["sd"])
|
|
50
|
+
y = pm.HalfNormal("y", sd=sd, observed=ymincentroid)
|
|
51
|
+
start = pm.find_MAP()
|
|
52
|
+
step = pm.NUTS() # Hamiltonian MCMC with No U-Turn Sampler
|
|
53
|
+
trace = pm.sample(
|
|
54
|
+
1000, step, start, random_seed=123, progressbar=True, tune=1000
|
|
55
|
+
)
|
|
56
|
+
pm.summary(trace)
|
|
57
|
+
# plot_posterior(trace)
|
|
58
|
+
# traceplot(trace)
|
|
59
|
+
return pm.summary(trace)["mean"].values[0]
|
|
60
|
+
|
|
61
|
+
def simple_model_error_dist(self, ymincentroid):
|
|
62
|
+
"""
|
|
63
|
+
# Legacy code for Bayesian efforts - not used.
|
|
64
|
+
pymc3 is not installed by default,
|
|
65
|
+
if have plans to use it manual installation of pymc3
|
|
66
|
+
package before using this method is needed
|
|
67
|
+
"""
|
|
68
|
+
import pymc3 as pm
|
|
69
|
+
# from pymc3 import traceplot, plot_posterior
|
|
70
|
+
# import seaborn as sns
|
|
71
|
+
# f, ax = pyplot.subplots(figsize=(6, 6))
|
|
72
|
+
# sns.distplot(ymincentroid)
|
|
73
|
+
# sns.kdeplot(ymincentroid, ax=ax, shade=True, color="g")
|
|
74
|
+
# sns.rugplot(ymincentroid, color="black", ax=ax)
|
|
75
|
+
# ax.set(xlabel= "Peak Minima Magnitude", ylabel= "Density")
|
|
76
|
+
# pyplot.show()
|
|
77
|
+
|
|
78
|
+
with pm.Model() as model:
|
|
79
|
+
# mu = pm.Uniform('mu', lower=-1, upper=1)
|
|
80
|
+
lower = ymincentroid.min()
|
|
81
|
+
upper = ymincentroid.max()
|
|
82
|
+
|
|
83
|
+
sd = pm.Uniform("sd", lower=lower, upper=upper)
|
|
84
|
+
|
|
85
|
+
y = pm.HalfNormal("y", sd=sd, observed=ymincentroid)
|
|
86
|
+
|
|
87
|
+
start = pm.find_MAP()
|
|
88
|
+
step = pm.NUTS() # Hamiltonian MCMC with No U-Turn Sampler
|
|
89
|
+
trace = pm.sample(
|
|
90
|
+
1000, step, start, random_seed=123, progressbar=True, tune=1000
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
return pm.summary(trace)["mean"].values[0]
|