corems.mass_spectrum.input.massList

  1__author__ = "Yuri E. Corilo"
  2__date__ = "Jun 12, 2019"
  3
  4import warnings
  5
  6import pandas as pd
  7
  8from corems.encapsulation.constant import Atoms, Labels
  9from corems.mass_spectrum.factory.MassSpectrumClasses import (
 10    MassSpecCentroid,
 11    MassSpecProfile,
 12)
 13from corems.mass_spectrum.input.baseClass import MassListBaseClass
 14from corems.molecular_formula.factory.MolecularFormulaFactory import MolecularFormula
 15
 16
 17class ReadCoremsMasslist(MassListBaseClass):
 18    """
 19    The ReadCoremsMasslist object reads processed mass list data types
 20    and returns the mass spectrum obj with the molecular formula obj
 21
 22    **Only available for centroid mass spectrum type:** it will ignore the parameter **isCentroid**
 23    Please see MassListBaseClass for more details
 24
 25    """
 26
 27    def get_mass_spectrum(
 28        self, loadSettings: bool = True, auto_process: bool = True
 29    ) -> MassSpecCentroid:
 30        """
 31        Get the mass spectrum object from the processed mass list data.
 32
 33        Parameters
 34        ----------
 35        loadSettings : bool, optional
 36            Whether to load the settings for the mass spectrum. Default is True.
 37        auto_process : bool, optional
 38            Whether to automatically process the mass spectrum on instantiation.
 39            When False, molecular formulas are not attached; call
 40            ``process_mass_spec`` and then ``add_molecular_formula`` on the
 41            returned object. Default is True.
 42
 43        Returns
 44        -------
 45        MassSpecCentroid
 46            The mass spectrum object.
 47
 48        Raises
 49        ------
 50        ValueError
 51            If the input file is not a valid CoreMS file.
 52        """
 53
 54        dataframe = self.get_dataframe()
 55
 56        if not set(
 57            ["H/C", "O/C", "Heteroatom Class", "Ion Type", "Is Isotopologue"]
 58        ).issubset(dataframe.columns):
 59            raise ValueError(
 60                "%s it is not a valid CoreMS file" % str(self.file_location)
 61            )
 62
 63        self.check_columns(dataframe.columns)
 64
 65        dataframe.rename(columns=self.parameters.header_translate, inplace=True)
 66
 67        # "Ion Charge" is dual-purpose in CoreMS tables: spectrum/peak polarity
 68        # for unassigned rows (±1), formula assignment charge when assigned
 69        # (may be |z|>1). Spectrum polarity is only the sign.
 70        # Use iloc for pandas 3 / CoW-safe indexing.
 71        raw_charge = int(dataframe["Ion Charge"].iloc[0])
 72        if raw_charge == 0:
 73            raise ValueError("Ion Charge column must be non-zero to derive polarity")
 74        polarity = 1 if raw_charge > 0 else -1
 75
 76        output_parameters = self.get_output_parameters(polarity)
 77
 78        mass_spec_obj = MassSpecCentroid(
 79            dataframe.to_dict(orient="list"),
 80            output_parameters,
 81            auto_process=auto_process,
 82        )
 83
 84        if loadSettings is True:
 85            self.load_settings(mass_spec_obj, output_parameters)
 86
 87        if auto_process:
 88            # Formulas first. add_molecular_formula matches the uncalibrated
 89            # "m/z" column against mz_exp, which returns mz_cal once restored.
 90            self.add_molecular_formula(mass_spec_obj, dataframe)
 91            self.restore_peak_calibration(mass_spec_obj, dataframe)
 92
 93        return mass_spec_obj
 94
 95    def restore_peak_calibration(self, mass_spec_obj, dataframe):
 96        """Restore each peak's ``mz_cal`` from the stored "Calibrated m/z" column.
 97
 98        The peak table always stores both the uncalibrated "m/z" and the
 99        (possibly calibrated) "Calibrated m/z", but ``MassSpecCentroid`` is
100        built only from "m/z" -- so without this, a reloaded peak loses its
101        own calibration even when the spectrum it came from had been
102        calibrated. Only peaks whose "Calibrated m/z" actually differs from
103        "m/z" are touched; an unmatched or never-calibrated peak's ``mz_cal``
104        is left as ``None``, same as before this method existed.
105
106        Parameters
107        ----------
108        mass_spec_obj : MassSpecCentroid
109            The mass spectrum object whose peaks' ``mz_cal`` to restore.
110        dataframe : pandas.DataFrame
111            The processed mass list data, with column names already
112            translated via ``header_translate`` (same dataframe passed to
113            ``add_molecular_formula``).
114        """
115        if "Calibrated m/z" not in dataframe.columns:
116            return
117
118        mz_exp_col = dataframe[Labels.mz].astype(float)
119        mz_cal_col = dataframe["Calibrated m/z"]
120
121        # A missing "Calibrated m/z" cell is NaN (pandas' representation of
122        # missing data), not None -- and NaN is truthy in Python, so letting
123        # it through would set mz_cal to NaN, and MSPeak.mz_exp
124        # (`self.mz_cal if self.mz_cal else self._mz_exp`) would then return
125        # NaN instead of correctly falling back to the uncalibrated value.
126        # pd.isna() catches it; `is None` would not.
127        present = ~pd.isna(mz_cal_col)
128        mz_cal_col = mz_cal_col.astype(float)
129        differs = present & (mz_cal_col != mz_exp_col)
130        if not differs.any():
131            return
132
133        # Built once -- O(n_peaks) -- and only applied to the rows that
134        # actually differ, instead of a per-row list.index() lookup inside
135        # the loop (quadratic in peak count for a large peak list). Matches
136        # peaks by m/z value rather than row position, same approach
137        # add_molecular_formula uses -- safe against any reordering between
138        # the dataframe and mass_spec_obj.mspeaks. Exact-match only, same as
139        # before.
140        mz_to_index = {mz: i for i, mz in enumerate(mass_spec_obj.mz_exp)}
141
142        for mz_exp, mz_cal in zip(mz_exp_col[differs], mz_cal_col[differs]):
143            ms_peak_index = mz_to_index.get(mz_exp)
144            if ms_peak_index is None:
145                continue
146            mass_spec_obj[ms_peak_index].mz_cal = mz_cal
147
148    def add_molecular_formula(self, mass_spec_obj, dataframe):
149        """
150        Add molecular formula information to the mass spectrum object.
151
152        Parameters
153        ----------
154        mass_spec_obj : MassSpecCentroid
155            The mass spectrum object to add the molecular formula to.
156        dataframe : pandas.DataFrame
157            The processed mass list data.
158
159        """
160
161        # check if is coreMS file
162        if "Is Isotopologue" in dataframe:
163            # Reindex dataframe to row index to avoid issues with duplicated indexes (e.g. when multiple formula map to single mz_exp)
164            dataframe = dataframe.reset_index(drop=True)
165
166            mz_exp_df = dataframe[Labels.mz].astype(float)
167            formula_df = dataframe[
168                dataframe.columns.intersection(Atoms.atoms_order)
169            ].copy()
170            # Convert to numeric first (pandas 3.x may infer str dtype for
171            # HDF5-sourced atom count columns); coerce handles b"nan" bytes too
172            formula_df = formula_df.apply(pd.to_numeric, errors="coerce").fillna(0)
173
174            ion_type_df = dataframe["Ion Type"]
175            # Formula assignment charge from export (not peak polarity)
176            ion_charge_df = dataframe["Ion Charge"]
177            is_isotopologue_df = dataframe["Is Isotopologue"]
178            if "Adduct" in dataframe:
179                adduct_df = dataframe["Adduct"]
180            else:
181                adduct_df = None
182
183        mass_spec_mz_exp_list = mass_spec_obj.mz_exp
184
185        for df_index, mz_exp in enumerate(mz_exp_df):
186            bad_mf = False
187            counts = 0
188
189            ms_peak_index = list(mass_spec_mz_exp_list).index(float(mz_exp))
190
191            if "Is Isotopologue" in dataframe:
192                atoms = list(formula_df.columns.astype(str))
193                counts = list(formula_df.iloc[df_index].astype(int))
194
195                formula_dict = dict(zip(atoms, counts))
196
197                # Drop any atoms with 0 counts
198                formula_dict = {
199                    atom: formula_dict[atom]
200                    for atom in formula_dict
201                    if formula_dict[atom] > 0
202                }
203
204            if sum(counts) > 0:
205                # Prefer iloc for positional access (pandas 3 Series[] is label-based)
206                ion_type = str(
207                    Labels.ion_type_translate.get(ion_type_df.iloc[df_index])
208                )
209                if adduct_df is not None:
210                    adduct_atom = str(adduct_df.iloc[df_index])
211                    if adduct_atom == "None":
212                        adduct_atom = None
213                else:
214                    adduct_atom = None
215
216                # If not isotopologue, cast as MolecularFormula
217                if not bool(int(is_isotopologue_df.iloc[df_index])):
218                    mfobj = MolecularFormula(
219                        formula_dict,
220                        int(ion_charge_df.iloc[df_index]),
221                        mspeak_parent=mass_spec_obj[ms_peak_index],
222                        ion_type=ion_type,
223                        adduct_atom=adduct_atom,
224                    )
225
226                # if is isotopologue, recast as MolecularFormulaIsotopologue
227                if bool(int(is_isotopologue_df.iloc[df_index])):
228                    # First make a MolecularFormula object for the parent so we can get probabilities etc
229                    formula_list_parent = {}
230                    for atom in formula_dict:
231                        if atom in Atoms.isotopes.keys():
232                            formula_list_parent[atom] = formula_dict[atom]
233                        else:
234                            # remove any numbers from the atom name to cast as a mono-isotopic atom
235                            atom_mono = atom.strip("0123456789")
236                            if (
237                                atom_mono in Atoms.isotopes.keys()
238                                and atom_mono in formula_list_parent.keys()
239                            ):
240                                formula_list_parent[atom_mono] = (
241                                    formula_list_parent[atom_mono] + formula_dict[atom]
242                                )
243                            elif atom_mono in Atoms.isotopes.keys():
244                                formula_list_parent[atom_mono] = formula_dict[atom]
245                            else:
246                                warnings.warn(f"Atom {atom} not in Atoms.atoms_order")
247                    mono_index = int(dataframe.iloc[df_index]["Mono Isotopic Index"])
248                    mono_mfobj = MolecularFormula(
249                        formula_list_parent,
250                        int(ion_charge_df.iloc[df_index]),
251                        mspeak_parent=mass_spec_obj[mono_index],
252                        ion_type=ion_type,
253                        adduct_atom=adduct_atom,
254                    )
255
256                    # Next, generate isotopologues from the parent
257                    isos = list(
258                        mono_mfobj.isotopologues(
259                            min_abundance=mass_spec_obj.abundance.min() * 0.01,
260                            current_mono_abundance=mass_spec_obj[mono_index].abundance,
261                            dynamic_range=mass_spec_obj.dynamic_range,
262                        )
263                    )
264
265                    # Finally, find the isotopologue that matches the formula_dict
266                    matched_isos = []
267                    for iso in isos:
268                        # If match was already found, exit the loop
269                        if len(matched_isos) > 0:
270                            break
271                        else:
272                            # Check the atoms match
273                            if set(iso.atoms) == set(formula_dict.keys()):
274                                # Check the values of the atoms match
275                                if all(
276                                    [
277                                        iso[atom] == formula_dict[atom]
278                                        for atom in formula_dict
279                                    ]
280                                ):
281                                    matched_isos.append(iso)
282
283                    if len(matched_isos) == 0:
284                        # FIXME: This should not occur see https://code.emsl.pnl.gov/mass-spectrometry/corems/-/issues/190
285                        warnings.warn(
286                            f"No isotopologue matched the formula_dict: {formula_dict}"
287                        )
288                        bad_mf = True
289                    else:
290                        bad_mf = False
291                        mfobj = matched_isos[0]
292
293                        # Add the mono isotopic index, confidence score and isotopologue similarity
294                        mfobj.mspeak_index_mono_isotopic = int(
295                            dataframe.iloc[df_index]["Mono Isotopic Index"]
296                        )
297                if not bad_mf:
298                    # Add the confidence score and isotopologue similarity and average MZ error score
299                    if "m/z Error Score" in dataframe:
300                        mfobj._mass_error_average_score = float(
301                            dataframe.iloc[df_index]["m/z Error Score"]
302                        )
303                    if "Confidence Score" in dataframe:
304                        mfobj._confidence_score = float(
305                            dataframe.iloc[df_index]["Confidence Score"]
306                        )
307                    if "Isotopologue Similarity" in dataframe:
308                        mfobj._isotopologue_similarity = float(
309                            dataframe.iloc[df_index]["Isotopologue Similarity"]
310                        )
311                    mass_spec_obj[ms_peak_index].add_molecular_formula(mfobj)
312
313
314class ReadMassList(MassListBaseClass):
315    """
316    The ReadMassList object reads unprocessed mass list data types
317    and returns the mass spectrum object.
318
319    Parameters
320    ----------
321    MassListBaseClass : class
322        The base class for reading mass list data types.
323
324    Methods
325    -------
326    * get_mass_spectrum(polarity, scan=0, auto_process=True, loadSettings=True). Reads mass list data types and returns the mass spectrum object.
327
328    """
329
330    def get_mass_spectrum(
331        self,
332        polarity: int,
333        scan: int = 0,
334        auto_process: bool = True,
335        loadSettings: bool = True,
336    ):
337        """
338        Reads mass list data types and returns the mass spectrum object.
339
340        Parameters
341        ----------
342        polarity : int
343            The polarity of the mass spectrum (+1 or -1).
344        scan : int, optional
345            The scan number of the mass spectrum (default is 0).
346        auto_process : bool, optional
347            Flag indicating whether to automatically process the mass spectrum (default is True).
348        loadSettings : bool, optional
349            Flag indicating whether to load settings for the mass spectrum (default is True).
350
351        Returns
352        -------
353        mass_spec : MassSpecCentroid or MassSpecProfile
354            The mass spectrum object.
355
356        """
357
358        # delimiter = "  " or " " or  "," or "\t" etc
359
360        if self.isCentroid:
361            dataframe = self.get_dataframe()
362
363            self.check_columns(dataframe.columns)
364
365            self.clean_data_frame(dataframe)
366
367            dataframe.rename(columns=self.parameters.header_translate, inplace=True)
368
369            output_parameters = self.get_output_parameters(polarity)
370
371            mass_spec = MassSpecCentroid(
372                dataframe.to_dict(orient="list"),
373                output_parameters,
374                auto_process=auto_process,
375            )
376
377            if loadSettings:
378                self.load_settings(mass_spec, output_parameters)
379
380            return mass_spec
381
382        else:
383            dataframe = self.get_dataframe()
384
385            self.check_columns(dataframe.columns)
386
387            output_parameters = self.get_output_parameters(polarity)
388
389            self.clean_data_frame(dataframe)
390
391            dataframe.rename(columns=self.parameters.header_translate, inplace=True)
392
393            mass_spec = MassSpecProfile(
394                dataframe.to_dict(orient="list"),
395                output_parameters,
396                auto_process=auto_process,
397            )
398
399            if loadSettings:
400                self.load_settings(mass_spec, output_parameters)
401
402            return mass_spec
403
404
405class ReadBrukerXMLList(MassListBaseClass):
406    """
407    The ReadBrukerXMLList object reads Bruker XML objects
408    and returns the mass spectrum object.
409    See MassListBaseClass for details
410
411    Parameters
412    ----------
413    MassListBaseClass : class
414        The base class for reading mass list data types and returning the mass spectrum object.
415
416    Methods
417    -------
418    * get_mass_spectrum(polarity: bool = None, scan: int = 0, auto_process: bool = True, loadSettings: bool = True). Reads mass list data types and returns the mass spectrum object.
419
420    """
421
422    def get_mass_spectrum(
423        self,
424        polarity: bool = None,
425        scan: int = 0,
426        auto_process: bool = True,
427        loadSettings: bool = True,
428    ):
429        """
430        Reads mass list data types and returns the mass spectrum object.
431
432        Parameters
433        ----------
434        polarity : bool, optional
435            The polarity of the mass spectrum. Can be +1 or -1. If not provided, it will be determined from the XML file.
436        scan : int, optional
437            The scan number of the mass spectrum. Default is 0.
438        auto_process : bool, optional
439            Whether to automatically process the mass spectrum. Default is True.
440        loadSettings : bool, optional
441            Whether to load the settings for the mass spectrum. Default is True.
442
443        Returns
444        -------
445        mass_spec : MassSpecCentroid
446            The mass spectrum object representing the centroided mass spectrum.
447        """
448        # delimiter = "  " or " " or  "," or "\t" etc
449
450        if polarity == None:
451            polarity = self.get_xml_polarity()
452        dataframe = self.get_dataframe()
453
454        self.check_columns(dataframe.columns)
455
456        self.clean_data_frame(dataframe)
457
458        dataframe.rename(columns=self.parameters.header_translate, inplace=True)
459
460        output_parameters = self.get_output_parameters(polarity)
461
462        mass_spec = MassSpecCentroid(
463            dataframe.to_dict(orient="list"),
464            output_parameters,
465            auto_process=auto_process,
466        )
467
468        if loadSettings:
469            self.load_settings(mass_spec, output_parameters)
470
471        return mass_spec
class ReadCoremsMasslist(corems.mass_spectrum.input.baseClass.MassListBaseClass):
 18class ReadCoremsMasslist(MassListBaseClass):
 19    """
 20    The ReadCoremsMasslist object reads processed mass list data types
 21    and returns the mass spectrum obj with the molecular formula obj
 22
 23    **Only available for centroid mass spectrum type:** it will ignore the parameter **isCentroid**
 24    Please see MassListBaseClass for more details
 25
 26    """
 27
 28    def get_mass_spectrum(
 29        self, loadSettings: bool = True, auto_process: bool = True
 30    ) -> MassSpecCentroid:
 31        """
 32        Get the mass spectrum object from the processed mass list data.
 33
 34        Parameters
 35        ----------
 36        loadSettings : bool, optional
 37            Whether to load the settings for the mass spectrum. Default is True.
 38        auto_process : bool, optional
 39            Whether to automatically process the mass spectrum on instantiation.
 40            When False, molecular formulas are not attached; call
 41            ``process_mass_spec`` and then ``add_molecular_formula`` on the
 42            returned object. Default is True.
 43
 44        Returns
 45        -------
 46        MassSpecCentroid
 47            The mass spectrum object.
 48
 49        Raises
 50        ------
 51        ValueError
 52            If the input file is not a valid CoreMS file.
 53        """
 54
 55        dataframe = self.get_dataframe()
 56
 57        if not set(
 58            ["H/C", "O/C", "Heteroatom Class", "Ion Type", "Is Isotopologue"]
 59        ).issubset(dataframe.columns):
 60            raise ValueError(
 61                "%s it is not a valid CoreMS file" % str(self.file_location)
 62            )
 63
 64        self.check_columns(dataframe.columns)
 65
 66        dataframe.rename(columns=self.parameters.header_translate, inplace=True)
 67
 68        # "Ion Charge" is dual-purpose in CoreMS tables: spectrum/peak polarity
 69        # for unassigned rows (±1), formula assignment charge when assigned
 70        # (may be |z|>1). Spectrum polarity is only the sign.
 71        # Use iloc for pandas 3 / CoW-safe indexing.
 72        raw_charge = int(dataframe["Ion Charge"].iloc[0])
 73        if raw_charge == 0:
 74            raise ValueError("Ion Charge column must be non-zero to derive polarity")
 75        polarity = 1 if raw_charge > 0 else -1
 76
 77        output_parameters = self.get_output_parameters(polarity)
 78
 79        mass_spec_obj = MassSpecCentroid(
 80            dataframe.to_dict(orient="list"),
 81            output_parameters,
 82            auto_process=auto_process,
 83        )
 84
 85        if loadSettings is True:
 86            self.load_settings(mass_spec_obj, output_parameters)
 87
 88        if auto_process:
 89            # Formulas first. add_molecular_formula matches the uncalibrated
 90            # "m/z" column against mz_exp, which returns mz_cal once restored.
 91            self.add_molecular_formula(mass_spec_obj, dataframe)
 92            self.restore_peak_calibration(mass_spec_obj, dataframe)
 93
 94        return mass_spec_obj
 95
 96    def restore_peak_calibration(self, mass_spec_obj, dataframe):
 97        """Restore each peak's ``mz_cal`` from the stored "Calibrated m/z" column.
 98
 99        The peak table always stores both the uncalibrated "m/z" and the
100        (possibly calibrated) "Calibrated m/z", but ``MassSpecCentroid`` is
101        built only from "m/z" -- so without this, a reloaded peak loses its
102        own calibration even when the spectrum it came from had been
103        calibrated. Only peaks whose "Calibrated m/z" actually differs from
104        "m/z" are touched; an unmatched or never-calibrated peak's ``mz_cal``
105        is left as ``None``, same as before this method existed.
106
107        Parameters
108        ----------
109        mass_spec_obj : MassSpecCentroid
110            The mass spectrum object whose peaks' ``mz_cal`` to restore.
111        dataframe : pandas.DataFrame
112            The processed mass list data, with column names already
113            translated via ``header_translate`` (same dataframe passed to
114            ``add_molecular_formula``).
115        """
116        if "Calibrated m/z" not in dataframe.columns:
117            return
118
119        mz_exp_col = dataframe[Labels.mz].astype(float)
120        mz_cal_col = dataframe["Calibrated m/z"]
121
122        # A missing "Calibrated m/z" cell is NaN (pandas' representation of
123        # missing data), not None -- and NaN is truthy in Python, so letting
124        # it through would set mz_cal to NaN, and MSPeak.mz_exp
125        # (`self.mz_cal if self.mz_cal else self._mz_exp`) would then return
126        # NaN instead of correctly falling back to the uncalibrated value.
127        # pd.isna() catches it; `is None` would not.
128        present = ~pd.isna(mz_cal_col)
129        mz_cal_col = mz_cal_col.astype(float)
130        differs = present & (mz_cal_col != mz_exp_col)
131        if not differs.any():
132            return
133
134        # Built once -- O(n_peaks) -- and only applied to the rows that
135        # actually differ, instead of a per-row list.index() lookup inside
136        # the loop (quadratic in peak count for a large peak list). Matches
137        # peaks by m/z value rather than row position, same approach
138        # add_molecular_formula uses -- safe against any reordering between
139        # the dataframe and mass_spec_obj.mspeaks. Exact-match only, same as
140        # before.
141        mz_to_index = {mz: i for i, mz in enumerate(mass_spec_obj.mz_exp)}
142
143        for mz_exp, mz_cal in zip(mz_exp_col[differs], mz_cal_col[differs]):
144            ms_peak_index = mz_to_index.get(mz_exp)
145            if ms_peak_index is None:
146                continue
147            mass_spec_obj[ms_peak_index].mz_cal = mz_cal
148
149    def add_molecular_formula(self, mass_spec_obj, dataframe):
150        """
151        Add molecular formula information to the mass spectrum object.
152
153        Parameters
154        ----------
155        mass_spec_obj : MassSpecCentroid
156            The mass spectrum object to add the molecular formula to.
157        dataframe : pandas.DataFrame
158            The processed mass list data.
159
160        """
161
162        # check if is coreMS file
163        if "Is Isotopologue" in dataframe:
164            # Reindex dataframe to row index to avoid issues with duplicated indexes (e.g. when multiple formula map to single mz_exp)
165            dataframe = dataframe.reset_index(drop=True)
166
167            mz_exp_df = dataframe[Labels.mz].astype(float)
168            formula_df = dataframe[
169                dataframe.columns.intersection(Atoms.atoms_order)
170            ].copy()
171            # Convert to numeric first (pandas 3.x may infer str dtype for
172            # HDF5-sourced atom count columns); coerce handles b"nan" bytes too
173            formula_df = formula_df.apply(pd.to_numeric, errors="coerce").fillna(0)
174
175            ion_type_df = dataframe["Ion Type"]
176            # Formula assignment charge from export (not peak polarity)
177            ion_charge_df = dataframe["Ion Charge"]
178            is_isotopologue_df = dataframe["Is Isotopologue"]
179            if "Adduct" in dataframe:
180                adduct_df = dataframe["Adduct"]
181            else:
182                adduct_df = None
183
184        mass_spec_mz_exp_list = mass_spec_obj.mz_exp
185
186        for df_index, mz_exp in enumerate(mz_exp_df):
187            bad_mf = False
188            counts = 0
189
190            ms_peak_index = list(mass_spec_mz_exp_list).index(float(mz_exp))
191
192            if "Is Isotopologue" in dataframe:
193                atoms = list(formula_df.columns.astype(str))
194                counts = list(formula_df.iloc[df_index].astype(int))
195
196                formula_dict = dict(zip(atoms, counts))
197
198                # Drop any atoms with 0 counts
199                formula_dict = {
200                    atom: formula_dict[atom]
201                    for atom in formula_dict
202                    if formula_dict[atom] > 0
203                }
204
205            if sum(counts) > 0:
206                # Prefer iloc for positional access (pandas 3 Series[] is label-based)
207                ion_type = str(
208                    Labels.ion_type_translate.get(ion_type_df.iloc[df_index])
209                )
210                if adduct_df is not None:
211                    adduct_atom = str(adduct_df.iloc[df_index])
212                    if adduct_atom == "None":
213                        adduct_atom = None
214                else:
215                    adduct_atom = None
216
217                # If not isotopologue, cast as MolecularFormula
218                if not bool(int(is_isotopologue_df.iloc[df_index])):
219                    mfobj = MolecularFormula(
220                        formula_dict,
221                        int(ion_charge_df.iloc[df_index]),
222                        mspeak_parent=mass_spec_obj[ms_peak_index],
223                        ion_type=ion_type,
224                        adduct_atom=adduct_atom,
225                    )
226
227                # if is isotopologue, recast as MolecularFormulaIsotopologue
228                if bool(int(is_isotopologue_df.iloc[df_index])):
229                    # First make a MolecularFormula object for the parent so we can get probabilities etc
230                    formula_list_parent = {}
231                    for atom in formula_dict:
232                        if atom in Atoms.isotopes.keys():
233                            formula_list_parent[atom] = formula_dict[atom]
234                        else:
235                            # remove any numbers from the atom name to cast as a mono-isotopic atom
236                            atom_mono = atom.strip("0123456789")
237                            if (
238                                atom_mono in Atoms.isotopes.keys()
239                                and atom_mono in formula_list_parent.keys()
240                            ):
241                                formula_list_parent[atom_mono] = (
242                                    formula_list_parent[atom_mono] + formula_dict[atom]
243                                )
244                            elif atom_mono in Atoms.isotopes.keys():
245                                formula_list_parent[atom_mono] = formula_dict[atom]
246                            else:
247                                warnings.warn(f"Atom {atom} not in Atoms.atoms_order")
248                    mono_index = int(dataframe.iloc[df_index]["Mono Isotopic Index"])
249                    mono_mfobj = MolecularFormula(
250                        formula_list_parent,
251                        int(ion_charge_df.iloc[df_index]),
252                        mspeak_parent=mass_spec_obj[mono_index],
253                        ion_type=ion_type,
254                        adduct_atom=adduct_atom,
255                    )
256
257                    # Next, generate isotopologues from the parent
258                    isos = list(
259                        mono_mfobj.isotopologues(
260                            min_abundance=mass_spec_obj.abundance.min() * 0.01,
261                            current_mono_abundance=mass_spec_obj[mono_index].abundance,
262                            dynamic_range=mass_spec_obj.dynamic_range,
263                        )
264                    )
265
266                    # Finally, find the isotopologue that matches the formula_dict
267                    matched_isos = []
268                    for iso in isos:
269                        # If match was already found, exit the loop
270                        if len(matched_isos) > 0:
271                            break
272                        else:
273                            # Check the atoms match
274                            if set(iso.atoms) == set(formula_dict.keys()):
275                                # Check the values of the atoms match
276                                if all(
277                                    [
278                                        iso[atom] == formula_dict[atom]
279                                        for atom in formula_dict
280                                    ]
281                                ):
282                                    matched_isos.append(iso)
283
284                    if len(matched_isos) == 0:
285                        # FIXME: This should not occur see https://code.emsl.pnl.gov/mass-spectrometry/corems/-/issues/190
286                        warnings.warn(
287                            f"No isotopologue matched the formula_dict: {formula_dict}"
288                        )
289                        bad_mf = True
290                    else:
291                        bad_mf = False
292                        mfobj = matched_isos[0]
293
294                        # Add the mono isotopic index, confidence score and isotopologue similarity
295                        mfobj.mspeak_index_mono_isotopic = int(
296                            dataframe.iloc[df_index]["Mono Isotopic Index"]
297                        )
298                if not bad_mf:
299                    # Add the confidence score and isotopologue similarity and average MZ error score
300                    if "m/z Error Score" in dataframe:
301                        mfobj._mass_error_average_score = float(
302                            dataframe.iloc[df_index]["m/z Error Score"]
303                        )
304                    if "Confidence Score" in dataframe:
305                        mfobj._confidence_score = float(
306                            dataframe.iloc[df_index]["Confidence Score"]
307                        )
308                    if "Isotopologue Similarity" in dataframe:
309                        mfobj._isotopologue_similarity = float(
310                            dataframe.iloc[df_index]["Isotopologue Similarity"]
311                        )
312                    mass_spec_obj[ms_peak_index].add_molecular_formula(mfobj)

