CoreMS 4.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (171) hide show
  1. corems/__init__.py +63 -0
  2. corems/chroma_peak/__init__.py +0 -0
  3. corems/chroma_peak/calc/ChromaPeakCalc.py +480 -0
  4. corems/chroma_peak/calc/__init__.py +0 -0
  5. corems/chroma_peak/calc/subset.py +196 -0
  6. corems/chroma_peak/factory/__init__.py +0 -0
  7. corems/chroma_peak/factory/chroma_peak_classes.py +1178 -0
  8. corems/encapsulation/__init__.py +0 -0
  9. corems/encapsulation/constant.py +1283 -0
  10. corems/encapsulation/factory/__init__.py +0 -0
  11. corems/encapsulation/factory/parameters.py +392 -0
  12. corems/encapsulation/factory/processingSetting.py +1244 -0
  13. corems/encapsulation/input/__init__.py +0 -0
  14. corems/encapsulation/input/parameter_from_json.py +579 -0
  15. corems/encapsulation/output/__init__.py +0 -0
  16. corems/encapsulation/output/parameter_to_dict.py +142 -0
  17. corems/encapsulation/output/parameter_to_json.py +332 -0
  18. corems/mass_spectra/__init__.py +0 -0
  19. corems/mass_spectra/calc/GC_Calc.py +84 -0
  20. corems/mass_spectra/calc/GC_Deconvolution.py +558 -0
  21. corems/mass_spectra/calc/GC_RI_Calibration.py +44 -0
  22. corems/mass_spectra/calc/MZSearch.py +249 -0
  23. corems/mass_spectra/calc/SignalProcessing.py +656 -0
  24. corems/mass_spectra/calc/__init__.py +0 -0
  25. corems/mass_spectra/calc/lc_calc.py +5790 -0
  26. corems/mass_spectra/calc/lc_calc_operations.py +1127 -0
  27. corems/mass_spectra/factory/GC_Class.py +791 -0
  28. corems/mass_spectra/factory/__init__.py +0 -0
  29. corems/mass_spectra/factory/chromat_data.py +51 -0
  30. corems/mass_spectra/factory/lc_class.py +2721 -0
  31. corems/mass_spectra/input/__init__.py +0 -0
  32. corems/mass_spectra/input/andiNetCDF.py +200 -0
  33. corems/mass_spectra/input/boosterHDF5.py +216 -0
  34. corems/mass_spectra/input/brukerSolarix.py +153 -0
  35. corems/mass_spectra/input/brukerSolarix_utils.py +73 -0
  36. corems/mass_spectra/input/corems_hdf5.py +1710 -0
  37. corems/mass_spectra/input/massList.py +133 -0
  38. corems/mass_spectra/input/mzml.py +668 -0
  39. corems/mass_spectra/input/parserbase.py +239 -0
  40. corems/mass_spectra/input/rawFileReader.py +1839 -0
  41. corems/mass_spectra/output/__init__.py +0 -0
  42. corems/mass_spectra/output/export.py +2800 -0
  43. corems/mass_spectrum/__init__.py +0 -0
  44. corems/mass_spectrum/calc/AutoRecalibration.py +237 -0
  45. corems/mass_spectrum/calc/Calibration.py +602 -0
  46. corems/mass_spectrum/calc/CalibrationCalc.py +253 -0
  47. corems/mass_spectrum/calc/KendrickGroup.py +239 -0
  48. corems/mass_spectrum/calc/MassErrorPrediction.py +436 -0
  49. corems/mass_spectrum/calc/MassSpectrumCalc.py +303 -0
  50. corems/mass_spectrum/calc/MeanResolvingPowerFilter.py +212 -0
  51. corems/mass_spectrum/calc/NoiseCalc.py +371 -0
  52. corems/mass_spectrum/calc/NoiseCalc_Bayes.py +93 -0
  53. corems/mass_spectrum/calc/PeakPicking.py +994 -0
  54. corems/mass_spectrum/calc/__init__.py +0 -0
  55. corems/mass_spectrum/factory/MassSpectrumClasses.py +1753 -0
  56. corems/mass_spectrum/factory/__init__.py +0 -0
  57. corems/mass_spectrum/input/__init__.py +0 -0
  58. corems/mass_spectrum/input/baseClass.py +531 -0
  59. corems/mass_spectrum/input/boosterHDF5.py +161 -0
  60. corems/mass_spectrum/input/coremsHDF5.py +475 -0
  61. corems/mass_spectrum/input/massList.py +402 -0
  62. corems/mass_spectrum/input/numpyArray.py +133 -0
  63. corems/mass_spectrum/output/__init__.py +0 -0
  64. corems/mass_spectrum/output/export.py +841 -0
  65. corems/molecular_formula/__init__.py +0 -0
  66. corems/molecular_formula/calc/MolecularFormulaCalc.py +885 -0
  67. corems/molecular_formula/calc/__init__.py +0 -0
  68. corems/molecular_formula/factory/MolecularFormulaFactory.py +895 -0
  69. corems/molecular_formula/factory/__init__.py +0 -0
  70. corems/molecular_formula/input/__init__.py +0 -0
  71. corems/molecular_formula/input/masslist_ref.py +355 -0
  72. corems/molecular_id/__init__.py +0 -0
  73. corems/molecular_id/calc/ClusterFilter.py +251 -0
  74. corems/molecular_id/calc/MolecularFilter.py +122 -0
  75. corems/molecular_id/calc/SpectralSimilarity.py +632 -0
  76. corems/molecular_id/calc/__init__.py +0 -0
  77. corems/molecular_id/calc/math_distance.py +1637 -0
  78. corems/molecular_id/data/FAMES_REF.msp +980 -0
  79. corems/molecular_id/data/PNNLMetV20191015.msp +157267 -0
  80. corems/molecular_id/factory/EI_SQL.py +650 -0
  81. corems/molecular_id/factory/MolecularLookupTable.py +914 -0
  82. corems/molecular_id/factory/__init__.py +0 -0
  83. corems/molecular_id/factory/classification.py +884 -0
  84. corems/molecular_id/factory/lipid_molecular_metadata.py +50 -0
  85. corems/molecular_id/factory/molecularSQL.py +827 -0
  86. corems/molecular_id/factory/spectrum_search_results.py +119 -0
  87. corems/molecular_id/input/__init__.py +0 -0
  88. corems/molecular_id/input/nistMSI.py +148 -0
  89. corems/molecular_id/search/__init__.py +0 -0
  90. corems/molecular_id/search/compoundSearch.py +214 -0
  91. corems/molecular_id/search/database_interfaces.py +1527 -0
  92. corems/molecular_id/search/findOxygenPeaks.py +330 -0
  93. corems/molecular_id/search/lcms_spectral_search.py +348 -0
  94. corems/molecular_id/search/molecularFormulaSearch.py +1117 -0
  95. corems/molecular_id/search/priorityAssignment.py +723 -0
  96. corems/ms_peak/__init__.py +0 -0
  97. corems/ms_peak/calc/MSPeakCalc.py +1010 -0
  98. corems/ms_peak/calc/__init__.py +0 -0
  99. corems/ms_peak/factory/MSPeakClasses.py +542 -0
  100. corems/ms_peak/factory/__init__.py +0 -0
  101. corems/transient/__init__.py +0 -0
  102. corems/transient/calc/TransientCalc.py +362 -0
  103. corems/transient/calc/__init__.py +0 -0
  104. corems/transient/factory/TransientClasses.py +457 -0
  105. corems/transient/factory/__init__.py +0 -0
  106. corems/transient/input/__init__.py +0 -0
  107. corems/transient/input/brukerSolarix.py +461 -0
  108. corems/transient/input/midasDatFile.py +172 -0
  109. corems-4.0.0.dist-info/METADATA +475 -0
  110. corems-4.0.0.dist-info/RECORD +171 -0
  111. corems-4.0.0.dist-info/WHEEL +5 -0
  112. corems-4.0.0.dist-info/licenses/LICENSE +22 -0
  113. corems-4.0.0.dist-info/top_level.txt +4 -0
  114. examples/archive/scripts/CoreMS_tutorial.py +94 -0
  115. examples/archive/scripts/DI HR-MS Halogens Bruker.py +196 -0
  116. examples/archive/scripts/DI HR-MS MassList.py +385 -0
  117. examples/archive/scripts/GC-MS MetabRef.py +213 -0
  118. examples/archive/scripts/GC-MS NetCDF.py +217 -0
  119. examples/archive/scripts/HR-MS Thermo Raw 21T.py +136 -0
  120. examples/archive/scripts/LC-ICPMS_metal_peaks.py +297 -0
  121. examples/archive/scripts/LCMS-Thermo.py +460 -0
  122. examples/archive/scripts/LCMS_isotopes.py +283 -0
  123. examples/archive/scripts/MSParams_example.py +21 -0
  124. examples/archive/scripts/Molecular Formula Data Aggreation.py +84 -0
  125. examples/archive/scripts/Single Mz Search.py +69 -0
  126. examples/test_notebooks.py +145 -0
  127. ext_lib/ChemstationMSFileReader.dll +0 -0
  128. ext_lib/ChemstationMSFileReader.xml +126 -0
  129. ext_lib/RawFileReaderLicense.doc +0 -0
  130. ext_lib/ThermoFisher.CommonCore.BackgroundSubtraction.dll +0 -0
  131. ext_lib/ThermoFisher.CommonCore.BackgroundSubtraction.xml +2307 -0
  132. ext_lib/ThermoFisher.CommonCore.Data.dll +0 -0
  133. ext_lib/ThermoFisher.CommonCore.Data.xml +28974 -0
  134. ext_lib/ThermoFisher.CommonCore.MassPrecisionEstimator.dll +0 -0
  135. ext_lib/ThermoFisher.CommonCore.MassPrecisionEstimator.xml +241 -0
  136. ext_lib/ThermoFisher.CommonCore.RawFileReader.dll +0 -0
  137. ext_lib/ThermoFisher.CommonCore.RawFileReader.xml +31174 -0
  138. ext_lib/__init__.py +0 -0
  139. ext_lib/dotnet/OpenMcdf.Extensions.dll +0 -0
  140. ext_lib/dotnet/OpenMcdf.dll +0 -0
  141. ext_lib/dotnet/OpenMcdf.xml +1154 -0
  142. ext_lib/dotnet/System.IO.FileSystem.AccessControl.dll +0 -0
  143. ext_lib/dotnet/System.IO.FileSystem.AccessControl.xml +506 -0
  144. ext_lib/dotnet/System.Security.AccessControl.dll +0 -0
  145. ext_lib/dotnet/System.Security.AccessControl.xml +2043 -0
  146. ext_lib/dotnet/System.Security.Principal.Windows.dll +0 -0
  147. ext_lib/dotnet/System.Security.Principal.Windows.xml +1011 -0
  148. ext_lib/dotnet/ThermoFisher.CommonCore.BackgroundSubtraction.dll +0 -0
  149. ext_lib/dotnet/ThermoFisher.CommonCore.BackgroundSubtraction.xml +2307 -0
  150. ext_lib/dotnet/ThermoFisher.CommonCore.Data.dll +0 -0
  151. ext_lib/dotnet/ThermoFisher.CommonCore.Data.xml +29148 -0
  152. ext_lib/dotnet/ThermoFisher.CommonCore.MassPrecisionEstimator.dll +0 -0
  153. ext_lib/dotnet/ThermoFisher.CommonCore.MassPrecisionEstimator.xml +241 -0
  154. ext_lib/dotnet/ThermoFisher.CommonCore.RawFileReader.dll +0 -0
  155. ext_lib/dotnet/ThermoFisher.CommonCore.RawFileReader.xml +31492 -0
  156. ext_lib/version +18 -0
  157. support_code/atom_parsers/AtomsDescription.py +359 -0
  158. support_code/atom_parsers/CreateAtomsDescription.py +56 -0
  159. support_code/nmdc/filefinder.py +90 -0
  160. support_code/nmdc/lipidomics/lipidomics_workflow.py +748 -0
  161. support_code/nmdc/lipidomics/manifest_examples.py +49 -0
  162. support_code/nmdc/metabolomics/gcms_workflow.py +158 -0
  163. support_code/nmdc/metabolomics/lcms_metabolomics_targeted_search.py +59 -0
  164. support_code/nmdc/metabolomics/lcms_metabolomics_workflow.py +248 -0
  165. support_code/nmdc/metabolomics/metabolomics_collection.py +628 -0
  166. support_code/nmdc/metadata/dms_api.py +42 -0
  167. support_code/nmdc/nom/archived_scripts/nmdc_metadata_gen.py +288 -0
  168. support_code/nmdc/nom/archived_scripts/nom_grow_workflow.py +209 -0
  169. support_code/nmdc/nom/nom_workflow.py +312 -0
  170. support_code/windows_only_importers/BrukerCompassXtract.py +180 -0
  171. support_code/windows_only_importers/ThermoMSFileReader.py +405 -0
