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,362 @@
1
+ import gc
2
+ import warnings
3
+
4
+ from numpy import (
5
+ arange,
6
+ blackman,
7
+ ceil,
8
+ fft,
9
+ hamming,
10
+ hanning,
11
+ kaiser,
12
+ linspace,
13
+ log2,
14
+ pi,
15
+ power,
16
+ sin,
17
+ sqrt,
18
+ where,
19
+ zeros,
20
+ )
21
+
22
+ __author__ = "Yuri E. Corilo"
23
+ __date__ = "Jun 12, 2019"
24
+
25
+
26
+ class TransientCalculations(object):
27
+ """Transient Calculations
28
+
29
+ Parameters
30
+ ----------
31
+ parameters : corems.transient.parameters.TransientParameters
32
+ The transient parameters
33
+ bandwidth : float
34
+ The bandwidth of the transient (Hz)
35
+ number_data_points : int
36
+ The number of data points of the transient
37
+ exc_low_freq : float
38
+ The low frequency of the excitation (Hz)
39
+ exc_high_freq : float
40
+ The high frequency of the excitation (Hz)
41
+
42
+ Attributes
43
+ ----------
44
+ parameters : corems.transient.parameters.TransientParameters
45
+ The transient parameters
46
+ bandwidth : float
47
+ The bandwidth of the transient (Hz)
48
+ number_data_points : int
49
+ The number of data points of the transient
50
+ exc_low_freq : float
51
+ The low frequency of the excitation (Hz)
52
+ exc_high_freq : float
53
+ The high frequency of the excitation (Hz)
54
+
55
+ Methods
56
+ -------
57
+ * cal_transient_time().
58
+ Calculate the time domain length of the transient
59
+ * zero_fill(transient).
60
+ Zero fill the transient
61
+ * truncation(transient).
62
+ Truncate the transient
63
+ * apodization(transient).
64
+ Apodization of the transient
65
+ * calculate_frequency_domain(number_data_points).
66
+ Calculate the frequency domain (axis) of the transient
67
+ * cut_freq_domain(freqdomain_X, freqdomain_Y).
68
+ Cut the frequency domain of the transient
69
+ * phase_and_absorption_mode_ft().
70
+ [Not Functional] Produce a phased absorption mode FT spectrum
71
+ * magnitude_mode_ft(transient).
72
+ Perform magnitude mode FT of the transient
73
+ * correct_dc_offset().
74
+ [Not Yet Implemented] Correct the DC offset of the transient
75
+
76
+ """
77
+
78
+ def cal_transient_time(self):
79
+ """Calculate the time domain length of the transient
80
+
81
+ Returns
82
+ -------
83
+ float
84
+ The time domain length of the transient (s)
85
+ """
86
+ return (1 / self.bandwidth) * ((self.number_data_points) / 2)
87
+
88
+ def zero_fill(self, transient):
89
+ """Zero fill the transient
90
+
91
+ Parameters
92
+ ----------
93
+ transient : numpy.ndarray
94
+ The transient data points
95
+
96
+ Returns
97
+ -------
98
+ numpy.ndarray
99
+ The transient data points zerofilled
100
+
101
+ Notes
102
+ -----
103
+ The number of zero fills is defined by the transient parameter number_of_zero_fills.
104
+ The function first calculate the next power of two of the transient length and zero fills to that length, to take advantage of FFT algorithm.
105
+ If the parameter next_power_of_two is set to False, the function will zero fill to the length of the original transient times the number of zero fills
106
+
107
+ """
108
+ if self.parameters.next_power_of_two:
109
+ exponent = int(
110
+ ceil(log2(len(transient) * (self.parameters.number_of_zero_fills + 1)))
111
+ )
112
+ zeros_filled_transient = zeros(2**exponent)
113
+ else:
114
+ zeros_filled_transient = zeros(
115
+ len(transient) * (self.parameters.number_of_zero_fills + 1)
116
+ )
117
+
118
+ zeros_filled_transient[0 : len(transient)] = transient
119
+
120
+ del transient
121
+
122
+ gc.collect()
123
+
124
+ return zeros_filled_transient
125
+
126
+ def truncation(self, transient):
127
+ """Truncate the transient
128
+
129
+ Parameters
130
+ ----------
131
+ transient : numpy.ndarray
132
+ The transient data points
133
+
134
+ Returns
135
+ -------
136
+ numpy.ndarray
137
+ The truncated transient data points
138
+
139
+ Notes
140
+ -----
141
+ The number of truncations is defined by the transient parameter number_of_truncations
142
+ """
143
+
144
+ data_count = len(transient)
145
+
146
+ for _ in range(self.parameters.number_of_truncations):
147
+ data_count = int(data_count / 2)
148
+
149
+ time_domain_truncated = transient[0:data_count]
150
+
151
+ del transient
152
+
153
+ gc.collect()
154
+
155
+ return time_domain_truncated
156
+
157
+ def apodization(self, transient):
158
+ """Apodization of the transient
159
+
160
+ Parameters
161
+ ----------
162
+ transient : numpy.ndarray
163
+ The transient data points
164
+
165
+ Returns
166
+ -------
167
+ numpy.ndarray
168
+ The apodized transient data points
169
+
170
+ Notes
171
+ -----
172
+ The apodization method is defined by the transient parameter apodization_method.
173
+ The following apodization methods are available:
174
+ Hamming,
175
+ Hanning,
176
+ Blackman,
177
+ Full-Sine,
178
+ Half-Sine,
179
+ Kaiser,
180
+ Half-Kaiser,
181
+ Rectangular/None
182
+
183
+ For Kaiser and Half-Kaiser, an additional parameter 'beta' is required, set by the transient parameter kaiser_beta.
184
+
185
+ """
186
+
187
+ apodi_method = self.parameters.apodization_method
188
+ beta = self.parameters.kaiser_beta
189
+
190
+ length = len(transient)
191
+
192
+ if apodi_method == "Hamming":
193
+ H_function = hamming(length)
194
+ elif apodi_method == "Hanning":
195
+ H_function = hanning(length)
196
+ elif apodi_method == "Blackman":
197
+ H_function = blackman(length)
198
+ elif apodi_method == "Full-Sine":
199
+ H_function = sin(linspace(0, pi, num=length))
200
+ elif apodi_method == "Half-Sine":
201
+ H_function = sin(linspace((pi / 2), 0, num=length))
202
+ elif apodi_method == "Kaiser":
203
+ H_function = kaiser(length, beta)
204
+ elif apodi_method == "Half-Kaiser":
205
+ H_function = kaiser(length * 2, beta)[length:]
206
+ elif apodi_method == 'Rectangular' or apodi_method is None:
207
+ H_function = 1
208
+
209
+ S_x = transient * H_function
210
+
211
+ del transient
212
+ gc.collect()
213
+
214
+ return S_x
215
+
216
+ def calculate_frequency_domain(self, number_data_points):
217
+ """Calculate the frequency domain (axis) of the transient
218
+
219
+ Parameters
220
+ ----------
221
+ number_data_points : int
222
+ The number of data points of the transient
223
+
224
+ Returns
225
+ -------
226
+ numpy.ndarray
227
+ The frequency domain of the transient (Hz)
228
+
229
+
230
+ """
231
+
232
+ qntpoints = arange(0, (number_data_points))
233
+
234
+ factor_distancy = (self.bandwidth) / (number_data_points)
235
+
236
+ frequency_domain = qntpoints * factor_distancy
237
+
238
+ del qntpoints
239
+ del factor_distancy
240
+ gc.collect()
241
+
242
+ return frequency_domain
243
+
244
+ def cut_freq_domain(self, freqdomain_X, freqdomain_Y):
245
+ """Cut the frequency domain of the transient
246
+
247
+ Parameters
248
+ ----------
249
+ freqdomain_X : numpy.ndarray
250
+ The frequency domain of the transient (Hz)
251
+ freqdomain_Y : numpy.ndarray
252
+ The frequency domain of the transient (Hz)
253
+
254
+ Returns
255
+ -------
256
+ numpy.ndarray
257
+ The frequency domain of the transient (Hz)
258
+ numpy.ndarray
259
+ The frequency domain of the transient (Hz)
260
+
261
+
262
+ """
263
+ # If the mw_low and mw_high are set, the frequency domain is cut to the mw range
264
+ # this accounts for the detection settings, not the excitation settings.
265
+ # TODO: Implement this - right now the f to mz function is in the ms class, not the transient class, so it doesnt work.
266
+ # if (self._mw_low != 0) & (self._mw_high != 0):
267
+ # high_freq = self._f_to_mz(self._mw_high)
268
+ # low_freq = self._f_to_mz(self._mw_low)
269
+ #
270
+ # final = where(freqdomain_X < high_freq)[-1][-1]
271
+ # start = where(freqdomain_X > low_freq)[0][0]
272
+ # else:
273
+ if self._qpd_enabled == 1:
274
+ low_freq = self._exc_low_freq * 2
275
+ high_freq = self._exc_high_freq * 2
276
+ else:
277
+ low_freq = self._exc_low_freq
278
+ high_freq = self._exc_high_freq
279
+
280
+ if self._exc_low_freq > self._exc_high_freq:
281
+ # TODO: This needs to be tested
282
+ # I'm not sure that this is relevant anyway - the excitation pulse is ramped in frequency but the detection is simulatenous
283
+ warnings.warn("This is not tested. Please check the results.")
284
+ final = where(freqdomain_X > low_freq)[0][0]
285
+ start = where(freqdomain_X > high_freq)[0][0]
286
+
287
+ else:
288
+ final = where(freqdomain_X < high_freq)[-1][-1]
289
+ start = where(freqdomain_X > low_freq)[0][0]
290
+
291
+ return freqdomain_X[start:final], freqdomain_Y[start:final]
292
+ # del freqdomain_X, freqdomain_Y
293
+ # gc.collect()
294
+
295
+ def phase_and_absorption_mode_ft(self):
296
+ """[Not Functional] Produce a phased absorption mode FT spectrum"""
297
+ # anyone wants to play with this part please make yourself comfortable. I will:
298
+ pass
299
+
300
+ def perform_magniture_mode_ft(self, transient):
301
+ """Perform magnitude mode FT of the transient
302
+
303
+ Parameters
304
+ ----------
305
+ transient : numpy.ndarray
306
+ The transient data points
307
+
308
+ Returns
309
+ -------
310
+ numpy.ndarray
311
+ The frequency domain of the transient (Hz)
312
+ numpy.ndarray
313
+ The magnitude of the transient (a.u.)
314
+
315
+
316
+ """
317
+
318
+ A = fft.rfft(transient)
319
+
320
+ # A = fft.fft(transient)
321
+ # A = A[0:int(len(A)/2)]
322
+
323
+ factor = int(self.parameters.number_of_zero_fills - 1)
324
+ if self.parameters.number_of_zero_fills:
325
+ if self.parameters.number_of_zero_fills == 1:
326
+ factor = 1 / 2
327
+
328
+ else:
329
+ factor = int(1 / self.parameters.number_of_zero_fills + 1)
330
+
331
+ Max_index = int(len(A) / factor)
332
+
333
+ else:
334
+ Max_index = int(len(A))
335
+
336
+ A = A[0:Max_index]
337
+
338
+ datapoints = len(A)
339
+
340
+ freqdomain_X = self.calculate_frequency_domain(datapoints)
341
+
342
+ magnitude_Y = sqrt((power(A.real, 2)) + (power(A.imag, 2)))
343
+
344
+ freqdomain_X_cut, magnitude_Y_cut = self.cut_freq_domain(
345
+ freqdomain_X, magnitude_Y
346
+ )
347
+
348
+ del transient
349
+ # del freqdomain_X
350
+ # del magnitude_Y
351
+ gc.collect()
352
+
353
+ return freqdomain_X_cut, magnitude_Y_cut
354
+
355
+ def correct_dc_offset(self):
356
+ """[Not Yet Implemented] Correct the DC offset of the transient
357
+
358
+ A simple baseline correction to compensate for a DC offset in the recorded transient.
359
+ Not implemented.
360
+
361
+ """
362
+ pass
File without changes