The ReadCoremsMasslist object reads processed mass list data types and returns the mass spectrum obj with the molecular formula obj

Only available for centroid mass spectrum type: it will ignore the parameter isCentroid Please see MassListBaseClass for more details

def get_mass_spectrum( self, loadSettings: bool = True, auto_process: bool = True) -> corems.mass_spectrum.factory.MassSpectrumClasses.MassSpecCentroid:
28    def get_mass_spectrum(
29        self, loadSettings: bool = True, auto_process: bool = True
30    ) -> MassSpecCentroid:
31        """
32        Get the mass spectrum object from the processed mass list data.
33
34        Parameters
35        ----------
36        loadSettings : bool, optional
37            Whether to load the settings for the mass spectrum. Default is True.
38        auto_process : bool, optional
39            Whether to automatically process the mass spectrum on instantiation.
40            When False, molecular formulas are not attached; call
41            ``process_mass_spec`` and then ``add_molecular_formula`` on the
42            returned object. Default is True.
43
44        Returns
45        -------
46        MassSpecCentroid
47            The mass spectrum object.
48
49        Raises
50        ------
51        ValueError
52            If the input file is not a valid CoreMS file.
53        """
54
55        dataframe = self.get_dataframe()
56
57        if not set(
58            ["H/C", "O/C", "Heteroatom Class", "Ion Type", "Is Isotopologue"]
59        ).issubset(dataframe.columns):
60            raise ValueError(
61                "%s it is not a valid CoreMS file" % str(self.file_location)
62            )
63
64        self.check_columns(dataframe.columns)
65
66        dataframe.rename(columns=self.parameters.header_translate, inplace=True)
67
68        # "Ion Charge" is dual-purpose in CoreMS tables: spectrum/peak polarity
69        # for unassigned rows (±1), formula assignment charge when assigned
70        # (may be |z|>1). Spectrum polarity is only the sign.
71        # Use iloc for pandas 3 / CoW-safe indexing.
72        raw_charge = int(dataframe["Ion Charge"].iloc[0])
73        if raw_charge == 0:
74            raise ValueError("Ion Charge column must be non-zero to derive polarity")
75        polarity = 1 if raw_charge > 0 else -1
76
77        output_parameters = self.get_output_parameters(polarity)
78
79        mass_spec_obj = MassSpecCentroid(
80            dataframe.to_dict(orient="list"),
81            output_parameters,
82            auto_process=auto_process,
83        )
84
85        if loadSettings is True:
86            self.load_settings(mass_spec_obj, output_parameters)
87
88        if auto_process:
89            # Formulas first. add_molecular_formula matches the uncalibrated
90            # "m/z" column against mz_exp, which returns mz_cal once restored.
91            self.add_molecular_formula(mass_spec_obj, dataframe)
92            self.restore_peak_calibration(mass_spec_obj, dataframe)
93
94        return mass_spec_obj

