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,748 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Notes
|
|
3
|
+
--------
|
|
4
|
+
Assumes that ms1 are collected in profile mode, persistent homology not applicable for centroided data.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import sys
|
|
8
|
+
|
|
9
|
+
sys.path.append("./")
|
|
10
|
+
from multiprocessing import Pool
|
|
11
|
+
from pathlib import Path
|
|
12
|
+
import datetime
|
|
13
|
+
import toml
|
|
14
|
+
import warnings
|
|
15
|
+
|
|
16
|
+
import pandas as pd
|
|
17
|
+
import time
|
|
18
|
+
|
|
19
|
+
from corems.mass_spectra.input.corems_hdf5 import ReadCoreMSHDFMassSpectra
|
|
20
|
+
from corems.mass_spectra.input.mzml import MZMLSpectraParser
|
|
21
|
+
from corems.mass_spectra.input.rawFileReader import ImportMassSpectraThermoMSFileReader
|
|
22
|
+
from corems.mass_spectra.output.export import LipidomicsExport
|
|
23
|
+
from corems.molecular_id.search.molecularFormulaSearch import (
|
|
24
|
+
SearchMolecularFormulas,
|
|
25
|
+
SearchMolecularFormulasLC,
|
|
26
|
+
)
|
|
27
|
+
from corems.molecular_id.search.database_interfaces import LCLipidLibraryInterface
|
|
28
|
+
from corems.encapsulation.input.parameter_from_json import (
|
|
29
|
+
load_and_set_toml_parameters_lcms,
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def instantiate_lcms_obj(file_in):
|
|
34
|
+
"""Instantiate a corems LCMS object from a binary file. Pull in ms1 spectra into dataframe (without storing as MassSpectrum objects to save memory)
|
|
35
|
+
|
|
36
|
+
Parameters
|
|
37
|
+
----------
|
|
38
|
+
file_in : str or Path
|
|
39
|
+
Path to binary file
|
|
40
|
+
verbose : bool
|
|
41
|
+
Whether to print verbose output
|
|
42
|
+
|
|
43
|
+
Returns
|
|
44
|
+
-------
|
|
45
|
+
myLCMSobj : corems LCMS object
|
|
46
|
+
LCMS object with ms1 spectra in dataframe
|
|
47
|
+
"""
|
|
48
|
+
# Instantiate parser based on binary file type
|
|
49
|
+
if ".raw" in str(file_in):
|
|
50
|
+
parser = ImportMassSpectraThermoMSFileReader(file_in)
|
|
51
|
+
|
|
52
|
+
if ".mzML" in str(file_in):
|
|
53
|
+
parser = MZMLSpectraParser(file_in)
|
|
54
|
+
|
|
55
|
+
# Instantiate lc-ms data object using parser and pull in ms1 spectra into dataframe (without storing as MassSpectrum objects to save memory)
|
|
56
|
+
myLCMSobj = parser.get_lcms_obj(spectra="ms1")
|
|
57
|
+
|
|
58
|
+
return myLCMSobj
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def set_params_on_lcms_obj(myLCMSobj, params_toml, verbose):
|
|
62
|
+
"""Set parameters on the LCMS object
|
|
63
|
+
|
|
64
|
+
Parameters
|
|
65
|
+
----------
|
|
66
|
+
myLCMSobj : corems LCMS object
|
|
67
|
+
LCMS object to set parameters on
|
|
68
|
+
params_toml : str or Path
|
|
69
|
+
Path to toml file with parameters
|
|
70
|
+
|
|
71
|
+
Returns
|
|
72
|
+
-------
|
|
73
|
+
None, sets parameters on the LCMS object
|
|
74
|
+
"""
|
|
75
|
+
# Load parameters from toml file
|
|
76
|
+
load_and_set_toml_parameters_lcms(myLCMSobj, params_toml)
|
|
77
|
+
|
|
78
|
+
# If myLCMSobj is a positive mode, remove Cl from atoms used in molecular search
|
|
79
|
+
# This cuts down on the number of molecular formulas searched hugely
|
|
80
|
+
if myLCMSobj.polarity == "positive":
|
|
81
|
+
myLCMSobj.parameters.mass_spectrum["ms1"].molecular_search.usedAtoms.pop("Cl")
|
|
82
|
+
elif myLCMSobj.polarity == "negative":
|
|
83
|
+
myLCMSobj.parameters.mass_spectrum["ms1"].molecular_search.usedAtoms.pop("Na")
|
|
84
|
+
|
|
85
|
+
if verbose:
|
|
86
|
+
print("Parameters set on LCMS object")
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def load_scan_translator(scan_translator=None):
|
|
90
|
+
"""Translate scans using a scan translator
|
|
91
|
+
|
|
92
|
+
Parameters
|
|
93
|
+
----------
|
|
94
|
+
scan_translator : str or Path
|
|
95
|
+
Path to scan translator yaml file
|
|
96
|
+
|
|
97
|
+
Returns
|
|
98
|
+
-------
|
|
99
|
+
scan_dict : dict
|
|
100
|
+
Dict with keys as parameter keys and values as lists of scans
|
|
101
|
+
"""
|
|
102
|
+
# Convert the scan translator to a dictionary
|
|
103
|
+
if scan_translator is None:
|
|
104
|
+
scan_translator_dict = {"ms2": {"scan_filter": "", "resolution": "high"}}
|
|
105
|
+
else:
|
|
106
|
+
# Convert the scan translator to a dictionary
|
|
107
|
+
if isinstance(scan_translator, str):
|
|
108
|
+
scan_translator = Path(scan_translator)
|
|
109
|
+
# read in the scan translator from toml
|
|
110
|
+
with open(scan_translator, "r") as f:
|
|
111
|
+
scan_translator_dict = toml.load(f)
|
|
112
|
+
for param_key in scan_translator_dict.keys():
|
|
113
|
+
if scan_translator_dict[param_key]["scan_filter"] == "":
|
|
114
|
+
scan_translator_dict[param_key]["scan_filter"] = None
|
|
115
|
+
return scan_translator_dict
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def check_scan_translator(myLCMSobj, scan_translator):
|
|
119
|
+
"""Check if scan translator is provided and that it maps correctly to scans and parameters"""
|
|
120
|
+
scan_translator_dict = load_scan_translator(scan_translator)
|
|
121
|
+
# Check that the scan translator maps correctly to scans and parameters
|
|
122
|
+
scan_df = myLCMSobj.scan_df
|
|
123
|
+
scans_pulled_out = []
|
|
124
|
+
for param_key in scan_translator_dict.keys():
|
|
125
|
+
assert param_key in myLCMSobj.parameters.mass_spectrum.keys()
|
|
126
|
+
assert "scan_filter" in scan_translator_dict[param_key].keys()
|
|
127
|
+
assert "resolution" in scan_translator_dict[param_key].keys()
|
|
128
|
+
# Pull out scans that match the scan filter
|
|
129
|
+
scan_df_sub = scan_df[
|
|
130
|
+
scan_df.scan_text.str.contains(
|
|
131
|
+
scan_translator_dict[param_key]["scan_filter"]
|
|
132
|
+
)
|
|
133
|
+
]
|
|
134
|
+
scans_pulled_out.extend(scan_df_sub.scan.tolist())
|
|
135
|
+
if len(scan_df_sub) == 0:
|
|
136
|
+
raise ValueError(
|
|
137
|
+
"No scans pulled out by scan translator for parameter key: ",
|
|
138
|
+
param_key,
|
|
139
|
+
" and scan filter: ",
|
|
140
|
+
scan_translator_dict[param_key]["scan_filter"],
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
# Check that the scans pulled out by the scan translator are not overlapping and assert error if they are
|
|
144
|
+
if len(set(scans_pulled_out)) != len(scans_pulled_out):
|
|
145
|
+
raise ValueError("Overlapping scans pulled out by scan translator")
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def add_mass_features(myLCMSobj, scan_translator):
|
|
149
|
+
"""Process ms1 spectra and perform molecular search
|
|
150
|
+
|
|
151
|
+
This includes peak picking, adding and processing associated ms1 spectra,
|
|
152
|
+
integration of mass features, annotation of c13 mass features, deconvolution of ms1 mass features,
|
|
153
|
+
and adding of peak shape metrics of mass features to the mass feature dataframe.
|
|
154
|
+
|
|
155
|
+
Parameters
|
|
156
|
+
----------
|
|
157
|
+
myLCMSobj : corems LCMS object
|
|
158
|
+
LCMS object to process
|
|
159
|
+
scan_translator : str or Path
|
|
160
|
+
Path to scan translator yaml file
|
|
161
|
+
|
|
162
|
+
Returns
|
|
163
|
+
-------
|
|
164
|
+
None, processes the LCMS object
|
|
165
|
+
"""
|
|
166
|
+
print("Finding mass features")
|
|
167
|
+
myLCMSobj.find_mass_features()
|
|
168
|
+
print("Found ", len(myLCMSobj.mass_features), " mass features")
|
|
169
|
+
|
|
170
|
+
# Get the scan mode of the ms1 spectra
|
|
171
|
+
ms1_scan_df = myLCMSobj.scan_df[myLCMSobj.scan_df.ms_level == 1]
|
|
172
|
+
|
|
173
|
+
|
|
174
|
+
# Integrate before adding associated ms1 spectra to be able to filter by peak shape metrics?
|
|
175
|
+
print("Integrating mass features")
|
|
176
|
+
myLCMSobj.integrate_mass_features(drop_if_fail=True)
|
|
177
|
+
print("Adding peak shape metrics")
|
|
178
|
+
myLCMSobj.add_peak_metrics()
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
print("Adding associated ms1 spectra")
|
|
182
|
+
if all(x == "profile" for x in ms1_scan_df.ms_format.to_list()):
|
|
183
|
+
myLCMSobj.add_associated_ms1(
|
|
184
|
+
auto_process=True, use_parser=False, spectrum_mode="profile"
|
|
185
|
+
)
|
|
186
|
+
# If the ms1 data are centroided and the parser if MZMLSpectraParser, set spectrum_mode to centroided but use_parser to False (mzml doesn't have resolving power anyway)
|
|
187
|
+
elif isinstance(myLCMSobj.spectra_parser, MZMLSpectraParser) and all(
|
|
188
|
+
x == "centroid" for x in ms1_scan_df.ms_format.to_list()
|
|
189
|
+
):
|
|
190
|
+
myLCMSobj.add_associated_ms1(
|
|
191
|
+
auto_process=True, use_parser=False, spectrum_mode="centroid"
|
|
192
|
+
)
|
|
193
|
+
elif all(x == "centroid" for x in ms1_scan_df.ms_format.to_list()):
|
|
194
|
+
myLCMSobj.add_associated_ms1(
|
|
195
|
+
auto_process=True, use_parser=True, spectrum_mode="centroid"
|
|
196
|
+
)
|
|
197
|
+
|
|
198
|
+
# Count and report how many mass features are left after integration
|
|
199
|
+
print("Number of mass features after integration: ", len(myLCMSobj.mass_features))
|
|
200
|
+
#filter_and_plot_mass_features(myLCMSobj)
|
|
201
|
+
"""
|
|
202
|
+
print("Annotating C13 mass features")
|
|
203
|
+
myLCMSobj.find_c13_mass_features()
|
|
204
|
+
print("Deconvoluting mass features")
|
|
205
|
+
myLCMSobj.deconvolute_ms1_mass_features()
|
|
206
|
+
|
|
207
|
+
print("Adding associated ms2 spectra")
|
|
208
|
+
scan_dictionary = load_scan_translator(scan_translator=scan_translator)
|
|
209
|
+
for param_key in scan_dictionary.keys():
|
|
210
|
+
scan_filter = scan_dictionary[param_key]["scan_filter"]
|
|
211
|
+
if scan_filter == "":
|
|
212
|
+
scan_filter = None
|
|
213
|
+
myLCMSobj.add_associated_ms2_dda(
|
|
214
|
+
spectrum_mode="centroid", ms_params_key=param_key, scan_filter=scan_filter
|
|
215
|
+
)
|
|
216
|
+
"""
|
|
217
|
+
|
|
218
|
+
def filter_and_plot_mass_features(myLCMSobj):
|
|
219
|
+
"""Filter mass features based on peak shape metrics and plot composite feature map
|
|
220
|
+
|
|
221
|
+
Helpful for visualizing and optimizing filtering parameters
|
|
222
|
+
|
|
223
|
+
Parameters
|
|
224
|
+
----------
|
|
225
|
+
myLCMSobj : corems LCMS object
|
|
226
|
+
LCMS object to process
|
|
227
|
+
|
|
228
|
+
Returns
|
|
229
|
+
-------
|
|
230
|
+
None, processes the LCMS object
|
|
231
|
+
"""
|
|
232
|
+
# Filter mass features based on peak shape metrics
|
|
233
|
+
my_df_og = myLCMSobj.mass_features_to_df()
|
|
234
|
+
# Make mf_df with only mass features that pass the filters
|
|
235
|
+
mf_df = my_df_og[
|
|
236
|
+
# use normalized_dispersity_index, and set to less than 0.2
|
|
237
|
+
(my_df_og["noise_score_max"] > 0.8)
|
|
238
|
+
& (my_df_og["noise_score_min"] > 0.5)
|
|
239
|
+
]
|
|
240
|
+
mf_ids_to_keep = mf_df.index.tolist()
|
|
241
|
+
|
|
242
|
+
# Make a mf_df with dropped mass features
|
|
243
|
+
mf_df_dropped = my_df_og[~my_df_og.index.isin(mf_ids_to_keep)]
|
|
244
|
+
|
|
245
|
+
# Plot 50 random "good" mass features
|
|
246
|
+
import numpy as np
|
|
247
|
+
import matplotlib.pyplot as plt
|
|
248
|
+
good_mf_dir = Path("good_mass_features")
|
|
249
|
+
# delete good_mf_dir if it exists
|
|
250
|
+
if good_mf_dir.exists():
|
|
251
|
+
import shutil
|
|
252
|
+
shutil.rmtree(good_mf_dir)
|
|
253
|
+
good_mf_dir.mkdir(exist_ok=True)
|
|
254
|
+
# save df of dropped mass features in good_mf_dir
|
|
255
|
+
mf_df.to_csv(good_mf_dir / "good_mass_features.csv", index=True)
|
|
256
|
+
for mf_id in np.random.choice(mf_ids_to_keep, min(50, len(mf_ids_to_keep)), replace=False):
|
|
257
|
+
fig = myLCMSobj.mass_features[mf_id].plot(return_fig=True, plot_smoothed_eic=True, plot_eic_datapoints=True)
|
|
258
|
+
# Add the noise_score_max and dispersity_index to the subtitle
|
|
259
|
+
fig.suptitle(f"mf_id: {mf_id}, noise_score_max: {myLCMSobj.mass_features[mf_id].noise_score_max:.2f}, dispersity_index: {myLCMSobj.mass_features[mf_id].dispersity_index:.2f}")
|
|
260
|
+
fig.savefig(good_mf_dir / f"mf_{mf_id}_good.png", dpi=300, bbox_inches="tight")
|
|
261
|
+
plt.close(fig)
|
|
262
|
+
|
|
263
|
+
# Do the same for dropped mass features
|
|
264
|
+
dropped_mf_dir = Path("dropped_mass_features")
|
|
265
|
+
# delete dropped_mf_dir if it exists
|
|
266
|
+
if dropped_mf_dir.exists():
|
|
267
|
+
import shutil
|
|
268
|
+
shutil.rmtree(dropped_mf_dir)
|
|
269
|
+
dropped_mf_dir.mkdir(exist_ok=True)
|
|
270
|
+
# save df of dropped mass features in dropped_mf_dir
|
|
271
|
+
mf_df_dropped.to_csv(dropped_mf_dir / "dropped_mass_features.csv", index=True)
|
|
272
|
+
for mf_id in np.random.choice(mf_df_dropped.index.tolist(), min(50, len(mf_df_dropped)), replace=False):
|
|
273
|
+
fig = myLCMSobj.mass_features[mf_id].plot(return_fig=True, plot_smoothed_eic=True, plot_eic_datapoints=True)
|
|
274
|
+
# Add the noise_score_max and dispersity_index to the subtitle
|
|
275
|
+
fig.suptitle(f"mf_id: {mf_id}, noise_score_max: {myLCMSobj.mass_features[mf_id].noise_score_max:.2f}, dispersity_index: {myLCMSobj.mass_features[mf_id].dispersity_index:.2f}")
|
|
276
|
+
fig.savefig(dropped_mf_dir / f"mf_{mf_id}_dropped.png", dpi=300, bbox_inches="tight")
|
|
277
|
+
plt.close(fig)
|
|
278
|
+
|
|
279
|
+
print("Number of mass features after filtering: ", len(mf_ids_to_keep), " out of ", len(my_df_og), " (", round(len(mf_ids_to_keep)/len(my_df_og)*100, 2), "% )")
|
|
280
|
+
print("Mass features filtered out due to dispersity_index >= 0.8 or noise_score_max <= 0.6")
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
def molecular_formula_search(myLCMSobj):
|
|
285
|
+
"""Perform molecular search on ms1 spectra
|
|
286
|
+
|
|
287
|
+
Parameters
|
|
288
|
+
----------
|
|
289
|
+
myLCMSobj : corems LCMS object
|
|
290
|
+
LCMS object to process
|
|
291
|
+
|
|
292
|
+
Returns
|
|
293
|
+
-------
|
|
294
|
+
None, processes the LCMS object
|
|
295
|
+
"""
|
|
296
|
+
mol_search = SearchMolecularFormulasLC(myLCMSobj)
|
|
297
|
+
mol_search.run_mass_feature_search()
|
|
298
|
+
print("Finished molecular search")
|
|
299
|
+
|
|
300
|
+
|
|
301
|
+
def export_results(myLCMSobj, out_path, molecular_metadata=None, final=False):
|
|
302
|
+
"""Export results to hdf5 and csv as a lipid report
|
|
303
|
+
|
|
304
|
+
Parameters
|
|
305
|
+
----------
|
|
306
|
+
myLCMSobj : corems LCMS object
|
|
307
|
+
LCMS object to process
|
|
308
|
+
out_path : str or Path
|
|
309
|
+
Path to output file
|
|
310
|
+
molecular_metadata : dict
|
|
311
|
+
Dict with molecular metadata
|
|
312
|
+
final : bool
|
|
313
|
+
Whether to export final results
|
|
314
|
+
|
|
315
|
+
Returns
|
|
316
|
+
-------
|
|
317
|
+
None, exports results to hdf5 and csv as a lipid report
|
|
318
|
+
"""
|
|
319
|
+
exporter = LipidomicsExport(out_path, myLCMSobj)
|
|
320
|
+
exporter.to_hdf(overwrite=True)
|
|
321
|
+
if final:
|
|
322
|
+
# Do not show warnings, these are expected
|
|
323
|
+
exporter.report_to_csv(molecular_metadata=molecular_metadata)
|
|
324
|
+
else:
|
|
325
|
+
with warnings.catch_warnings():
|
|
326
|
+
warnings.simplefilter("ignore")
|
|
327
|
+
exporter.report_to_csv()
|
|
328
|
+
|
|
329
|
+
|
|
330
|
+
def save_times(myLCMSobj, time_start, out_path, time_end=None):
|
|
331
|
+
"""Get times for processing steps
|
|
332
|
+
|
|
333
|
+
Parameters
|
|
334
|
+
----------
|
|
335
|
+
myLCMSobj : corems LCMS object
|
|
336
|
+
LCMS object to process
|
|
337
|
+
time_start : float
|
|
338
|
+
Start time of processing
|
|
339
|
+
out_path : str or Path
|
|
340
|
+
Path to output file
|
|
341
|
+
time_end : float
|
|
342
|
+
End time of processing
|
|
343
|
+
|
|
344
|
+
Returns
|
|
345
|
+
-------
|
|
346
|
+
None, writes out times to a file within the output directory
|
|
347
|
+
"""
|
|
348
|
+
# Check if out_path (with .corems) exisits
|
|
349
|
+
out_dir = Path(str(out_path) + ".corems/")
|
|
350
|
+
if not out_dir.exists():
|
|
351
|
+
print("Output directory does not exist")
|
|
352
|
+
|
|
353
|
+
time_toml_path = out_dir / "times.toml"
|
|
354
|
+
if not time_toml_path.exists():
|
|
355
|
+
raw_data_creation_time = myLCMSobj.spectra_parser.get_creation_time().strftime(
|
|
356
|
+
"%Y-%m-%dT%H:%M:%SZ"
|
|
357
|
+
)
|
|
358
|
+
processed_data_creation_time = time_start.strftime("%Y-%m-%dT%H:%M:%SZ")
|
|
359
|
+
time_dict = {
|
|
360
|
+
"raw_data_creation_time": raw_data_creation_time,
|
|
361
|
+
"metabolomics_workflow_start_time": processed_data_creation_time,
|
|
362
|
+
}
|
|
363
|
+
# save as a toml file
|
|
364
|
+
toml_string = toml.dumps(time_dict) # Output to a string
|
|
365
|
+
with open(time_toml_path, "w") as f:
|
|
366
|
+
f.write(toml_string)
|
|
367
|
+
elif time_toml_path.exists() and time_end is not None:
|
|
368
|
+
time_dict = toml.load(time_toml_path)
|
|
369
|
+
time_dict["metabolomics_workflow_end_time"] = time_end.strftime(
|
|
370
|
+
"%Y-%m-%dT%H:%M:%SZ"
|
|
371
|
+
)
|
|
372
|
+
toml_string = toml.dumps(time_dict)
|
|
373
|
+
with open(time_toml_path, "w") as f:
|
|
374
|
+
f.write(toml_string)
|
|
375
|
+
|
|
376
|
+
|
|
377
|
+
def process_ms2(myLCMSobj, metadata, scan_translator):
|
|
378
|
+
"""Process ms2 spectra and perform molecular search
|
|
379
|
+
|
|
380
|
+
Parameters
|
|
381
|
+
----------
|
|
382
|
+
myLCMSobj : corems LCMS object
|
|
383
|
+
LCMS object to process
|
|
384
|
+
metadata : dict
|
|
385
|
+
Dict with keys "mzs", "fe", and "molecular_metadata" with values of dicts of precursor mzs (negative and positive), flash entropy search databases (negative and positive), and molecular metadata, respectively
|
|
386
|
+
|
|
387
|
+
Returns
|
|
388
|
+
-------
|
|
389
|
+
None, processes the LCMS object
|
|
390
|
+
"""
|
|
391
|
+
# Perform molecular search on ms2 spectra
|
|
392
|
+
# Grab fe from metatdata associated with polarity (this is inherently high resolution as its from a in-silico high res library)
|
|
393
|
+
fe_search = metadata["fe"][myLCMSobj.polarity]
|
|
394
|
+
|
|
395
|
+
scan_dictionary = load_scan_translator(scan_translator)
|
|
396
|
+
ms2_scan_df = myLCMSobj.scan_df[myLCMSobj.scan_df.ms_level == 2]
|
|
397
|
+
|
|
398
|
+
# Process high resolution MS2 scans
|
|
399
|
+
# Collect all high resolution MS2 scans using the scan translator
|
|
400
|
+
for param_key in scan_dictionary.keys():
|
|
401
|
+
ms2_scans_oi_hr = []
|
|
402
|
+
if scan_dictionary[param_key]["resolution"] == "high":
|
|
403
|
+
scan_filter = scan_dictionary[param_key]["scan_filter"]
|
|
404
|
+
if scan_filter is not None:
|
|
405
|
+
ms2_scan_df_hr = ms2_scan_df[
|
|
406
|
+
ms2_scan_df.scan_text.str.contains(scan_filter)
|
|
407
|
+
]
|
|
408
|
+
else:
|
|
409
|
+
ms2_scan_df_hr = ms2_scan_df
|
|
410
|
+
ms2_scans_oi_hr_i = [
|
|
411
|
+
x for x in ms2_scan_df_hr.scan.tolist() if x in myLCMSobj._ms.keys()
|
|
412
|
+
]
|
|
413
|
+
ms2_scans_oi_hr.extend(ms2_scans_oi_hr_i)
|
|
414
|
+
# Perform search on high res scans
|
|
415
|
+
if len(ms2_scans_oi_hr) > 0:
|
|
416
|
+
myLCMSobj.fe_search(
|
|
417
|
+
scan_list=ms2_scans_oi_hr, fe_lib=fe_search, peak_sep_da=0.01
|
|
418
|
+
)
|
|
419
|
+
|
|
420
|
+
# Process low resolution MS2 scans
|
|
421
|
+
# Collect all low resolution MS2 scans using the scan translator
|
|
422
|
+
for param_key in scan_dictionary.keys():
|
|
423
|
+
ms2_scans_oi_lr = []
|
|
424
|
+
if scan_dictionary[param_key]["resolution"] == "low":
|
|
425
|
+
scan_filter = scan_dictionary[param_key]["scan_filter"]
|
|
426
|
+
if scan_filter is not None:
|
|
427
|
+
ms2_scan_df_lr = ms2_scan_df[
|
|
428
|
+
ms2_scan_df.scan_text.str.contains(scan_filter)
|
|
429
|
+
]
|
|
430
|
+
else:
|
|
431
|
+
ms2_scan_df_lr = ms2_scan_df
|
|
432
|
+
ms2_scans_oi_lri = [
|
|
433
|
+
x for x in ms2_scan_df_lr.scan.tolist() if x in myLCMSobj._ms.keys()
|
|
434
|
+
]
|
|
435
|
+
ms2_scans_oi_lr.extend(ms2_scans_oi_lri)
|
|
436
|
+
# Perform search on low res scans
|
|
437
|
+
if len(ms2_scans_oi_lr) > 0:
|
|
438
|
+
# Recast the flashentropy search database to low resolution
|
|
439
|
+
lipid_library = LCLipidLibraryInterface()
|
|
440
|
+
fe_search_lr = lipid_library._to_flashentropy(
|
|
441
|
+
spectral_library=fe_search,
|
|
442
|
+
normalize=True,
|
|
443
|
+
fe_kwargs={
|
|
444
|
+
"normalize_intensity": True,
|
|
445
|
+
"min_ms2_difference_in_da": 0.4,
|
|
446
|
+
"max_ms2_tolerance_in_da": 0.2,
|
|
447
|
+
"max_indexed_mz": 3000,
|
|
448
|
+
"precursor_ions_removal_da": None,
|
|
449
|
+
"noise_threshold": 0,
|
|
450
|
+
},
|
|
451
|
+
)
|
|
452
|
+
myLCMSobj.fe_search(
|
|
453
|
+
scan_list=ms2_scans_oi_lr, fe_lib=fe_search_lr, peak_sep_da=0.3
|
|
454
|
+
)
|
|
455
|
+
|
|
456
|
+
|
|
457
|
+
def run_lipid_sp_ms1(
|
|
458
|
+
file_in,
|
|
459
|
+
out_path,
|
|
460
|
+
params_toml,
|
|
461
|
+
scan_translator=None,
|
|
462
|
+
verbose=True,
|
|
463
|
+
return_mzs=True,
|
|
464
|
+
ms1_molecular_search=True,
|
|
465
|
+
):
|
|
466
|
+
"""Run signal processing, get associated ms1, add associated ms2, do ms1 molecular search, and export intermediate results
|
|
467
|
+
|
|
468
|
+
Parameters
|
|
469
|
+
----------
|
|
470
|
+
file_in : str or Path
|
|
471
|
+
Path to binary file
|
|
472
|
+
out_path : str or Path
|
|
473
|
+
Path to output file
|
|
474
|
+
params_toml : str or Path
|
|
475
|
+
Path to toml file with parameters
|
|
476
|
+
verbose : bool
|
|
477
|
+
Whether to print verbose output
|
|
478
|
+
return_mzs : bool
|
|
479
|
+
Whether to return precursor mzs
|
|
480
|
+
|
|
481
|
+
Returns
|
|
482
|
+
-------
|
|
483
|
+
mz_dict : dict
|
|
484
|
+
Dict with keys "positive" and "negative" and values of lists of precursor mzs
|
|
485
|
+
"""
|
|
486
|
+
time_start = datetime.datetime.now()
|
|
487
|
+
myLCMSobj = instantiate_lcms_obj(file_in)
|
|
488
|
+
set_params_on_lcms_obj(myLCMSobj, params_toml, verbose)
|
|
489
|
+
check_scan_translator(myLCMSobj, scan_translator)
|
|
490
|
+
add_mass_features(myLCMSobj, scan_translator)
|
|
491
|
+
myLCMSobj.remove_unprocessed_data()
|
|
492
|
+
# myLCMSobj.parameters.mass_spectrum['ms1'].molecular_search.verbose_processing = False
|
|
493
|
+
if ms1_molecular_search:
|
|
494
|
+
molecular_formula_search(myLCMSobj)
|
|
495
|
+
export_results(myLCMSobj, out_path=out_path, final=False)
|
|
496
|
+
save_times(myLCMSobj, time_start, out_path)
|
|
497
|
+
if return_mzs:
|
|
498
|
+
precursor_mz_list = list(
|
|
499
|
+
set(
|
|
500
|
+
[
|
|
501
|
+
v.mz
|
|
502
|
+
for k, v in myLCMSobj.mass_features.items()
|
|
503
|
+
if len(v.ms2_scan_numbers) > 0 and v.isotopologue_type is None
|
|
504
|
+
]
|
|
505
|
+
)
|
|
506
|
+
)
|
|
507
|
+
mz_dict = {myLCMSobj.polarity: precursor_mz_list}
|
|
508
|
+
return mz_dict
|
|
509
|
+
|
|
510
|
+
|
|
511
|
+
def prep_metadata(mz_dicts, out_dir, db_location):
|
|
512
|
+
"""Prepare metadata for ms2 spectral search
|
|
513
|
+
|
|
514
|
+
Parameters
|
|
515
|
+
----------
|
|
516
|
+
mz_dicts : list of dicts
|
|
517
|
+
List of dicts with keys "positive" and "negative" and values of lists of precursor mzs
|
|
518
|
+
out_dir : Path
|
|
519
|
+
Path to output directory
|
|
520
|
+
db_location : str | Path
|
|
521
|
+
Path to local lipid sqlite library.
|
|
522
|
+
|
|
523
|
+
Returns
|
|
524
|
+
-------
|
|
525
|
+
metadata : dict
|
|
526
|
+
Dict with keys "mzs", "fe", and "molecular_metadata" with values of dicts of precursor mzs (negative and positive), flash entropy search databases (negative and positive), and molecular metadata, respectively
|
|
527
|
+
|
|
528
|
+
Notes
|
|
529
|
+
-------
|
|
530
|
+
Also writes out files for the flash entropy search databases and molecular metadata
|
|
531
|
+
"""
|
|
532
|
+
metadata = {
|
|
533
|
+
"mzs": {"positive": None, "negative": None},
|
|
534
|
+
"fe": {"positive": None, "negative": None},
|
|
535
|
+
"molecular_metadata": {},
|
|
536
|
+
}
|
|
537
|
+
for d in mz_dicts:
|
|
538
|
+
metadata["mzs"].update(d)
|
|
539
|
+
|
|
540
|
+
lipid_library = LCLipidLibraryInterface(db_location=db_location)
|
|
541
|
+
|
|
542
|
+
print("Preparing positive lipid library")
|
|
543
|
+
if metadata["mzs"]["positive"] is not None:
|
|
544
|
+
positive_library, lipidmetadata_positive = lipid_library.get_lipid_library(
|
|
545
|
+
mz_list=metadata["mzs"]["positive"],
|
|
546
|
+
polarity="positive",
|
|
547
|
+
mz_tol_ppm=5,
|
|
548
|
+
format="flashentropy",
|
|
549
|
+
normalize=True,
|
|
550
|
+
fe_kwargs={
|
|
551
|
+
"normalize_intensity": True,
|
|
552
|
+
"min_ms2_difference_in_da": 0.02, # for cleaning spectra
|
|
553
|
+
"max_ms2_tolerance_in_da": 0.01, # for setting search space
|
|
554
|
+
"max_indexed_mz": 3000,
|
|
555
|
+
"precursor_ions_removal_da": None,
|
|
556
|
+
"noise_threshold": 0,
|
|
557
|
+
},
|
|
558
|
+
)
|
|
559
|
+
metadata["fe"]["positive"] = positive_library
|
|
560
|
+
metadata["molecular_metadata"].update(lipidmetadata_positive)
|
|
561
|
+
fe_positive_df = pd.DataFrame.from_dict(
|
|
562
|
+
{k: v for k, v in enumerate(metadata["fe"]["positive"])}, orient="index"
|
|
563
|
+
)
|
|
564
|
+
fe_positive_df.to_csv(out_dir / "ms2_db_positive.csv")
|
|
565
|
+
|
|
566
|
+
print("Preparing negative lipid library")
|
|
567
|
+
if metadata["mzs"]["negative"] is not None:
|
|
568
|
+
negative_library, lipidmetadata_negative = lipid_library.get_lipid_library(
|
|
569
|
+
mz_list=metadata["mzs"]["negative"],
|
|
570
|
+
polarity="negative",
|
|
571
|
+
mz_tol_ppm=5,
|
|
572
|
+
mz_tol_da_api=0.01,
|
|
573
|
+
format="flashentropy",
|
|
574
|
+
normalize=True,
|
|
575
|
+
fe_kwargs={
|
|
576
|
+
"normalize_intensity": True,
|
|
577
|
+
"min_ms2_difference_in_da": 0.02, # for cleaning spectra
|
|
578
|
+
"max_ms2_tolerance_in_da": 0.01, # for setting search space
|
|
579
|
+
"max_indexed_mz": 3000,
|
|
580
|
+
"precursor_ions_removal_da": None,
|
|
581
|
+
"noise_threshold": 0,
|
|
582
|
+
},
|
|
583
|
+
)
|
|
584
|
+
metadata["fe"]["negative"] = negative_library
|
|
585
|
+
metadata["molecular_metadata"].update(lipidmetadata_negative)
|
|
586
|
+
fe_negative_df = pd.DataFrame.from_dict(
|
|
587
|
+
{k: v for k, v in enumerate(metadata["fe"]["negative"])}, orient="index"
|
|
588
|
+
)
|
|
589
|
+
fe_negative_df.to_csv(out_dir / "ms2_db_negative.csv")
|
|
590
|
+
|
|
591
|
+
mol_metadata_df = pd.concat(
|
|
592
|
+
[
|
|
593
|
+
pd.DataFrame.from_dict(v.__dict__, orient="index").transpose()
|
|
594
|
+
for k, v in metadata["molecular_metadata"].items()
|
|
595
|
+
],
|
|
596
|
+
ignore_index=True,
|
|
597
|
+
)
|
|
598
|
+
mol_metadata_df.to_csv(out_dir / "molecular_metadata.csv")
|
|
599
|
+
return metadata
|
|
600
|
+
|
|
601
|
+
|
|
602
|
+
def run_lipid_ms2(out_path, metadata, scan_translator=None):
|
|
603
|
+
"""Run ms2 spectral search and export final results
|
|
604
|
+
|
|
605
|
+
Parameters
|
|
606
|
+
----------
|
|
607
|
+
out_path : str or Path
|
|
608
|
+
Path to output file
|
|
609
|
+
metadata : dict
|
|
610
|
+
Dict with keys "mzs", "fe", and "molecular_metadata" with values of dicts of precursor mzs (negative and positive), flash entropy search databases (negative and positive), and molecular metadata, respectively
|
|
611
|
+
|
|
612
|
+
Returns
|
|
613
|
+
-------
|
|
614
|
+
None, runs ms2 spectral search and exports final results
|
|
615
|
+
"""
|
|
616
|
+
# Read in the intermediate results
|
|
617
|
+
out_path_hdf5 = str(out_path) + ".corems/" + out_path.stem + ".hdf5"
|
|
618
|
+
parser = ReadCoreMSHDFMassSpectra(out_path_hdf5)
|
|
619
|
+
myLCMSobj = parser.get_lcms_obj()
|
|
620
|
+
|
|
621
|
+
# Process ms2 spectra, perform spectral search, and export final results
|
|
622
|
+
process_ms2(myLCMSobj, metadata, scan_translator=scan_translator)
|
|
623
|
+
export_results(myLCMSobj, str(out_path), metadata["molecular_metadata"], final=True)
|
|
624
|
+
time_end = datetime.datetime.now()
|
|
625
|
+
save_times(myLCMSobj, time_start=None, out_path=out_path, time_end=time_end)
|
|
626
|
+
|
|
627
|
+
|
|
628
|
+
def run_lipid_workflow(
|
|
629
|
+
file_dir,
|
|
630
|
+
out_dir,
|
|
631
|
+
params_toml,
|
|
632
|
+
db_location,
|
|
633
|
+
scan_translator=None,
|
|
634
|
+
verbose=True,
|
|
635
|
+
ms1_molecular_search=False, # whether to do ms1 molecular search
|
|
636
|
+
cores=1,
|
|
637
|
+
):
|
|
638
|
+
"""Run lipidomics workflow
|
|
639
|
+
|
|
640
|
+
Parameters
|
|
641
|
+
----------
|
|
642
|
+
file_dir : str or Path
|
|
643
|
+
Path to directory with raw or mzml lipid files
|
|
644
|
+
out_dir : str or Path
|
|
645
|
+
Path to output directory
|
|
646
|
+
params_toml : str or Path
|
|
647
|
+
Path to toml file with parameters
|
|
648
|
+
db_location : str or Path
|
|
649
|
+
Path to local lipid sqlite library
|
|
650
|
+
verbose : bool
|
|
651
|
+
Whether to print verbose output
|
|
652
|
+
cores : int
|
|
653
|
+
Number of cores to use
|
|
654
|
+
|
|
655
|
+
Returns
|
|
656
|
+
-------
|
|
657
|
+
None, runs lipidomics workflow and exports final results
|
|
658
|
+
"""
|
|
659
|
+
# Make output dir and get list of files to process
|
|
660
|
+
out_dir.mkdir(parents=True, exist_ok=True)
|
|
661
|
+
files_list = list(file_dir.glob("*.raw"))
|
|
662
|
+
out_paths_list = [out_dir / f.stem for f in files_list]
|
|
663
|
+
|
|
664
|
+
# Run signal processing, get associated ms1, add associated ms2, and export temp results
|
|
665
|
+
if cores == 1 or len(files_list) == 1:
|
|
666
|
+
mz_dicts = []
|
|
667
|
+
for file_in, file_out in list(zip(files_list, out_paths_list)):
|
|
668
|
+
# Check if folder already exists
|
|
669
|
+
if Path(str(file_out) + ".corems").exists():
|
|
670
|
+
print("File already exists, skipping: ", file_out)
|
|
671
|
+
continue
|
|
672
|
+
if verbose:
|
|
673
|
+
print("Processing file: ", file_in)
|
|
674
|
+
mz_dict = run_lipid_sp_ms1(
|
|
675
|
+
file_in=str(file_in),
|
|
676
|
+
out_path=str(file_out),
|
|
677
|
+
params_toml=params_toml,
|
|
678
|
+
scan_translator=scan_translator,
|
|
679
|
+
verbose=verbose,
|
|
680
|
+
ms1_molecular_search=ms1_molecular_search,
|
|
681
|
+
)
|
|
682
|
+
mz_dicts.append(mz_dict)
|
|
683
|
+
elif cores > 1:
|
|
684
|
+
pool = Pool(cores)
|
|
685
|
+
args = [
|
|
686
|
+
(
|
|
687
|
+
str(file_in),
|
|
688
|
+
str(file_out),
|
|
689
|
+
params_toml,
|
|
690
|
+
scan_translator,
|
|
691
|
+
verbose,
|
|
692
|
+
ms1_molecular_search,
|
|
693
|
+
)
|
|
694
|
+
for file_in, file_out in list(zip(files_list, out_paths_list))
|
|
695
|
+
]
|
|
696
|
+
mz_dicts = pool.starmap(run_lipid_sp_ms1, args)
|
|
697
|
+
pool.close()
|
|
698
|
+
pool.join()
|
|
699
|
+
|
|
700
|
+
# Skip ms2 spectral search for now, will add back once we have an improved MetabRefLCInterface method
|
|
701
|
+
"""
|
|
702
|
+
# Prepare ms2 spectral search space
|
|
703
|
+
metadata = prep_metadata(mz_dicts, out_dir, db_location)
|
|
704
|
+
|
|
705
|
+
# Run ms2 spectral search and export final results
|
|
706
|
+
if cores == 1 or len(files_list) == 1:
|
|
707
|
+
for file_out in out_paths_list:
|
|
708
|
+
mz_dicts = run_lipid_ms2(
|
|
709
|
+
file_out, metadata, scan_translator=scan_translator
|
|
710
|
+
)
|
|
711
|
+
elif cores > 1:
|
|
712
|
+
pool = Pool(cores)
|
|
713
|
+
args = [(file_out, metadata, scan_translator) for file_out in out_paths_list]
|
|
714
|
+
mz_dicts = pool.starmap(run_lipid_ms2, args)
|
|
715
|
+
pool.close()
|
|
716
|
+
pool.join()
|
|
717
|
+
"""
|
|
718
|
+
print("Finished processing, data are written in " + str(out_dir))
|
|
719
|
+
|
|
720
|
+
|
|
721
|
+
if __name__ == "__main__":
|
|
722
|
+
# Set input variables to run
|
|
723
|
+
cores = 5
|
|
724
|
+
file_dir = Path("/Volumes/LaCie/nmdc_data/collection_testing/blanchard_lipid/mini_collection_test")
|
|
725
|
+
out_dir = Path("/Volumes/LaCie/nmdc_data/collection_testing/blanchard_lipid/mini_collection_test_out2")
|
|
726
|
+
params_toml = Path(
|
|
727
|
+
"/Volumes/LaCie/nmdc_data/collection_testing/blanchard_lipid/blanchard_collection_params.toml"
|
|
728
|
+
)
|
|
729
|
+
db_location = Path("tests/tests_data/lcms/202412_lipid_ref.sqlite")
|
|
730
|
+
verbose = True
|
|
731
|
+
scan_translator = Path("tmp_data/thermo_raw_collection/scan_translator.toml")
|
|
732
|
+
|
|
733
|
+
# Set up output directory
|
|
734
|
+
out_dir.mkdir(parents=True, exist_ok=True)
|
|
735
|
+
|
|
736
|
+
# if cores > 1, don't use verbose output
|
|
737
|
+
if cores > 2:
|
|
738
|
+
verbose = False
|
|
739
|
+
|
|
740
|
+
run_lipid_workflow(
|
|
741
|
+
file_dir=file_dir,
|
|
742
|
+
out_dir=out_dir,
|
|
743
|
+
params_toml=params_toml,
|
|
744
|
+
db_location=db_location,
|
|
745
|
+
scan_translator=scan_translator,
|
|
746
|
+
verbose=verbose,
|
|
747
|
+
cores=cores,
|
|
748
|
+
)
|