@@ -0,0 +1,49 @@
1
+ """
2
+ Simple examples demonstrating manifest creation utility usage.
3
+ """
4
+
5
+ from pathlib import Path
6
+ from corems.mass_spectra.input.corems_hdf5 import create_manifest_from_folder
7
+
8
+ # Example 1: Basic usage - auto-select middle sample as center
9
+ print("Example 1: Basic usage (middle sample as center)")
10
+ print("-" * 60)
11
+ manifest_path = create_manifest_from_folder(
12
+ folder_path=Path("/Volumes/LaCie/nmdc_data/collection_testing/blanchard_lipid/mini_collection_test_out2"),
13
+ overwrite=True
14
+ )
15
+ print()
16
+
17
+ # Example 2: Custom batch threshold
18
+ print("Example 2: Custom batch threshold (24 hours)")
19
+ print("-" * 60)
20
+ manifest_path = create_manifest_from_folder(
21
+ folder_path=Path("/Volumes/LaCie/nmdc_data/collection_testing/blanchard_lipid/mini_collection_test_out2"),
22
+ output_path=Path("/Volumes/LaCie/nmdc_data/collection_testing/blanchard_lipid/mini_collection_test_out2/manifest_24hr.csv"),
23
+ batch_time_threshold_hours=24.0,
24
+ overwrite=True
25
+ )
26
+ print()
27
+
28
+ # Example 3: Specify a sample as center by name
29
+ print("Example 3: Specify center sample by name")
30
+ print("-" * 60)
31
+ manifest_path = create_manifest_from_folder(
32
+ folder_path=Path("/Volumes/LaCie/nmdc_data/collection_testing/blanchard_lipid/mini_collection_test_out2"),
33
+ output_path=Path("/Volumes/LaCie/nmdc_data/collection_testing/blanchard_lipid/mini_collection_test_out2/manifest_custom_center.csv"),
34
+ batch_time_threshold_hours=12.0,
35
+ center_name="Blanch_Nat_Lip_C_7_AB_M_07_POS_23Jan18_Brandi-WCSH5801",
36
+ overwrite=True
37
+ )
38
+ print()
39
+
40
+ # Example 4: Strict batch threshold
41
+ print("Example 4: Strict batch threshold (1 hour)")
42
+ print("-" * 60)
43
+ manifest_path = create_manifest_from_folder(
44
+ folder_path=Path("/Volumes/LaCie/nmdc_data/collection_testing/blanchard_lipid/mini_collection_test_out2"),
45
+ output_path=Path("/Volumes/LaCie/nmdc_data/collection_testing/blanchard_lipid/mini_collection_test_out2/manifest_1hr.csv"),
46
+ batch_time_threshold_hours=1.0,
47
+ overwrite=True
48
+ )
49
+ print()
@@ -0,0 +1,158 @@
1
+ import warnings
2
+ warnings.filterwarnings("ignore")
3
+
4
+ import sys
5
+ sys.path.append("./")
6
+
7
+ from pathlib import Path
8
+ from multiprocessing import Pool
9
+ import cProfile
10
+
11
+
12
+ from corems.molecular_id.input.nistMSI import ReadNistMSI
13
+ from corems.mass_spectra.input.andiNetCDF import ReadAndiNetCDF
14
+ from corems.molecular_id.search.compoundSearch import LowResMassSpectralMatch
15
+ from corems.mass_spectra.calc.GC_RI_Calibration import get_rt_ri_pairs
16
+ from support_code.nmdc.filefinder import get_dirname, get_filename
17
+
18
+ import glob
19
+ from nmdc.metadata.nmdc_registration import NMDC_Metadata
20
+
21
+ def start_sql_from_file():
22
+
23
+ ref_lib_path = Path.cwd() / "tests/tests_data/gcms/" / "PNNLMetV20191015.MSL"
24
+ sql_obj = ReadNistMSI(ref_lib_path).get_sqlLite_obj()
25
+ return sql_obj
26
+
27
+
28
+ def get_gcms(file_path):
29
+
30
+ reader_gcms = ReadAndiNetCDF(file_path)
31
+
32
+ reader_gcms.run()
33
+
34
+ gcms = reader_gcms.get_gcms_obj()
35
+
36
+ # gcms.process_chromatogram()
37
+
38
+ return gcms
39
+
40
+ def get_reference_dict(calibration_file_path=False):
41
+
42
+ from PySide2.QtWidgets import QFileDialog, QApplication
43
+ from PySide2.QtCore import Qt
44
+
45
+ if not calibration_file_path:
46
+ app = QApplication(sys.argv)
47
+ file_dialog = QFileDialog()
48
+ file_dialog.setWindowFlags(Qt.WindowStaysOnTopHint)
49
+ file_path = file_dialog.getOpenFileName(None, "FAMES REF FILE", filter="*.cdf")[0]
50
+ file_dialog.close()
51
+ app.exit()
52
+ else:
53
+ file_path = calibration_file_path
54
+
55
+ if not file_path:
56
+ return None
57
+
58
+ else:
59
+
60
+ gcms_ref_obj = get_gcms(file_path)
61
+ # sql_obj = start_sql_from_file()
62
+ rt_ri_pairs = get_rt_ri_pairs(gcms_ref_obj) # sql_obj=sql_obj)
63
+ # !!!!!! READ !!!!! use the previous two lines if db/pnnl_lowres_gcms_compounds.sqlite does not exist
64
+ # and comment the next line
65
+ # rt_ri_pairs = get_rt_ri_pairs(gcms_ref_obj)
66
+
67
+ return rt_ri_pairs, file_path
68
+
69
+ def run(args):
70
+
71
+ file_path, ref_dict, cal_file_path = args
72
+
73
+ gcms = get_gcms(file_path)
74
+
75
+ gcms.process_chromatogram()
76
+
77
+ gcms.calibrate_ri(ref_dict, cal_file_path)
78
+
79
+ # sql_obj = start_sql_from_file()
80
+
81
+ lowResSearch = LowResMassSpectralMatch(gcms) # sql_obj=sql_obj)
82
+ # !!!!!! READ !!!!! use the previous two lines if db/pnnl_lowres_gcms_compounds.sqlite does not exist
83
+ # and comment the next line
84
+ # lowResSearch = LowResMassSpectralMatch(gcms)
85
+ lowResSearch.run()
86
+
87
+ return gcms
88
+
89
+ def calibrate_and_search(out_put_file_name, jobs, dms_file_path):
90
+
91
+ from PySide2.QtWidgets import QFileDialog
92
+ from PySide2.QtCore import Qt
93
+
94
+ ref_dict, cal_file_path = get_reference_dict()
95
+ if ref_dict:
96
+
97
+ file_dialog = QFileDialog()
98
+ file_dialog.setWindowFlags(Qt.WindowStaysOnTopHint)
99
+
100
+ if file_dialog:
101
+
102
+ file_locations = file_dialog.getOpenFileNames(None, "Standard Compounds Files", filter="*.cdf")
103
+ file_dialog.close()
104
+
105
+ # run in multiprocessing mode
106
+ pool = Pool(jobs)
107
+ args = [(file_path, ref_dict, cal_file_path) for file_path in file_locations[0]]
108
+ gcmss = pool.map(run, args)
109
+ pool.close()
110
+ pool.join()
111
+
112
+ for file_index, gcms in enumerate(gcmss):
113
+
114
+ file_path = Path(file_locations[0][file_index])
115
+ # print(out_put_file_name)
116
+
117
+ gcms.to_csv(file_path, write_metadata=False, id_label="emsl:")
118
+ nmdc = NMDC_Metadata(file_path, cal_file_path, file_path.with_suffix(".cvs"), dms_file_path)
119
+ nmdc.create_nmdc_gcms_metadata(gcms)
120
+
121
+ # gcms.to_excel(out_put_file_name)
122
+ # gcms.to_pandas(out_put_file_name)
123
+ # gcms.to_hdf()
124
+
125
+ # df = gcms.get_dataframe()
126
+ # json_data = gcms.to_json()
127
+
128
+ # print(json_data)
129
+
130
+ # gcms.plot_processed_chromatogram()
131
+
132
+ # gcms.plot_gc_peaks()
133
+
134
+ # gcms.plot_chromatogram()
135
+
136
+ # gcms.plot_smoothed_chromatogram()
137
+
138
+ # gcms.plot_baseline_subtraction()
139
+
140
+ # gcms.plot_detected_baseline()
141
+
142
+ # matplotlib.pyplot.show()
143
+
144
+ def worker(args):
145
+
146
+ cProfile.runctx('run(args)', globals(), locals(), 'gc-ms.prof')
147
+
148
+
149
+
150
+ if __name__ == '__main__':
151
+ # import matplotlib
152
+ # matplotlib.use('TkAgg')
153
+ # %%
154
+ cores = 4
155
+ out_put_file_group_name = 'sql_test'
156
+ dms_file_path="db/GC-MS Metabolomics Experiments to Process Final.xlsx"
157
+ calibrate_and_search(out_put_file_group_name, cores, dms_file_path)
158
+
@@ -0,0 +1,59 @@
1
+ from pathlib import Path
2
+
3
+ from corems.mass_spectra.input.rawFileReader import ImportMassSpectraThermoMSFileReader
4
+
5
+ if __name__ == "__main__":
6
+ # =============================================================================
7
+ # Configuration
8
+ # =============================================================================
9
+ # Paths
10
+ base_path = Path("/Volumes/LaCie/nmdc_data/collection_testing/dev_test/")
11
+ raw_data_path = base_path / "raw"
12
+
13
+ # Instantiate LCMS object from the first raw data file
14
+ first_raw_file = next(raw_data_path.glob("*.raw"))
15
+ parser = ImportMassSpectraThermoMSFileReader(first_raw_file)
16
+ lcms_obj = parser.get_lcms_obj(spectra="ms1")
17
+ assert lcms_obj is not None, "Failed to instantiate LCMS object."
18
+
19
+ # Set parameters for the LCMS object, only ones we NEED to change from defaults to get things running
20
+ # Ideally, we'd load carefully chosen parameters from a file here for general processing
21
+ lcms_obj.parameters.mass_spectrum['ms2'].mass_spectrum.noise_threshold_method = "relative_abundance"
22
+
23
+ # Prepare a search dictionary for a targeted search
24
+ # Here are examples of target m/z and RT values
25
+ # Could derive this from an msp file.
26
+ target_mz_list = [254.2837, 521.325988, 503.3134460449219, 317.2839050292969]
27
+ target_rt_list = [5.83, 6.017, 7.977, 6.8658]
28
+ target_search_dict = {
29
+ "target_mz_list": target_mz_list,
30
+ "target_rt_list": target_rt_list,
31
+ "mz_tolerance_ppm": 5, #QUESTION: per target or bulk?
32
+ "rt_tolerance": 0.5, #QUESTION: per target or bulk?
33
+ "type": "internal standard"
34
+ }
35
+
36
+ # Look for mass features in targeted search mode
37
+ lcms_obj.find_mass_features(
38
+ targeted_search = True,
39
+ target_search_dict=target_search_dict
40
+ )
41
+ # Alternatively, or additionally, we could do normal (untargeted) mass feature finding here
42
+ # lcms_obj.find_mass_features(targeted_search=False)
43
+
44
+ # Let's integrate, add ms1 and ms2
45
+ lcms_obj.integrate_mass_features()
46
+ lcms_obj.add_associated_ms1(use_parser=False, spectrum_mode="profile")
47
+ lcms_obj.add_associated_ms2_dda(use_parser=True, spectrum_mode="centroid")
48
+
49
+ # Here we could do formula searching and MS2 search against a MSP database with MS2s of the search targets (similar to test_lcms_metabolomics.py)
50
+ # BUT, we'd need a compatible msp file, and that's not ultra simple
51
+
52
+ # Check out the mass feature dataframe
53
+ mf_df = lcms_obj.mass_features_to_df(drop_na_cols=True)
54
+
55
+ # Can visualize as well
56
+ lcms_obj.mass_features[0].plot(return_fig = False)
57
+
58
+ # Here could do some post-processing to report the "best hit" per target and include confidence metrics
59
+ print("here")
@@ -0,0 +1,248 @@
1
+ import os
2
+ from pathlib import Path
3
+ from multiprocessing import Pool
4
+ import warnings
5
+
6
+ from corems.molecular_id.search.database_interfaces import MSPInterface
7
+ from corems.mass_spectra.input.corems_hdf5 import ReadCoreMSHDFMassSpectra
8
+ from corems.mass_spectra.output.export import LCMSMetabolomicsExport
9
+
10
+ from support_code.nmdc.lipidomics.lipidomics_workflow import (
11
+ instantiate_lcms_obj,
12
+ set_params_on_lcms_obj,
13
+ check_scan_translator,
14
+ add_mass_features,
15
+ molecular_formula_search,
16
+ process_ms2,
17
+ )
18
+
19
+
20
+ def prepare_metadata(msp_file_path):
21
+ print("Parsing MSP file...")
22
+ my_msp = MSPInterface(file_path=msp_file_path)
23
+ print("Parsing MSP file complete.")
24
+ metadata = {
25
+ "fe": {"positive": None, "negative": None},
26
+ "molecular_metadata": {},
27
+ }
28
+ msp_positive, metabolite_metadata_positive = (
29
+ my_msp.get_metabolomics_spectra_library(
30
+ polarity="positive",
31
+ format="flashentropy",
32
+ normalize=True,
33
+ fe_kwargs={
34
+ "normalize_intensity": True,
35
+ "min_ms2_difference_in_da": 0.02, # for cleaning spectra
36
+ "max_ms2_tolerance_in_da": 0.01, # for setting search space
37
+ "max_indexed_mz": 3000,
38
+ "precursor_ions_removal_da": None,
39
+ "noise_threshold": 0,
40
+ },
41
+ )
42
+ )
43
+ metadata["fe"]["positive"] = msp_positive
44
+ metadata["molecular_metadata"] = metabolite_metadata_positive
45
+
46
+ msp_negative, metabolite_metadata_negative = (
47
+ my_msp.get_metabolomics_spectra_library(
48
+ polarity="negative",
49
+ format="flashentropy",
50
+ normalize=True,
51
+ fe_kwargs={
52
+ "normalize_intensity": True,
53
+ "min_ms2_difference_in_da": 0.02, # for cleaning spectra
54
+ "max_ms2_tolerance_in_da": 0.01, # for setting search space
55
+ "max_indexed_mz": 3000,
56
+ "precursor_ions_removal_da": None,
57
+ "noise_threshold": 0,
58
+ },
59
+ )
60
+ )
61
+ metadata["fe"]["negative"] = msp_negative
62
+ metadata["molecular_metadata"].update(metabolite_metadata_negative)
63
+
64
+ return metadata
65
+
66
+
67
+ def export_results(myLCMSobj, out_path, molecular_metadata=None, final=False):
68
+ """Export results to hdf5 and csv as a lipid report
69
+
70
+ Parameters
71
+ ----------
72
+ myLCMSobj : corems LCMS object
73
+ LCMS object to process
74
+ out_path : str or Path
75
+ Path to output file
76
+ molecular_metadata : dict
77
+ Dict with molecular metadata
78
+ final : bool
79
+ Whether to export final results
80
+
81
+ Returns
82
+ -------
83
+ None, exports results to hdf5 and csv as a lipid report
84
+ """
85
+ exporter = LCMSMetabolomicsExport(out_path, myLCMSobj)
86
+ exporter.to_hdf(overwrite=True)
87
+ if final:
88
+ # Do not show warnings, these are expected
89
+ exporter.report_to_csv(molecular_metadata=molecular_metadata)
90
+ else:
91
+ with warnings.catch_warnings():
92
+ warnings.simplefilter("ignore")
93
+ exporter.report_to_csv()
94
+
95
+
96
+ def run_ms2_search(out_path, metadata, scan_translator=None):
97
+ """Run ms2 spectral search and export final results
98
+
99
+ Parameters
100
+ ----------
101
+ out_path : str or Path
102
+ Path to output file
103
+ metadata : dict
104
+ 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
105
+
106
+ Returns
107
+ -------
108
+ None, runs ms2 spectral search and exports final results
109
+ """
110
+ # Read in the intermediate results
111
+ out_path = Path(out_path)
112
+ out_path_hdf5 = str(out_path) + ".corems/" + out_path.stem + ".hdf5"
113
+ parser = ReadCoreMSHDFMassSpectra(out_path_hdf5)
114
+ myLCMSobj = parser.get_lcms_obj()
115
+ process_ms2(myLCMSobj, metadata, scan_translator=scan_translator)
116
+ export_results(
117
+ myLCMSobj,
118
+ out_path=str(out_path),
119
+ molecular_metadata=metadata["molecular_metadata"],
120
+ final=True,
121
+ )
122
+
123
+
124
+ def run_lcms_metabolomics_workflow(
125
+ file_in,
126
+ out_path,
127
+ params_toml,
128
+ scan_translator,
129
+ metadata,
130
+ ):
131
+ myLCMSobj = instantiate_lcms_obj(file_in)
132
+ set_params_on_lcms_obj(myLCMSobj, params_toml, verbose)
133
+
134
+ # If the ms1 data are centroided, switch the peak picking method to centroided persistent homology
135
+ # and set the noise threshold method to relative abundance
136
+ ms1_scan_df = myLCMSobj.scan_df[myLCMSobj.scan_df.ms_level == 1]
137
+ if all(x == "centroid" for x in ms1_scan_df.ms_format.to_list()):
138
+ # Switch peak picking method to centroided persistent homology
139
+ myLCMSobj.parameters.lc_ms.peak_picking_method = "centroided_persistent_homology"
140
+ myLCMSobj.parameters.mass_spectrum[
141
+ "ms1"
142
+ ].mass_spectrum.noise_threshold_method = "relative_abundance"
143
+
144
+ myLCMSobj.parameters.mass_spectrum[
145
+ "ms1"
146
+ ].mass_spectrum.noise_threshold_min_relative_abundance = 0.1
147
+
148
+ check_scan_translator(myLCMSobj, scan_translator)
149
+ add_mass_features(myLCMSobj, scan_translator)
150
+ myLCMSobj.remove_unprocessed_data()
151
+ molecular_formula_search(myLCMSobj)
152
+ # Just for testing, not needed for workflow
153
+ export_results(
154
+ myLCMSobj,
155
+ out_path=str(out_path),
156
+ molecular_metadata=metadata["molecular_metadata"],
157
+ final=False,
158
+ )
159
+ process_ms2(myLCMSobj, metadata, scan_translator=scan_translator)
160
+ export_results(
161
+ myLCMSobj,
162
+ out_path=str(out_path),
163
+ molecular_metadata=metadata["molecular_metadata"],
164
+ final=True,
165
+ )
166
+
167
+
168
+ def run_lcms_metabolomics_workflow_batch(
169
+ file_dir,
170
+ out_dir,
171
+ params_toml,
172
+ msp_file_path,
173
+ scan_translator=None,
174
+ cores=1,
175
+ ):
176
+ """Run the LCMS metabolomics workflow on a batch of files
177
+
178
+ Parameters
179
+ ----------
180
+ file_dir : str or Path
181
+ Path to directory with raw files
182
+ out_dir : str or Path
183
+ Path to output directory
184
+ params_toml : str or Path
185
+ Path to toml file with parameters for all samples
186
+ msp_file_path : str or Path
187
+ Path to msp file with spectral library for MS2 search
188
+ scan_translator : str or Path
189
+ Path to toml file with scan translator for MS2 search
190
+ cores : int
191
+ Number of cores to use for processing
192
+ """
193
+ # Make output dir and get list of files to process
194
+ out_dir.mkdir(parents=True, exist_ok=True)
195
+ files_list = [
196
+ f for f in file_dir.iterdir() if f.suffix.lower() in {".raw", ".mzml"}
197
+ ]
198
+ out_paths_list = [out_dir / f.stem for f in files_list]
199
+
200
+ # Prepare search databases for ms2 search
201
+ my_msp_FE = prepare_metadata(msp_file_path)
202
+
203
+ # Run signal processing, get associated ms1, add associated ms2, do ms1 molecular search, and export temp results
204
+ # Note that this is exactly the same as the lipidomics workflow
205
+ if cores == 1 or len(files_list) == 1:
206
+ for file_in, file_out in list(zip(files_list, out_paths_list)):
207
+ print(f"Processing {file_in}")
208
+ run_lcms_metabolomics_workflow(
209
+ file_in=file_in,
210
+ out_path=file_out,
211
+ params_toml=params_toml,
212
+ scan_translator=scan_translator,
213
+ metadata=my_msp_FE,
214
+ )
215
+ elif cores > 1:
216
+ raise ValueError(
217
+ "Parallel processing is not yet supported for LCMS metabolomics workflow."
218
+ )
219
+
220
+
221
+ if __name__ == "__main__":
222
+ # Set input variables to run
223
+ msp_file_path = "/Users/heal742/LOCAL/05_NMDC/02_MetaMS/metams/test_data/test_lcms_metab_data/20250407_database.msp"
224
+ # msp_file_path = "/Users/heal742/LOCAL/corems_dev/corems/tests/tests_data/lcms/test_db.msp"
225
+ file_dir = Path(
226
+ "/Users/heal742/Library/CloudStorage/OneDrive-PNNL/Documents/_DMS_data/_NMDC/_massive/_bioscales_lcms/problem"
227
+ )
228
+ params_toml = Path(
229
+ "/Users/heal742/LOCAL/05_NMDC/02_MetaMS/data_processing/_bioscales_lcms_metabolomics/metadata/bioscales_hilic_corems.toml"
230
+ )
231
+ scan_translator = Path(
232
+ "/Users/heal742/LOCAL/05_NMDC/02_MetaMS/data_processing/_bioscales_lcms_metabolomics/metadata/bioscales_scan_translator.toml"
233
+ )
234
+ out_dir = Path("tmp_data/__lcms_metab_test_data_250509")
235
+ verbose = True
236
+ cores = 1
237
+
238
+ # Set up output directory
239
+ out_dir.mkdir(parents=True, exist_ok=True)
240
+
241
+ run_lcms_metabolomics_workflow_batch(
242
+ file_dir=file_dir,
243
+ out_dir=out_dir,
244
+ params_toml=params_toml,
245
+ msp_file_path=msp_file_path,
246
+ scan_translator=scan_translator,
247
+ cores=cores,
248
+ )