Get the mass spectrum object from the processed mass list data.

Parameters
  • loadSettings (bool, optional): Whether to load the settings for the mass spectrum. Default is True.
  • auto_process (bool, optional): Whether to automatically process the mass spectrum on instantiation. When False, molecular formulas are not attached; call process_mass_spec and then add_molecular_formula on the returned object. Default is True.
Returns
  • MassSpecCentroid: The mass spectrum object.
Raises
  • ValueError: If the input file is not a valid CoreMS file.
def restore_peak_calibration(self, mass_spec_obj, dataframe):
 96    def restore_peak_calibration(self, mass_spec_obj, dataframe):
 97        """Restore each peak's ``mz_cal`` from the stored "Calibrated m/z" column.
 98
 99        The peak table always stores both the uncalibrated "m/z" and the
100        (possibly calibrated) "Calibrated m/z", but ``MassSpecCentroid`` is
101        built only from "m/z" -- so without this, a reloaded peak loses its
102        own calibration even when the spectrum it came from had been
103        calibrated. Only peaks whose "Calibrated m/z" actually differs from
104        "m/z" are touched; an unmatched or never-calibrated peak's ``mz_cal``
105        is left as ``None``, same as before this method existed.
106
107        Parameters
108        ----------
109        mass_spec_obj : MassSpecCentroid
110            The mass spectrum object whose peaks' ``mz_cal`` to restore.
111        dataframe : pandas.DataFrame
112            The processed mass list data, with column names already
113            translated via ``header_translate`` (same dataframe passed to
114            ``add_molecular_formula``).
115        """
116        if "Calibrated m/z" not in dataframe.columns:
117            return
118
119        mz_exp_col = dataframe[Labels.mz].astype(float)
120        mz_cal_col = dataframe["Calibrated m/z"]
121
122        # A missing "Calibrated m/z" cell is NaN (pandas' representation of
123        # missing data), not None -- and NaN is truthy in Python, so letting
124        # it through would set mz_cal to NaN, and MSPeak.mz_exp
125        # (`self.mz_cal if self.mz_cal else self._mz_exp`) would then return
126        # NaN instead of correctly falling back to the uncalibrated value.
127        # pd.isna() catches it; `is None` would not.
128        present = ~pd.isna(mz_cal_col)
129        mz_cal_col = mz_cal_col.astype(float)
130        differs = present & (mz_cal_col != mz_exp_col)
131        if not differs.any():
132            return
133
134        # Built once -- O(n_peaks) -- and only applied to the rows that
135        # actually differ, instead of a per-row list.index() lookup inside
136        # the loop (quadratic in peak count for a large peak list). Matches
137        # peaks by m/z value rather than row position, same approach
138        # add_molecular_formula uses -- safe against any reordering between
139        # the dataframe and mass_spec_obj.mspeaks. Exact-match only, same as
140        # before.
141        mz_to_index = {mz: i for i, mz in enumerate(mass_spec_obj.mz_exp)}
142
143        for mz_exp, mz_cal in zip(mz_exp_col[differs], mz_cal_col[differs]):
144            ms_peak_index = mz_to_index.get(mz_exp)
145            if ms_peak_index is None:
146                continue
147            mass_spec_obj[ms_peak_index].mz_cal = mz_cal

Restore each peak's mz_cal from the stored "Calibrated m/z" column.

The peak table always stores both the uncalibrated "m/z" and the (possibly calibrated) "Calibrated m/z", but MassSpecCentroid is built only from "m/z" -- so without this, a reloaded peak loses its own calibration even when the spectrum it came from had been calibrated. Only peaks whose "Calibrated m/z" actually differs from "m/z" are touched; an unmatched or never-calibrated peak's mz_cal is left as None, same as before this method existed.

Parameters
  • mass_spec_obj (MassSpecCentroid): The mass spectrum object whose peaks' mz_cal to restore.
  • dataframe (pandas.DataFrame): The processed mass list data, with column names already translated via header_translate (same dataframe passed to add_molecular_formula).
def add_molecular_formula(self, mass_spec_obj, dataframe):
149    def add_molecular_formula(self, mass_spec_obj, dataframe):
150        """
151        Add molecular formula information to the mass spectrum object.
152
153        Parameters
154        ----------
155        mass_spec_obj : MassSpecCentroid
156            The mass spectrum object to add the molecular formula to.
157        dataframe : pandas.DataFrame
158            The processed mass list data.
159
160        """
161
162        # check if is coreMS file
163        if "Is Isotopologue" in dataframe:
164            # Reindex dataframe to row index to avoid issues with duplicated indexes (e.g. when multiple formula map to single mz_exp)
165            dataframe = dataframe.reset_index(drop=True)
166
167            mz_exp_df = dataframe[Labels.mz].astype(float)
168            formula_df = dataframe[
169                dataframe.columns.intersection(Atoms.atoms_order)
170            ].copy()
171            # Convert to numeric first (pandas 3.x may infer str dtype for
172            # HDF5-sourced atom count columns); coerce handles b"nan" bytes too
173            formula_df = formula_df.apply(pd.to_numeric, errors="coerce").fillna(0)
174
175            ion_type_df = dataframe["Ion Type"]
176            # Formula assignment charge from export (not peak polarity)
177            ion_charge_df = dataframe["Ion Charge"]
178            is_isotopologue_df = dataframe["Is Isotopologue"]
179            if "Adduct" in dataframe:
180                adduct_df = dataframe["Adduct"]
181            else:
182                adduct_df = None
183
184        mass_spec_mz_exp_list = mass_spec_obj.mz_exp
185
186        for df_index, mz_exp in enumerate(mz_exp_df):
187            bad_mf = False
188            counts = 0
189
190            ms_peak_index = list(mass_spec_mz_exp_list).index(float(mz_exp))
191
192            if "Is Isotopologue" in dataframe:
193                atoms = list(formula_df.columns.astype(str))
194                counts = list(formula_df.iloc[df_index].astype(int))
195
196                formula_dict = dict(zip(atoms, counts))
197
198                # Drop any atoms with 0 counts
199                formula_dict = {
200                    atom: formula_dict[atom]
201                    for atom in formula_dict
202                    if formula_dict[atom] > 0
203                }
204
205            if sum(counts) > 0:
206                # Prefer iloc for positional access (pandas 3 Series[] is label-based)
207                ion_type = str(
208                    Labels.ion_type_translate.get(ion_type_df.iloc[df_index])
209                )
210                if adduct_df is not None:
211                    adduct_atom = str(adduct_df.iloc[df_index])
212                    if adduct_atom == "None":
213                        adduct_atom = None
214                else:
215                    adduct_atom = None
216
217                # If not isotopologue, cast as MolecularFormula
218                if not bool(int(is_isotopologue_df.iloc[df_index])):
219                    mfobj = MolecularFormula(
220                        formula_dict,
221                        int(ion_charge_df.iloc[df_index]),
222                        mspeak_parent=mass_spec_obj[ms_peak_index],
223                        ion_type=ion_type,
224                        adduct_atom=adduct_atom,
225                    )
226
227                # if is isotopologue, recast as MolecularFormulaIsotopologue
228                if bool(int(is_isotopologue_df.iloc[df_index])):
229                    # First make a MolecularFormula object for the parent so we can get probabilities etc
230                    formula_list_parent = {}
231                    for atom in formula_dict:
232                        if atom in Atoms.isotopes.keys():
233                            formula_list_parent[atom] = formula_dict[atom]
234                        else:
235                            # remove any numbers from the atom name to cast as a mono-isotopic atom
236                            atom_mono = atom.strip("0123456789")
237                            if (
238                                atom_mono in Atoms.isotopes.keys()
239                                and atom_mono in formula_list_parent.keys()
240                            ):
241                                formula_list_parent[atom_mono] = (
242                                    formula_list_parent[atom_mono] + formula_dict[atom]
243                                )
244                            elif atom_mono in Atoms.isotopes.keys():
245                                formula_list_parent[atom_mono] = formula_dict[atom]
246                            else:
247                                warnings.warn(f"Atom {atom} not in Atoms.atoms_order")
248                    mono_index = int(dataframe.iloc[df_index]["Mono Isotopic Index"])
249                    mono_mfobj = MolecularFormula(
250                        formula_list_parent,
251                        int(ion_charge_df.iloc[df_index]),
252                        mspeak_parent=mass_spec_obj[mono_index],
253                        ion_type=ion_type,
254                        adduct_atom=adduct_atom,
255                    )
256
257                    # Next, generate isotopologues from the parent
258                    isos = list(
259                        mono_mfobj.isotopologues(
260                            min_abundance=mass_spec_obj.abundance.min() * 0.01,
261                            current_mono_abundance=mass_spec_obj[mono_index].abundance,
262                            dynamic_range=mass_spec_obj.dynamic_range,
263                        )
264                    )
265
266                    # Finally, find the isotopologue that matches the formula_dict
267                    matched_isos = []
268                    for iso in isos:
269                        # If match was already found, exit the loop
270                        if len(matched_isos) > 0:
271                            break
272                        else:
273                            # Check the atoms match
274                            if set(iso.atoms) == set(formula_dict.keys()):
275                                # Check the values of the atoms match
276                                if all(
277                                    [
278                                        iso[atom] == formula_dict[atom]
279                                        for atom in formula_dict
280                                    ]
281                                ):
282                                    matched_isos.append(iso)
283
284                    if len(matched_isos) == 0:
285                        # FIXME: This should not occur see https://code.emsl.pnl.gov/mass-spectrometry/corems/-/issues/190
286                        warnings.warn(
287                            f"No isotopologue matched the formula_dict: {formula_dict}"
288                        )
289                        bad_mf = True
290                    else:
291                        bad_mf = False
292                        mfobj = matched_isos[0]
293
294                        # Add the mono isotopic index, confidence score and isotopologue similarity
295                        mfobj.mspeak_index_mono_isotopic = int(
296                            dataframe.iloc[df_index]["Mono Isotopic Index"]
297                        )
298                if not bad_mf:
299                    # Add the confidence score and isotopologue similarity and average MZ error score
300                    if "m/z Error Score" in dataframe:
301                        mfobj._mass_error_average_score = float(
302                            dataframe.iloc[df_index]["m/z Error Score"]
303                        )
304                    if "Confidence Score" in dataframe:
305                        mfobj._confidence_score = float(
306                            dataframe.iloc[df_index]["Confidence Score"]
307                        )
308                    if "Isotopologue Similarity" in dataframe:
309                        mfobj._isotopologue_similarity = float(
310                            dataframe.iloc[df_index]["Isotopologue Similarity"]
311                        )
312                    mass_spec_obj[ms_peak_index].add_molecular_formula(mfobj)

Add molecular formula information to the mass spectrum object.

Parameters
  • mass_spec_obj (MassSpecCentroid): The mass spectrum object to add the molecular formula to.
  • dataframe (pandas.DataFrame): The processed mass list data.
315class ReadMassList(MassListBaseClass):
316    """
317    The ReadMassList object reads unprocessed mass list data types
318    and returns the mass spectrum object.
319
320    Parameters
321    ----------
322    MassListBaseClass : class
323        The base class for reading mass list data types.
324
325    Methods
326    -------
327    * get_mass_spectrum(polarity, scan=0, auto_process=True, loadSettings=True). Reads mass list data types and returns the mass spectrum object.
328
329    """
330
331    def get_mass_spectrum(
332        self,
333        polarity: int,
334        scan: int = 0,
335        auto_process: bool = True,
336        loadSettings: bool = True,
337    ):
338        """
339        Reads mass list data types and returns the mass spectrum object.
340
341        Parameters
342        ----------
343        polarity : int
344            The polarity of the mass spectrum (+1 or -1).
345        scan : int, optional
346            The scan number of the mass spectrum (default is 0).
347        auto_process : bool, optional
348            Flag indicating whether to automatically process the mass spectrum (default is True).
349        loadSettings : bool, optional
350            Flag indicating whether to load settings for the mass spectrum (default is True).
351
352        Returns
353        -------
354        mass_spec : MassSpecCentroid or MassSpecProfile
355            The mass spectrum object.
356
357        """
358
359        # delimiter = "  " or " " or  "," or "\t" etc
360
361        if self.isCentroid:
362            dataframe = self.get_dataframe()
363
364            self.check_columns(dataframe.columns)
365
366            self.clean_data_frame(dataframe)
367
368            dataframe.rename(columns=self.parameters.header_translate, inplace=True)
369
370            output_parameters = self.get_output_parameters(polarity)
371
372            mass_spec = MassSpecCentroid(
373                dataframe.to_dict(orient="list"),
374                output_parameters,
375                auto_process=auto_process,
376            )
377
378            if loadSettings:
379                self.load_settings(mass_spec, output_parameters)
380
381            return mass_spec
382
383        else:
384            dataframe = self.get_dataframe()
385
386            self.check_columns(dataframe.columns)
387
388            output_parameters = self.get_output_parameters(polarity)
389
390            self.clean_data_frame(dataframe)
391
392            dataframe.rename(columns=self.parameters.header_translate, inplace=True)
393
394            mass_spec = MassSpecProfile(
395                dataframe.to_dict(orient="list"),
396                output_parameters,
397                auto_process=auto_process,
398            )
399
400            if loadSettings:
401                self.load_settings(mass_spec, output_parameters)
402
403            return mass_spec

The ReadMassList object reads unprocessed mass list data types and returns the mass spectrum object.

Parameters
  • MassListBaseClass (class): The base class for reading mass list data types.
Methods
  • get_mass_spectrum(polarity, scan=0, auto_process=True, loadSettings=True). Reads mass list data types and returns the mass spectrum object.
def get_mass_spectrum( self, polarity: int, scan: int = 0, auto_process: bool = True, loadSettings: bool = True):
331    def get_mass_spectrum(
332        self,
333        polarity: int,
334        scan: int = 0,
335        auto_process: bool = True,
336        loadSettings: bool = True,
337    ):
338        """
339        Reads mass list data types and returns the mass spectrum object.
340
341        Parameters
342        ----------
343        polarity : int
344            The polarity of the mass spectrum (+1 or -1).
345        scan : int, optional
346            The scan number of the mass spectrum (default is 0).
347        auto_process : bool, optional
348            Flag indicating whether to automatically process the mass spectrum (default is True).
349        loadSettings : bool, optional
350            Flag indicating whether to load settings for the mass spectrum (default is True).
351
352        Returns
353        -------
354        mass_spec : MassSpecCentroid or MassSpecProfile
355            The mass spectrum object.
356
357        """
358
359        # delimiter = "  " or " " or  "," or "\t" etc
360
361        if self.isCentroid:
362            dataframe = self.get_dataframe()
363
364            self.check_columns(dataframe.columns)
365
366            self.clean_data_frame(dataframe)
367
368            dataframe.rename(columns=self.parameters.header_translate, inplace=True)
369
370            output_parameters = self.get_output_parameters(polarity)
371
372            mass_spec = MassSpecCentroid(
373                dataframe.to_dict(orient="list"),
374                output_parameters,
375                auto_process=auto_process,
376            )
377
378            if loadSettings:
379                self.load_settings(mass_spec, output_parameters)
380
381            return mass_spec
382
383        else:
384            dataframe = self.get_dataframe()
385
386            self.check_columns(dataframe.columns)
387
388            output_parameters = self.get_output_parameters(polarity)
389
390            self.clean_data_frame(dataframe)
391
392            dataframe.rename(columns=self.parameters.header_translate, inplace=True)
393
394            mass_spec = MassSpecProfile(
395                dataframe.to_dict(orient="list"),
396                output_parameters,
397                auto_process=auto_process,
398            )
399
400            if loadSettings:
401                self.load_settings(mass_spec, output_parameters)
402
403            return mass_spec

Reads mass list data types and returns the mass spectrum object.

Parameters
  • polarity (int): The polarity of the mass spectrum (+1 or -1).
  • scan (int, optional): The scan number of the mass spectrum (default is 0).
  • auto_process (bool, optional): Flag indicating whether to automatically process the mass spectrum (default is True).
  • loadSettings (bool, optional): Flag indicating whether to load settings for the mass spectrum (default is True).
Returns
  • mass_spec (MassSpecCentroid or MassSpecProfile): The mass spectrum object.
class ReadBrukerXMLList(corems.mass_spectrum.input.baseClass.MassListBaseClass):
406class ReadBrukerXMLList(MassListBaseClass):
407    """
408    The ReadBrukerXMLList object reads Bruker XML objects
409    and returns the mass spectrum object.
410    See MassListBaseClass for details
411
412    Parameters
413    ----------
414    MassListBaseClass : class
415        The base class for reading mass list data types and returning the mass spectrum object.
416
417    Methods
418    -------
419    * get_mass_spectrum(polarity: bool = None, scan: int = 0, auto_process: bool = True, loadSettings: bool = True). Reads mass list data types and returns the mass spectrum object.
420
421    """
422
423    def get_mass_spectrum(
424        self,
425        polarity: bool = None,
426        scan: int = 0,
427        auto_process: bool = True,
428        loadSettings: bool = True,
429    ):
430        """
431        Reads mass list data types and returns the mass spectrum object.
432
433        Parameters
434        ----------
435        polarity : bool, optional
436            The polarity of the mass spectrum. Can be +1 or -1. If not provided, it will be determined from the XML file.
437        scan : int, optional
438            The scan number of the mass spectrum. Default is 0.
439        auto_process : bool, optional
440            Whether to automatically process the mass spectrum. Default is True.
441        loadSettings : bool, optional
442            Whether to load the settings for the mass spectrum. Default is True.
443
444        Returns
445        -------
446        mass_spec : MassSpecCentroid
447            The mass spectrum object representing the centroided mass spectrum.
448        """
449        # delimiter = "  " or " " or  "," or "\t" etc
450
451        if polarity == None:
452            polarity = self.get_xml_polarity()
453        dataframe = self.get_dataframe()
454
455        self.check_columns(dataframe.columns)
456
457        self.clean_data_frame(dataframe)
458
459        dataframe.rename(columns=self.parameters.header_translate, inplace=True)
460
461        output_parameters = self.get_output_parameters(polarity)
462
463        mass_spec = MassSpecCentroid(
464            dataframe.to_dict(orient="list"),
465            output_parameters,
466            auto_process=auto_process,
467        )
468
469        if loadSettings:
470            self.load_settings(mass_spec, output_parameters)
471
472        return mass_spec

The ReadBrukerXMLList object reads Bruker XML objects and returns the mass spectrum object. See MassListBaseClass for details

Parameters
  • MassListBaseClass (class): The base class for reading mass list data types and returning the mass spectrum object.
Methods
  • get_mass_spectrum(polarity: bool = None, scan: int = 0, auto_process: bool = True, loadSettings: bool = True). Reads mass list data types and returns the mass spectrum object.
def get_mass_spectrum( self, polarity: bool = None, scan: int = 0, auto_process: bool = True, loadSettings: bool = True):
423    def get_mass_spectrum(
424        self,
425        polarity: bool = None,
426        scan: int = 0,
427        auto_process: bool = True,
428        loadSettings: bool = True,
429    ):
430        """
431        Reads mass list data types and returns the mass spectrum object.
432
433        Parameters
434        ----------
435        polarity : bool, optional
436            The polarity of the mass spectrum. Can be +1 or -1. If not provided, it will be determined from the XML file.
437        scan : int, optional
438            The scan number of the mass spectrum. Default is 0.
439        auto_process : bool, optional
440            Whether to automatically process the mass spectrum. Default is True.
441        loadSettings : bool, optional
442            Whether to load the settings for the mass spectrum. Default is True.
443
444        Returns
445        -------
446        mass_spec : MassSpecCentroid
447            The mass spectrum object representing the centroided mass spectrum.
448        """
449        # delimiter = "  " or " " or  "," or "\t" etc
450
451        if polarity == None:
452            polarity = self.get_xml_polarity()
453        dataframe = self.get_dataframe()
454
455        self.check_columns(dataframe.columns)
456
457        self.clean_data_frame(dataframe)
458
459        dataframe.rename(columns=self.parameters.header_translate, inplace=True)
460
461        output_parameters = self.get_output_parameters(polarity)
462
463        mass_spec = MassSpecCentroid(
464            dataframe.to_dict(orient="list"),
465            output_parameters,
466            auto_process=auto_process,
467        )
468
469        if loadSettings:
470            self.load_settings(mass_spec, output_parameters)
471
472        return mass_spec

Reads mass list data types and returns the mass spectrum object.

Parameters
  • polarity (bool, optional): The polarity of the mass spectrum. Can be +1 or -1. If not provided, it will be determined from the XML file.
  • scan (int, optional): The scan number of the mass spectrum. Default is 0.
  • auto_process (bool, optional): Whether to automatically process the mass spectrum. Default is True.
  • loadSettings (bool, optional): Whether to load the settings for the mass spectrum. Default is True.
Returns
  • mass_spec (MassSpecCentroid): The mass spectrum object representing the centroided mass spectrum.