corems.mass_spectrum.factory.MassSpectrumClasses

   1from pathlib import Path
   2
   3import numpy as np
   4from lmfit.models import GaussianModel
   5
   6# from matplotlib import rcParamsDefault, rcParams
   7from numpy import array, float64, histogram, where
   8try:
   9    from numpy import trapezoid
  10except ImportError:  # numpy < 2.0
  11    from numpy import trapz as trapezoid
  12from pandas import DataFrame
  13
  14from corems.encapsulation.constant import Labels
  15from corems.encapsulation.factory.parameters import MSParameters
  16from corems.encapsulation.input.parameter_from_json import (
  17    load_and_set_parameters_ms,
  18    load_and_set_toml_parameters_ms,
  19)
  20from corems.mass_spectrum.calc.KendrickGroup import KendrickGrouping
  21from corems.mass_spectrum.calc.MassSpectrumCalc import MassSpecCalc
  22from corems.mass_spectrum.calc.MeanResolvingPowerFilter import MeanResolvingPowerFilter
  23from corems.ms_peak.factory.MSPeakClasses import ICRMassPeak as MSPeak
  24
  25__author__ = "Yuri E. Corilo"
  26__date__ = "Jun 12, 2019"
  27
  28
  29def overrides(interface_class):
  30    """Checks if the method overrides a method from an interface class."""
  31
  32    def overrider(method):
  33        assert method.__name__ in dir(interface_class)
  34        return method
  35
  36    return overrider
  37
  38
  39class MassSpecBase(MassSpecCalc, KendrickGrouping):
  40    """A mass spectrum base class, stores the profile data and instrument settings.
  41
  42    Iteration over a list of MSPeaks classes stored at the _mspeaks attributes.
  43    _mspeaks is populated under the hood by calling process_mass_spec method.
  44    Iteration is null if _mspeaks is empty.
  45
  46    Parameters
  47    ----------
  48    mz_exp : array_like
  49        The m/z values of the mass spectrum.
  50    abundance : array_like
  51        The abundance values of the mass spectrum.
  52    d_params : dict
  53        A dictionary of parameters for the mass spectrum.
  54    **kwargs
  55        Additional keyword arguments.
  56
  57    Attributes
  58    ----------
  59
  60    mspeaks : list
  61        A list of mass peaks.
  62    is_calibrated : bool
  63        Whether the mass spectrum is calibrated.
  64    is_centroid : bool
  65        Whether the mass spectrum is centroided.
  66    has_frequency : bool
  67        Whether the mass spectrum has a frequency domain.
  68    calibration_order : None or int
  69        The order of the mass spectrum's calibration.
  70    calibration_points : None or ndarray
  71        The calibration points of the mass spectrum.
  72    calibration_ref_mzs: None or ndarray
  73        The reference m/z values of the mass spectrum's calibration.
  74    calibration_meas_mzs : None or ndarray
  75        The measured m/z values of the mass spectrum's calibration.
  76    calibration_RMS : None or float
  77        The root mean square of the mass spectrum's calibration.
  78    calibration_segment : None or CalibrationSegment
  79        The calibration segment of the mass spectrum.
  80    _abundance : ndarray
  81        The abundance values of the mass spectrum.
  82    _mz_exp : ndarray
  83        The m/z values of the mass spectrum.
  84    _mspeaks : list
  85        A list of mass peaks.
  86    _dict_nominal_masses_indexes : dict
  87        A dictionary of nominal masses and their indexes.
  88    _baseline_noise : float
  89        The baseline noise of the mass spectrum.
  90    _baseline_noise_std : float
  91        The standard deviation of the baseline noise of the mass spectrum.
  92    _dynamic_range : float or None
  93        The dynamic range of the mass spectrum.
  94    _transient_settings : None or TransientSettings
  95        The transient settings of the mass spectrum.
  96    _frequency_domain : None or FrequencyDomain
  97        The frequency domain of the mass spectrum.
  98    _mz_cal_profile : None or MzCalibrationProfile
  99        The m/z calibration profile of the mass spectrum.
 100
 101    Methods
 102    -------
 103    * process_mass_spec(). Main function to process the mass spectrum,
 104    including calculating the noise threshold, peak picking, and resetting the MSpeak indexes.
 105
 106    See also: MassSpecCentroid(), MassSpecfromFreq(), MassSpecProfile()
 107    """
 108
 109    def __init__(self, mz_exp, abundance, d_params, **kwargs):
 110        self._abundance = array(abundance, dtype=float64)
 111        self._mz_exp = array(mz_exp, dtype=float64)
 112
 113        # objects created after process_mass_spec() function
 114        self._mspeaks = list()
 115        self.mspeaks = list()
 116        self._dict_nominal_masses_indexes = dict()
 117        self._baseline_noise = 0.001
 118        self._baseline_noise_std = 0.001
 119        self._dynamic_range = None
 120        # set to None: initialization occurs inside subclass MassSpecfromFreq
 121        self._transient_settings = None
 122        self._frequency_domain = None
 123        self._mz_cal_profile = None
 124        self.is_calibrated = False
 125
 126        self._set_parameters_objects(d_params)
 127        self._init_settings()
 128
 129        self.is_centroid = False
 130        self.has_frequency = False
 131
 132        self.calibration_order = None
 133        self.calibration_points = None
 134        self.calibration_ref_mzs = None
 135        self.calibration_meas_mzs = None
 136        self.calibration_RMS = None
 137        self.calibration_segment = None
 138        self.calibration_raw_error_median = None
 139        self.calibration_raw_error_stdev = None
 140
 141    def _init_settings(self):
 142        """Initializes the settings for the mass spectrum."""
 143        self._parameters = MSParameters()
 144
 145    def __len__(self):
 146        return len(self.mspeaks)
 147
 148    def __getitem__(self, position) -> MSPeak:
 149        return self.mspeaks[position]
 150
 151    def set_indexes(self, list_indexes):
 152        """Set the mass spectrum to iterate over only the selected MSpeaks indexes.
 153
 154        Parameters
 155        ----------
 156        list_indexes : list of int
 157            A list of integers representing the indexes of the MSpeaks to iterate over.
 158
 159        """
 160        self.mspeaks = [self._mspeaks[i] for i in list_indexes]
 161
 162        for i, mspeak in enumerate(self.mspeaks):
 163            mspeak.index = i
 164
 165        self._set_nominal_masses_start_final_indexes()
 166
 167    def reset_indexes(self):
 168        """Reset the mass spectrum to iterate over all MSpeaks objects.
 169
 170        This method resets the mass spectrum to its original state, allowing iteration over all MSpeaks objects.
 171        It also sets the index of each MSpeak object to its corresponding position in the mass spectrum.
 172
 173        """
 174        self.mspeaks = self._mspeaks
 175
 176        for i, mspeak in enumerate(self.mspeaks):
 177            mspeak.index = i
 178
 179        self._set_nominal_masses_start_final_indexes()
 180
 181    def add_mspeak(
 182        self,
 183        ion_charge,
 184        mz_exp,
 185        abundance,
 186        resolving_power,
 187        signal_to_noise,
 188        massspec_indexes,
 189        exp_freq=None,
 190        ms_parent=None,
 191    ):
 192        """Add a new MSPeak object to the MassSpectrum object.
 193
 194        Parameters
 195        ----------
 196        ion_charge : int
 197            The ion charge of the MSPeak.
 198        mz_exp : float
 199            The experimental m/z value of the MSPeak.
 200        abundance : float
 201            The abundance of the MSPeak.
 202        resolving_power : float
 203            The resolving power of the MSPeak.
 204        signal_to_noise : float
 205            The signal-to-noise ratio of the MSPeak.
 206        massspec_indexes : list
 207            A list of indexes of the MSPeak in the MassSpectrum object.
 208        exp_freq : float, optional
 209            The experimental frequency of the MSPeak. Defaults to None.
 210        ms_parent : MSParent, optional
 211            The MSParent object associated with the MSPeak. Defaults to None.
 212        """
 213        mspeak = MSPeak(
 214            ion_charge,
 215            mz_exp,
 216            abundance,
 217            resolving_power,
 218            signal_to_noise,
 219            massspec_indexes,
 220            len(self._mspeaks),
 221            exp_freq=exp_freq,
 222            ms_parent=ms_parent,
 223        )
 224
 225        self._mspeaks.append(mspeak)
 226
 227    def _set_parameters_objects(self, d_params):
 228        """Set the parameters of the MassSpectrum object.
 229
 230        Parameters
 231        ----------
 232        d_params : dict
 233            A dictionary containing the parameters to set.
 234
 235        Notes
 236        -----
 237        This method sets the following parameters of the MassSpectrum object:
 238        - _calibration_terms
 239        - label
 240        - analyzer
 241        - acquisition_time
 242        - instrument_label
 243        - polarity
 244        - scan_number
 245        - retention_time
 246        - mobility_rt
 247        - mobility_scan
 248        - _filename
 249        - _dir_location
 250        - _baseline_noise
 251        - _baseline_noise_std
 252        - sample_name
 253        """
 254        self._calibration_terms = (
 255            d_params.get("Aterm"),
 256            d_params.get("Bterm"),
 257            d_params.get("Cterm"),
 258        )
 259
 260        self.label = d_params.get(Labels.label)
 261
 262        self.analyzer = d_params.get("analyzer")
 263
 264        self.acquisition_time = d_params.get("acquisition_time")
 265
 266        self.instrument_label = d_params.get("instrument_label")
 267
 268        self.polarity = int(d_params.get("polarity"))
 269
 270        self.scan_number = d_params.get("scan_number")
 271
 272        self.retention_time = d_params.get("rt")
 273
 274        self.mobility_rt = d_params.get("mobility_rt")
 275
 276        self.mobility_scan = d_params.get("mobility_scan")
 277
 278        self._filename = d_params.get("filename_path")
 279
 280        self._dir_location = d_params.get("dir_location")
 281
 282        self._baseline_noise = d_params.get("baseline_noise")
 283
 284        self._baseline_noise_std = d_params.get("baseline_noise_std")
 285
 286        if d_params.get("sample_name") != "Unknown":
 287            self.sample_name = d_params.get("sample_name")
 288            if not self.sample_name:
 289                self.sample_name = self.filename.stem
 290        else:
 291            self.sample_name = self.filename.stem
 292
 293    def reset_cal_therms(self, Aterm, Bterm, C, fas=0):
 294        """Reset calibration terms and recalculate the mass-to-charge ratio and abundance.
 295
 296        Parameters
 297        ----------
 298        Aterm : float
 299            The A-term calibration coefficient.
 300        Bterm : float
 301            The B-term calibration coefficient.
 302        C : float
 303            The C-term calibration coefficient.
 304        fas : float, optional
 305            The frequency amplitude scaling factor. Default is 0.
 306        """
 307        self._calibration_terms = (Aterm, Bterm, C)
 308
 309        self._mz_exp = self._f_to_mz()
 310        self._abundance = self._abundance
 311        self.find_peaks()
 312        self.reset_indexes()
 313
 314    def clear_molecular_formulas(self):
 315        """Clear the molecular formulas for all mspeaks in the MassSpectrum.
 316
 317        Returns
 318        -------
 319        numpy.ndarray
 320            An array of the cleared molecular formulas for each mspeak in the MassSpectrum.
 321        """
 322        self.check_mspeaks()
 323        return array([mspeak.clear_molecular_formulas() for mspeak in self.mspeaks])
 324
 325    def process_mass_spec(self, keep_profile=True):
 326        """Process the mass spectrum.
 327
 328        Parameters
 329        ----------
 330        keep_profile : bool, optional
 331            Whether to keep the profile data after processing. Defaults to True.
 332
 333        Notes
 334        -----
 335        This method does the following:
 336        - calculates the noise threshold
 337        - does peak picking (creates mspeak_objs)
 338        - resets the mspeak_obj indexes
 339        """
 340
 341        # if runned mannually make sure to rerun filter_by_noise_threshold
 342        # calculates noise threshold
 343        # do peak picking( create mspeak_objs)
 344        # reset mspeak_obj the indexes
 345
 346        self.cal_noise_threshold()
 347
 348        self.find_peaks()
 349        self.reset_indexes()
 350
 351        if self.mspeaks:
 352            self._dynamic_range = self.max_abundance / self.min_abundance
 353        else:
 354            self._dynamic_range = 0
 355        if not keep_profile:
 356            self._abundance *= 0
 357            self._mz_exp *= 0
 358
 359    def cal_noise_threshold(self):
 360        """Calculate the noise threshold of the mass spectrum."""
 361
 362        if self.label == Labels.simulated_profile:
 363            self._baseline_noise, self._baseline_noise_std = 0.1, 1
 364
 365        if self.settings.noise_threshold_method == "log":
 366            self._baseline_noise, self._baseline_noise_std = (
 367                self.run_log_noise_threshold_calc()
 368            )
 369
 370        else:
 371            self._baseline_noise, self._baseline_noise_std = (
 372                self.run_noise_threshold_calc()
 373            )
 374
 375    @property
 376    def parameters(self):
 377        """Return the parameters of the mass spectrum."""
 378        return self._parameters
 379
 380    @parameters.setter
 381    def parameters(self, instance_MSParameters):
 382        self._parameters = instance_MSParameters
 383
 384    def set_parameter_from_json(self, parameters_path):
 385        """Set the parameters of the mass spectrum from a JSON file.
 386
 387        Parameters
 388        ----------
 389        parameters_path : str
 390            The path to the JSON file containing the parameters.
 391        """
 392        load_and_set_parameters_ms(self, parameters_path=parameters_path)
 393
 394    def set_parameter_from_toml(self, parameters_path):
 395        load_and_set_toml_parameters_ms(self, parameters_path=parameters_path)
 396
 397    @property
 398    def mspeaks_settings(self):
 399        """Return the MS peak settings of the mass spectrum."""
 400        return self.parameters.ms_peak
 401
 402    @mspeaks_settings.setter
 403    def mspeaks_settings(self, instance_MassSpecPeakSetting):
 404        self.parameters.ms_peak = instance_MassSpecPeakSetting
 405
 406    @property
 407    def settings(self):
 408        """Return the settings of the mass spectrum."""
 409        return self.parameters.mass_spectrum
 410
 411    @settings.setter
 412    def settings(self, instance_MassSpectrumSetting):
 413        self.parameters.mass_spectrum = instance_MassSpectrumSetting
 414
 415    @property
 416    def molecular_search_settings(self):
 417        """Return the molecular search settings of the mass spectrum."""
 418        return self.parameters.molecular_search
 419
 420    @molecular_search_settings.setter
 421    def molecular_search_settings(self, instance_MolecularFormulaSearchSettings):
 422        self.parameters.molecular_search = instance_MolecularFormulaSearchSettings
 423
 424    @property
 425    def mz_cal_profile(self):
 426        """Return the calibrated m/z profile of the mass spectrum."""
 427        return self._mz_cal_profile
 428
 429    @mz_cal_profile.setter
 430    def mz_cal_profile(self, mz_cal_list):
 431        if len(mz_cal_list) == len(self._mz_exp):
 432            self._mz_cal_profile = mz_cal_list
 433        else:
 434            raise Exception(
 435                "calibrated array (%i) is not of the same size of the data (%i)"
 436                % (len(mz_cal_list), len(self.mz_exp_profile))
 437            )
 438
 439    @property
 440    def mz_cal(self):
 441        """Return the calibrated m/z values of the mass spectrum."""
 442        return array([mspeak.mz_cal for mspeak in self.mspeaks])
 443
 444    @mz_cal.setter
 445    def mz_cal(self, mz_cal_list):
 446        if len(mz_cal_list) == len(self.mspeaks):
 447            self.is_calibrated = True
 448            for index, mz_cal in enumerate(mz_cal_list):
 449                self.mspeaks[index].mz_cal = mz_cal
 450        else:
 451            raise Exception(
 452                "calibrated array (%i) is not of the same size of the data (%i)"
 453                % (len(mz_cal_list), len(self._mspeaks))
 454            )
 455
 456    @property
 457    def mz_exp(self):
 458        """Return the experimental m/z values of the mass spectrum."""
 459        self.check_mspeaks()
 460
 461        if self.is_calibrated:
 462            return array([mspeak.mz_cal for mspeak in self.mspeaks])
 463
 464        else:
 465            return array([mspeak.mz_exp for mspeak in self.mspeaks])
 466
 467    @property
 468    def freq_exp_profile(self):
 469        """Return the experimental frequency profile of the mass spectrum."""
 470        return self._frequency_domain
 471
 472    @freq_exp_profile.setter
 473    def freq_exp_profile(self, new_data):
 474        self._frequency_domain = array(new_data)
 475
 476    @property
 477    def freq_exp_pp(self):
 478        """Return the experimental frequency values of the mass spectrum that are used for peak picking."""
 479        _, _, freq = self.prepare_peak_picking_data()
 480        return freq
 481
 482    @property
 483    def mz_exp_profile(self):
 484        """Return the experimental m/z profile of the mass spectrum."""
 485        if self.is_calibrated:
 486            return self.mz_cal_profile
 487        else:
 488            return self._mz_exp
 489
 490    @mz_exp_profile.setter
 491    def mz_exp_profile(self, new_data):
 492        self._mz_exp = array(new_data)
 493
 494    @property
 495    def mz_exp_pp(self):
 496        """Return the experimental m/z values of the mass spectrum that are used for peak picking."""
 497        mz, _, _ = self.prepare_peak_picking_data()
 498        return mz
 499
 500    @property
 501    def abundance_profile(self):
 502        """Return the abundance profile of the mass spectrum."""
 503        return self._abundance
 504
 505    @abundance_profile.setter
 506    def abundance_profile(self, new_data):
 507        self._abundance = array(new_data)
 508
 509    @property
 510    def abundance_profile_pp(self):
 511        """Return the abundance profile of the mass spectrum that is used for peak picking."""
 512        _, abundance, _ = self.prepare_peak_picking_data()
 513        return abundance
 514
 515    @property
 516    def abundance(self):
 517        """Return the abundance values of the mass spectrum."""
 518        self.check_mspeaks()
 519        return array([mspeak.abundance for mspeak in self.mspeaks])
 520
 521    def freq_exp(self):
 522        """Return the experimental frequency values of the mass spectrum."""
 523        self.check_mspeaks()
 524        return array([mspeak.freq_exp for mspeak in self.mspeaks])
 525
 526    @property
 527    def resolving_power(self):
 528        """Return the resolving power values of the mass spectrum."""
 529        self.check_mspeaks()
 530        return array([mspeak.resolving_power for mspeak in self.mspeaks])
 531
 532    @property
 533    def signal_to_noise(self):
 534        self.check_mspeaks()
 535        return array([mspeak.signal_to_noise for mspeak in self.mspeaks])
 536
 537    @property
 538    def nominal_mz(self):
 539        """Return the nominal m/z values of the mass spectrum."""
 540        if self._dict_nominal_masses_indexes:
 541            return sorted(list(self._dict_nominal_masses_indexes.keys()))
 542        else:
 543            raise ValueError("Nominal indexes not yet set")
 544
 545    def get_mz_and_abundance_peaks_tuples(self):
 546        """Return a list of tuples containing the m/z and abundance values of the mass spectrum."""
 547        self.check_mspeaks()
 548        return [(mspeak.mz_exp, mspeak.abundance) for mspeak in self.mspeaks]
 549
 550    @property
 551    def kmd(self):
 552        """Return the Kendrick mass defect values of the mass spectrum."""
 553        self.check_mspeaks()
 554        return array([mspeak.kmd for mspeak in self.mspeaks])
 555
 556    @property
 557    def kendrick_mass(self):
 558        """Return the Kendrick mass values of the mass spectrum."""
 559        self.check_mspeaks()
 560        return array([mspeak.kendrick_mass for mspeak in self.mspeaks])
 561
 562    @property
 563    def max_mz_exp(self):
 564        """Return the maximum experimental m/z value of the mass spectrum."""
 565        return max([mspeak.mz_exp for mspeak in self.mspeaks])
 566
 567    @property
 568    def min_mz_exp(self):
 569        """Return the minimum experimental m/z value of the mass spectrum."""
 570        return min([mspeak.mz_exp for mspeak in self.mspeaks])
 571
 572    @property
 573    def max_abundance(self):
 574        """Return the maximum abundance value of the mass spectrum."""
 575        return max([mspeak.abundance for mspeak in self.mspeaks])
 576
 577    @property
 578    def max_signal_to_noise(self):
 579        """Return the maximum signal-to-noise ratio of the mass spectrum."""
 580        return max([mspeak.signal_to_noise for mspeak in self.mspeaks])
 581
 582    @property
 583    def most_abundant_mspeak(self):
 584        """Return the most abundant MSpeak object of the mass spectrum."""
 585        return max(self.mspeaks, key=lambda m: m.abundance)
 586
 587    @property
 588    def min_abundance(self):
 589        """Return the minimum abundance value of the mass spectrum."""
 590        return min([mspeak.abundance for mspeak in self.mspeaks])
 591
 592    # takes too much cpu time
 593    @property
 594    def dynamic_range(self):
 595        """Return the dynamic range of the mass spectrum."""
 596        return self._dynamic_range
 597
 598    @property
 599    def baseline_noise(self):
 600        """Return the baseline noise of the mass spectrum."""
 601        if self._baseline_noise:
 602            return self._baseline_noise
 603        else:
 604            return None
 605
 606    @property
 607    def baseline_noise_std(self):
 608        """Return the standard deviation of the baseline noise of the mass spectrum."""
 609        if self._baseline_noise_std == 0:
 610            return self._baseline_noise_std
 611        if self._baseline_noise_std:
 612            return self._baseline_noise_std
 613        else:
 614            return None
 615
 616    @property
 617    def Aterm(self):
 618        """Return the A-term calibration coefficient of the mass spectrum."""
 619        return self._calibration_terms[0]
 620
 621    @property
 622    def Bterm(self):
 623        """Return the B-term calibration coefficient of the mass spectrum."""
 624        return self._calibration_terms[1]
 625
 626    @property
 627    def Cterm(self):
 628        """Return the C-term calibration coefficient of the mass spectrum."""
 629        return self._calibration_terms[2]
 630
 631    @property
 632    def filename(self):
 633        """Return the filename of the mass spectrum."""
 634        return Path(self._filename)
 635
 636    @property
 637    def dir_location(self):
 638        """Return the directory location of the mass spectrum."""
 639        return self._dir_location
 640
 641    def sort_by_mz(self):
 642        """Sort the mass spectrum by m/z values."""
 643        return sorted(self, key=lambda m: m.mz_exp)
 644
 645    def sort_by_abundance(self, reverse=False):
 646        """Sort the mass spectrum by abundance values."""
 647        return sorted(self, key=lambda m: m.abundance, reverse=reverse)
 648
 649    @property
 650    def tic(self):
 651        """Return the total ion current of the mass spectrum."""
 652        return trapezoid(self.abundance_profile, self.mz_exp_profile)
 653
 654    def check_mspeaks_warning(self):
 655        """Check if the mass spectrum has MSpeaks objects.
 656
 657        Raises
 658        ------
 659        Warning
 660            If the mass spectrum has no MSpeaks objects.
 661        """
 662        import warnings
 663
 664        if self.mspeaks:
 665            pass
 666        else:
 667            warnings.warn("mspeaks list is empty, continuing without filtering data")
 668
 669    def check_mspeaks(self):
 670        """Check if the mass spectrum has MSpeaks objects.
 671
 672        Raises
 673        ------
 674        Exception
 675            If the mass spectrum has no MSpeaks objects.
 676        """
 677        if self.mspeaks:
 678            pass
 679        else:
 680            raise Exception(
 681                "mspeaks list is empty, please run process_mass_spec() first"
 682            )
 683
 684    def remove_assignment_by_index(self, indexes):
 685        """Remove the molecular formula assignment of the MSpeaks objects at the specified indexes.
 686
 687        Parameters
 688        ----------
 689        indexes : list of int
 690            A list of indexes of the MSpeaks objects to remove the molecular formula assignment from.
 691        """
 692        for i in indexes:
 693            self.mspeaks[i].clear_molecular_formulas()
 694
 695    def filter_by_index(self, list_indexes):
 696        """Filter the mass spectrum by the specified indexes.
 697
 698        Parameters
 699        ----------
 700        list_indexes : list of int
 701            A list of indexes of the MSpeaks objects to drop.
 702
 703        """
 704
 705        self.mspeaks = [
 706            self.mspeaks[i] for i in range(len(self.mspeaks)) if i not in list_indexes
 707        ]
 708
 709        for i, mspeak in enumerate(self.mspeaks):
 710            mspeak.index = i
 711
 712        self._set_nominal_masses_start_final_indexes()
 713
 714    def filter_by_mz(self, min_mz, max_mz):
 715        """Filter the mass spectrum by the specified m/z range.
 716
 717        Parameters
 718        ----------
 719        min_mz : float
 720            The minimum m/z value to keep.
 721        max_mz : float
 722            The maximum m/z value to keep.
 723
 724        """
 725        self.check_mspeaks_warning()
 726        indexes = [
 727            index
 728            for index, mspeak in enumerate(self.mspeaks)
 729            if not min_mz <= mspeak.mz_exp <= max_mz
 730        ]
 731        self.filter_by_index(indexes)
 732
 733    def filter_by_s2n(self, min_s2n, max_s2n=False):
 734        """Filter the mass spectrum by the specified signal-to-noise ratio range.
 735
 736        Parameters
 737        ----------
 738        min_s2n : float
 739            The minimum signal-to-noise ratio to keep.
 740        max_s2n : float, optional
 741            The maximum signal-to-noise ratio to keep. Defaults to False (no maximum).
 742
 743        """
 744        self.check_mspeaks_warning()
 745        if max_s2n:
 746            indexes = [
 747                index
 748                for index, mspeak in enumerate(self.mspeaks)
 749                if not min_s2n <= mspeak.signal_to_noise <= max_s2n
 750            ]
 751        else:
 752            indexes = [
 753                index
 754                for index, mspeak in enumerate(self.mspeaks)
 755                if mspeak.signal_to_noise <= min_s2n
 756            ]
 757        self.filter_by_index(indexes)
 758
 759    def filter_by_abundance(self, min_abund, max_abund=False):
 760        """Filter the mass spectrum by the specified abundance range.
 761
 762        Parameters
 763        ----------
 764        min_abund : float
 765            The minimum abundance to keep.
 766        max_abund : float, optional
 767            The maximum abundance to keep. Defaults to False (no maximum).
 768
 769        """
 770        self.check_mspeaks_warning()
 771        if max_abund:
 772            indexes = [
 773                index
 774                for index, mspeak in enumerate(self.mspeaks)
 775                if not min_abund <= mspeak.abundance <= max_abund
 776            ]
 777        else:
 778            indexes = [
 779                index
 780                for index, mspeak in enumerate(self.mspeaks)
 781                if mspeak.abundance <= min_abund
 782            ]
 783        self.filter_by_index(indexes)
 784
 785    def filter_by_max_resolving_power(self, B, T):
 786        """Filter the mass spectrum by the specified maximum resolving power.
 787
 788        Parameters
 789        ----------
 790        B : float
 791        T : float
 792
 793        """
 794
 795        rpe = lambda m, z: (1.274e7 * z * B * T) / (m * z)
 796
 797        self.check_mspeaks_warning()
 798
 799        indexes_to_remove = [
 800            index
 801            for index, mspeak in enumerate(self.mspeaks)
 802            if mspeak.resolving_power >= rpe(mspeak.mz_exp, mspeak.ion_charge)
 803        ]
 804        self.filter_by_index(indexes_to_remove)
 805
 806    def filter_by_mean_resolving_power(
 807        self, ndeviations=3, plot=False, guess_pars=False
 808    ):
 809        """Filter the mass spectrum by the specified mean resolving power.
 810
 811        Parameters
 812        ----------
 813        ndeviations : float, optional
 814            The number of standard deviations to use for filtering. Defaults to 3.
 815        plot : bool, optional
 816            Whether to plot the resolving power distribution. Defaults to False.
 817        guess_pars : bool, optional
 818            Whether to guess the parameters for the Gaussian model. Defaults to False.
 819
 820        """
 821        self.check_mspeaks_warning()
 822        indexes_to_remove = MeanResolvingPowerFilter(
 823            self, ndeviations, plot, guess_pars
 824        ).main()
 825        self.filter_by_index(indexes_to_remove)
 826
 827    def filter_by_min_resolving_power(self, B, T, apodization_method: str=None, tolerance: float=0):
 828        """Filter the mass spectrum by the calculated minimum theoretical resolving power.
 829
 830        This is currently designed only for FTICR data, and accounts only for magnitude mode data
 831        Accurate results require passing the apodisaion method used to calculate the resolving power.
 832        see the ICRMassPeak function `resolving_power_calc` for more details.
 833
 834        Parameters
 835        ----------
 836        B : Magnetic field strength in Tesla, float
 837        T : transient length in seconds, float
 838        apodization_method : str, optional
 839            The apodization method to use for calculating the resolving power. Defaults to None.
 840        tolerance : float, optional
 841            The tolerance for the threshold. Defaults to 0, i.e. no tolerance
 842
 843        """
 844        if self.analyzer != "ICR":
 845            raise Exception(
 846                "This method is only applicable to ICR mass spectra. "
 847            )
 848
 849        self.check_mspeaks_warning()
 850
 851        indexes_to_remove = [
 852            index
 853            for index, mspeak in enumerate(self.mspeaks)
 854            if mspeak.resolving_power < (1-tolerance) * mspeak.resolving_power_calc(B, T, apodization_method=apodization_method)
 855        ]
 856        self.filter_by_index(indexes_to_remove)
 857
 858    def filter_by_noise_threshold(self):
 859        """Filter the mass spectrum by the noise threshold."""
 860
 861        threshold = self.get_noise_threshold()[1][0]
 862
 863        self.check_mspeaks_warning()
 864
 865        indexes_to_remove = [
 866            index
 867            for index, mspeak in enumerate(self.mspeaks)
 868            if mspeak.abundance <= threshold
 869        ]
 870        self.filter_by_index(indexes_to_remove)
 871
 872    def find_peaks(self):
 873        """Find the peaks of the mass spectrum."""
 874        # needs to clear previous results from peak_picking
 875        self._mspeaks = list()
 876
 877        # then do peak picking
 878        self.do_peak_picking()
 879        # print("A total of %i peaks were found" % len(self._mspeaks))
 880
 881    def change_kendrick_base_all_mspeaks(self, kendrick_dict_base):
 882        """Change the Kendrick base of all MSpeaks objects.
 883
 884        Parameters
 885        ----------
 886        kendrick_dict_base : dict
 887            A dictionary of the Kendrick base to change to.
 888
 889        Notes
 890        -----
 891        Example of kendrick_dict_base parameter: kendrick_dict_base = {"C": 1, "H": 2} or {"C": 1, "H": 1, "O":1} etc
 892        """
 893        self.parameters.ms_peak.kendrick_base = kendrick_dict_base
 894
 895        for mspeak in self.mspeaks:
 896            mspeak.change_kendrick_base(kendrick_dict_base)
 897
 898    def get_nominal_mz_first_last_indexes(self, nominal_mass):
 899        """Return the first and last indexes of the MSpeaks objects with the specified nominal mass.
 900
 901        Parameters
 902        ----------
 903        nominal_mass : int
 904            The nominal mass to get the indexes for.
 905
 906        Returns
 907        -------
 908        tuple
 909            A tuple containing the first and last indexes of the MSpeaks objects with the specified nominal mass.
 910        """
 911        if self._dict_nominal_masses_indexes:
 912            if nominal_mass in self._dict_nominal_masses_indexes.keys():
 913                return (
 914                    self._dict_nominal_masses_indexes.get(nominal_mass)[0],
 915                    self._dict_nominal_masses_indexes.get(nominal_mass)[1] + 1,
 916                )
 917
 918            else:
 919                # import warnings
 920                # uncomment warn to distribution
 921                # warnings.warn("Nominal mass not found in _dict_nominal_masses_indexes, returning (0, 0) for nominal mass %i"%nominal_mass)
 922                return (0, 0)
 923        else:
 924            raise Exception(
 925                "run process_mass_spec() function before trying to access the data"
 926            )
 927
 928    def get_masses_count_by_nominal_mass(self):
 929        """Return a dictionary of the nominal masses and their counts."""
 930
 931        dict_nominal_masses_count = {}
 932
 933        all_nominal_masses = list(set([i.nominal_mz_exp for i in self.mspeaks]))
 934
 935        for nominal_mass in all_nominal_masses:
 936            if nominal_mass not in dict_nominal_masses_count:
 937                dict_nominal_masses_count[nominal_mass] = len(
 938                    list(self.get_nominal_mass_indexes(nominal_mass))
 939                )
 940
 941        return dict_nominal_masses_count
 942
 943    def datapoints_count_by_nominal_mz(self, mz_overlay=0.1):
 944        """Return a dictionary of the nominal masses and their counts.
 945
 946        Parameters
 947        ----------
 948        mz_overlay : float, optional
 949            The m/z overlay to use for counting. Defaults to 0.1.
 950
 951        Returns
 952        -------
 953        dict
 954            A dictionary of the nominal masses and their counts.
 955        """
 956        dict_nominal_masses_count = {}
 957
 958        all_nominal_masses = list(set([i.nominal_mz_exp for i in self.mspeaks]))
 959
 960        for nominal_mass in all_nominal_masses:
 961            if nominal_mass not in dict_nominal_masses_count:
 962                min_mz = nominal_mass - mz_overlay
 963
 964                max_mz = nominal_mass + 1 + mz_overlay
 965
 966                indexes = indexes = where(
 967                    (self.mz_exp_profile > min_mz) & (self.mz_exp_profile < max_mz)
 968                )
 969
 970                dict_nominal_masses_count[nominal_mass] = indexes[0].size
 971
 972        return dict_nominal_masses_count
 973
 974    def get_nominal_mass_indexes(self, nominal_mass, overlay=0.1):
 975        """Return the indexes of the MSpeaks objects with the specified nominal mass.
 976
 977        Parameters
 978        ----------
 979        nominal_mass : int
 980            The nominal mass to get the indexes for.
 981        overlay : float, optional
 982            The m/z overlay to use for counting. Defaults to 0.1.
 983
 984        Returns
 985        -------
 986        generator
 987            A generator of the indexes of the MSpeaks objects with the specified nominal mass.
 988        """
 989        min_mz_to_look = nominal_mass - overlay
 990        max_mz_to_look = nominal_mass + 1 + overlay
 991
 992        return (
 993            i
 994            for i in range(len(self.mspeaks))
 995            if min_mz_to_look <= self.mspeaks[i].mz_exp <= max_mz_to_look
 996        )
 997
 998        # indexes = (i for i in range(len(self.mspeaks)) if min_mz_to_look <= self.mspeaks[i].mz_exp <= max_mz_to_look)
 999        # return indexes
1000
1001    def _set_nominal_masses_start_final_indexes(self):
1002        """Set the start and final indexes of the MSpeaks objects for all nominal masses."""
1003        dict_nominal_masses_indexes = {}
1004
1005        all_nominal_masses = set(i.nominal_mz_exp for i in self.mspeaks)
1006
1007        for nominal_mass in all_nominal_masses:
1008            # indexes = self.get_nominal_mass_indexes(nominal_mass)
1009            # Convert the iterator to a list to avoid multiple calls
1010            indexes = list(self.get_nominal_mass_indexes(nominal_mass))
1011
1012            # If the list is not empty, find the first and last; otherwise, set None
1013            if indexes:
1014                first, last = indexes[0], indexes[-1]
1015            else:
1016                first = last = None
1017            # defaultvalue = None
1018            # first = last = next(indexes, defaultvalue)
1019            # for last in indexes:
1020            #    pass
1021
1022            dict_nominal_masses_indexes[nominal_mass] = (first, last)
1023
1024        self._dict_nominal_masses_indexes = dict_nominal_masses_indexes
1025
1026    def plot_centroid(self, ax=None, c="g"):
1027        """Plot the centroid data of the mass spectrum.
1028
1029        Parameters
1030        ----------
1031        ax : matplotlib.axes.Axes, optional
1032            The matplotlib axes to plot on. Defaults to None.
1033        c : str, optional
1034            The color to use for the plot. Defaults to 'g' (green).
1035
1036        Returns
1037        -------
1038        matplotlib.axes.Axes
1039            The matplotlib axes containing the plot.
1040
1041        Raises
1042        ------
1043        Exception
1044            If no centroid data is found.
1045        """
1046
1047        import matplotlib.pyplot as plt
1048
1049        if self._mspeaks:
1050            if ax is None:
1051                ax = plt.gca()
1052
1053            markerline_a, stemlines_a, baseline_a = ax.stem(
1054                self.mz_exp, self.abundance, linefmt="-", markerfmt=" "
1055            )
1056
1057            plt.setp(markerline_a, "color", c, "linewidth", 2)
1058            plt.setp(stemlines_a, "color", c, "linewidth", 2)
1059            plt.setp(baseline_a, "color", c, "linewidth", 2)
1060
1061            ax.set_xlabel("$\t{m/z}$", fontsize=12)
1062            ax.set_ylabel("Abundance", fontsize=12)
1063            ax.tick_params(axis="both", which="major", labelsize=12)
1064
1065            ax.axes.spines["top"].set_visible(False)
1066            ax.axes.spines["right"].set_visible(False)
1067
1068            ax.get_yaxis().set_visible(False)
1069            ax.spines["left"].set_visible(False)
1070
1071        else:
1072            raise Exception("No centroid data found, please run process_mass_spec")
1073
1074        return ax
1075
1076    def plot_profile_and_noise_threshold(self, ax=None, legend=False):
1077        """Plot the profile data and noise threshold of the mass spectrum.
1078
1079        Parameters
1080        ----------
1081        ax : matplotlib.axes.Axes, optional
1082            The matplotlib axes to plot on. Defaults to None.
1083        legend : bool, optional
1084            Whether to show the legend. Defaults to False.
1085
1086        Returns
1087        -------
1088        matplotlib.axes.Axes
1089            The matplotlib axes containing the plot.
1090
1091        Raises
1092        ------
1093        Exception
1094            If no noise threshold is found.
1095        """
1096        import matplotlib.pyplot as plt
1097
1098        if self.baseline_noise_std and self.baseline_noise_std:
1099            # x = (self.mz_exp_profile.min(), self.mz_exp_profile.max())
1100            baseline = (self.baseline_noise, self.baseline_noise)
1101
1102            # std = self.parameters.mass_spectrum.noise_threshold_min_std
1103            # threshold = self.baseline_noise_std + (std * self.baseline_noise_std)
1104            x, y = self.get_noise_threshold()
1105
1106            if ax is None:
1107                ax = plt.gca()
1108
1109            ax.plot(
1110                self.mz_exp_profile,
1111                self.abundance_profile,
1112                color="green",
1113                label="Spectrum",
1114            )
1115            ax.plot(x, (baseline, baseline), color="yellow", label="Baseline Noise")
1116            ax.plot(x, y, color="red", label="Noise Threshold")
1117
1118            ax.set_xlabel("$\t{m/z}$", fontsize=12)
1119            ax.set_ylabel("Abundance", fontsize=12)
1120            ax.tick_params(axis="both", which="major", labelsize=12)
1121
1122            ax.axes.spines["top"].set_visible(False)
1123            ax.axes.spines["right"].set_visible(False)
1124
1125            ax.get_yaxis().set_visible(False)
1126            ax.spines["left"].set_visible(False)
1127            if legend:
1128                ax.legend()
1129
1130        else:
1131            raise Exception("Calculate noise threshold first")
1132
1133        return ax
1134
1135    def plot_mz_domain_profile(self, color="green", ax=None):
1136        """Plot the m/z domain profile of the mass spectrum.
1137
1138        Parameters
1139        ----------
1140        color : str, optional
1141            The color to use for the plot. Defaults to 'green'.
1142        ax : matplotlib.axes.Axes, optional
1143            The matplotlib axes to plot on. Defaults to None.
1144
1145        Returns
1146        -------
1147        matplotlib.axes.Axes
1148            The matplotlib axes containing the plot.
1149        """
1150
1151        import matplotlib.pyplot as plt
1152
1153        if ax is None:
1154            ax = plt.gca()
1155        ax.plot(self.mz_exp_profile, self.abundance_profile, color=color)
1156        ax.set(xlabel="m/z", ylabel="abundance")
1157
1158        return ax
1159
1160    def to_excel(self, out_file_path, write_metadata=True):
1161        """Export the mass spectrum to an Excel file.
1162
1163        Parameters
1164        ----------
1165        out_file_path : str
1166            The path to the Excel file to export to.
1167        write_metadata : bool, optional
1168            Whether to write the metadata to the Excel file. Defaults to True.
1169
1170        Returns
1171        -------
1172        None
1173        """
1174        from corems.mass_spectrum.output.export import HighResMassSpecExport
1175
1176        exportMS = HighResMassSpecExport(out_file_path, self)
1177        exportMS.to_excel(write_metadata=write_metadata)
1178
1179    def to_hdf(self, out_file_path):
1180        """Export the mass spectrum to an HDF file.
1181
1182        Parameters
1183        ----------
1184        out_file_path : str
1185            The path to the HDF file to export to.
1186
1187        Returns
1188        -------
1189        None
1190        """
1191        from corems.mass_spectrum.output.export import HighResMassSpecExport
1192
1193        exportMS = HighResMassSpecExport(out_file_path, self)
1194        exportMS.to_hdf()
1195
1196    def to_csv(self, out_file_path, write_metadata=True):
1197        """Export the mass spectrum to a CSV file.
1198
1199        Parameters
1200        ----------
1201        out_file_path : str
1202            The path to the CSV file to export to.
1203        write_metadata : bool, optional
1204            Whether to write the metadata to the CSV file. Defaults to True.
1205
1206        """
1207        from corems.mass_spectrum.output.export import HighResMassSpecExport
1208
1209        exportMS = HighResMassSpecExport(out_file_path, self)
1210        exportMS.to_csv(write_metadata=write_metadata)
1211
1212    def to_pandas(self, out_file_path, write_metadata=True):
1213        """Export the mass spectrum to a Pandas dataframe with pkl extension.
1214
1215        Parameters
1216        ----------
1217        out_file_path : str
1218            The path to the CSV file to export to.
1219        write_metadata : bool, optional
1220            Whether to write the metadata to the CSV file. Defaults to True.
1221
1222        """
1223        from corems.mass_spectrum.output.export import HighResMassSpecExport
1224
1225        exportMS = HighResMassSpecExport(out_file_path, self)
1226        exportMS.to_pandas(write_metadata=write_metadata)
1227
1228    def to_dataframe(self, additional_columns=None):
1229        """Return the mass spectrum as a Pandas dataframe.
1230
1231        Parameters
1232        ----------
1233        additional_columns : list, optional
1234            A list of additional columns to include in the dataframe. Defaults to None.
1235            Suitable columns are: "Aromaticity Index", "Aromaticity Index (modified)", and "NOSC"
1236
1237        Returns
1238        -------
1239        pandas.DataFrame
1240            The mass spectrum as a Pandas dataframe.
1241        """
1242        from corems.mass_spectrum.output.export import HighResMassSpecExport
1243
1244        exportMS = HighResMassSpecExport(self.filename, self)
1245        return exportMS.get_pandas_df(additional_columns=additional_columns)
1246
1247    def to_json(self):
1248        """Return the mass spectrum as a JSON file."""
1249        from corems.mass_spectrum.output.export import HighResMassSpecExport
1250
1251        exportMS = HighResMassSpecExport(self.filename, self)
1252        return exportMS.to_json()
1253
1254    def parameters_json(self):
1255        """Return the parameters of the mass spectrum as a JSON string."""
1256        from corems.mass_spectrum.output.export import HighResMassSpecExport
1257
1258        exportMS = HighResMassSpecExport(self.filename, self)
1259        return exportMS.parameters_to_json()
1260
1261    def parameters_toml(self):
1262        """Return the parameters of the mass spectrum as a TOML string."""
1263        from corems.mass_spectrum.output.export import HighResMassSpecExport
1264
1265        exportMS = HighResMassSpecExport(self.filename, self)
1266        return exportMS.parameters_to_toml()
1267
1268
1269class MassSpecProfile(MassSpecBase):
1270    """A mass spectrum class when the entry point is on profile format
1271
1272    Notes
1273    -----
1274    Stores the profile data and instrument settings.
1275    Iteration over a list of MSPeaks classes stored at the _mspeaks attributes.
1276    _mspeaks is populated under the hood by calling process_mass_spec method.
1277    Iteration is null if _mspeaks is empty. Many more attributes and methods inherited from MassSpecBase().
1278
1279    Parameters
1280    ----------
1281    data_dict : dict
1282        A dictionary containing the profile data.
1283    d_params : dict{'str': float, int or str}
1284        contains the instrument settings and processing settings
1285    auto_process : bool, optional
1286        Whether to automatically process the mass spectrum. Defaults to True.
1287
1288
1289    Attributes
1290    ----------
1291    _abundance : ndarray
1292        The abundance values of the mass spectrum.
1293    _mz_exp : ndarray
1294        The m/z values of the mass spectrum.
1295    _mspeaks : list
1296        A list of mass peaks.
1297
1298    Methods
1299    ----------
1300    * process_mass_spec(). Process the mass spectrum.
1301
1302    see also: MassSpecBase(), MassSpecfromFreq(), MassSpecCentroid()
1303    """
1304
1305    def __init__(self, data_dict, d_params, auto_process=True):
1306        # print(data_dict.keys())
1307        super().__init__(
1308            data_dict.get(Labels.mz), data_dict.get(Labels.abundance), d_params
1309        )
1310
1311        if auto_process:
1312            self.process_mass_spec()
1313
1314
1315class MassSpecfromFreq(MassSpecBase):
1316    """A mass spectrum class when data entry is on frequency domain
1317
1318    Notes
1319    -----
1320    - Transform to m/z based on the settings stored at d_params
1321    - Stores the profile data and instrument settings
1322    - Iteration over a list of MSPeaks classes stored at the _mspeaks attributes
1323    - _mspeaks is populated under the hood by calling process_mass_spec method
1324    - iteration is null if _mspeaks is empty
1325
1326    Parameters
1327    ----------
1328    frequency_domain : list(float)
1329        all datapoints in frequency domain in Hz
1330    magnitude :  frequency_domain : list(float)
1331        all datapoints in for magnitude of each frequency datapoint
1332    d_params : dict{'str': float, int or str}
1333        contains the instrument settings and processing settings
1334    auto_process : bool, optional
1335        Whether to automatically process the mass spectrum. Defaults to True.
1336    keep_profile : bool, optional
1337        Whether to keep the profile data. Defaults to True.
1338
1339    Attributes
1340    ----------
1341    has_frequency : bool
1342        Whether the mass spectrum has frequency data.
1343    _frequency_domain : list(float)
1344        Frequency domain in Hz
1345    label : str
1346        store label (Bruker, Midas Transient, see Labels class ). It across distinct processing points
1347    _abundance : ndarray
1348        The abundance values of the mass spectrum.
1349    _mz_exp : ndarray
1350        The m/z values of the mass spectrum.
1351    _mspeaks : list
1352        A list of mass peaks.
1353    See Also: all the attributes of MassSpecBase class
1354
1355    Methods
1356    ----------
1357    * _set_mz_domain().
1358        calculates the m_z based on the setting of d_params
1359    * process_mass_spec().  Process the mass spectrum.
1360
1361    see also: MassSpecBase(), MassSpecProfile(), MassSpecCentroid()
1362    """
1363
1364    def __init__(
1365        self,
1366        frequency_domain,
1367        magnitude,
1368        d_params,
1369        auto_process=True,
1370        keep_profile=True,
1371    ):
1372        super().__init__(None, magnitude, d_params)
1373
1374        self._frequency_domain = frequency_domain
1375        self.has_frequency = True
1376        self._set_mz_domain()
1377        self._sort_mz_domain()
1378
1379        self.magnetron_frequency = None
1380        self.magnetron_frequency_sigma = None
1381
1382        # use this call to automatically process data as the object is created, Setting need to be changed before initiating the class to be in effect
1383
1384        if auto_process:
1385            self.process_mass_spec(keep_profile=keep_profile)
1386
1387    def _sort_mz_domain(self):
1388        """Sort the mass spectrum by m/z values."""
1389
1390        if self._mz_exp[0] > self._mz_exp[-1]:
1391            self._mz_exp = self._mz_exp[::-1]
1392            self._abundance = self._abundance[::-1]
1393            self._frequency_domain = self._frequency_domain[::-1]
1394
1395    def _set_mz_domain(self):
1396        """Set the m/z domain of the mass spectrum based on the settings of d_params."""
1397        if self.label == Labels.bruker_frequency:
1398            self._mz_exp = self._f_to_mz_bruker()
1399
1400        else:
1401            self._mz_exp = self._f_to_mz()
1402
1403    @property
1404    def transient_settings(self):
1405        """Return the transient settings of the mass spectrum."""
1406        return self.parameters.transient
1407
1408    @transient_settings.setter
1409    def transient_settings(self, instance_TransientSetting):
1410        self.parameters.transient = instance_TransientSetting
1411
1412    def calc_magnetron_freq(self, max_magnetron_freq=50, magnetron_freq_bins=300):
1413        """Calculates the magnetron frequency of the mass spectrum.
1414
1415        Parameters
1416        ----------
1417        max_magnetron_freq : float, optional
1418            The maximum magnetron frequency. Defaults to 50.
1419        magnetron_freq_bins : int, optional
1420            The number of bins to use for the histogram. Defaults to 300.
1421
1422        Returns
1423        -------
1424        None
1425
1426        Notes
1427        -----
1428        Calculates the magnetron frequency by examining all the picked peaks and the distances between them in the frequency domain.
1429        A histogram of those values below the threshold 'max_magnetron_freq' with the 'magnetron_freq_bins' number of bins is calculated.
1430        A gaussian model is fit to this histogram - the center value of this (statistically probably) the magnetron frequency.
1431        This appears to work well or nOmega datasets, but may not work well for 1x datasets or those with very low magnetron peaks.
1432        """
1433        ms_df = DataFrame(self.freq_exp(), columns=["Freq"])
1434        ms_df["FreqDelta"] = ms_df["Freq"].diff()
1435
1436        freq_hist = histogram(
1437            ms_df[ms_df["FreqDelta"] < max_magnetron_freq]["FreqDelta"],
1438            bins=magnetron_freq_bins,
1439        )
1440
1441        mod = GaussianModel()
1442        pars = mod.guess(freq_hist[0], x=freq_hist[1][:-1])
1443        out = mod.fit(freq_hist[0], pars, x=freq_hist[1][:-1])
1444        self.magnetron_frequency = out.best_values["center"]
1445        self.magnetron_frequency_sigma = out.best_values["sigma"]
1446
1447
1448class MassSpecCentroid(MassSpecBase):
1449    """A mass spectrum class when the entry point is on centroid format
1450
1451    Notes
1452    -----
1453    - Stores the centroid data and instrument settings
1454    - Simulate profile data based on Gaussian or Lorentzian peak shape
1455    - Iteration over a list of MSPeaks classes stored at the _mspeaks attributes
1456    - _mspeaks is populated under the hood by calling process_mass_spec method
1457    - iteration is null if _mspeaks is empty
1458
1459    Parameters
1460    ----------
1461    data_dict : dict {string: numpy array float64 )
1462        contains keys [m/z, Abundance, Resolving Power, S/N]
1463    d_params : dict{'str': float, int or str}
1464        contains the instrument settings and processing settings
1465    auto_process : bool, optional
1466        Whether to automatically process the mass spectrum. Defaults to True.
1467
1468    Attributes
1469    ----------
1470    label : str
1471        store label (Bruker, Midas Transient, see Labels class)
1472    _baseline_noise : float
1473        store baseline noise
1474    _baseline_noise_std : float
1475        store baseline noise std
1476    _abundance : ndarray
1477        The abundance values of the mass spectrum.
1478    _mz_exp : ndarray
1479        The m/z values of the mass spectrum.
1480    _mspeaks : list
1481        A list of mass peaks.
1482
1483
1484    Methods
1485    ----------
1486    * process_mass_spec().
1487        Process the mass spectrum. Overriden from MassSpecBase. Populates the _mspeaks list with MSpeaks class using the centroid data.
1488    * __simulate_profile__data__().
1489        Simulate profile data based on Gaussian or Lorentzian peak shape. Needs theoretical resolving power calculation and define peak shape, intended for plotting and inspection purposes only.
1490
1491    see also: MassSpecBase(), MassSpecfromFreq(), MassSpecProfile()
1492    """
1493
1494    def __init__(self, data_dict, d_params, auto_process=True):
1495        super().__init__([], [], d_params)
1496
1497        self._set_parameters_objects(d_params)
1498
1499        if self.label == Labels.thermo_centroid:
1500            self._baseline_noise = d_params.get("baseline_noise")
1501            self._baseline_noise_std = d_params.get("baseline_noise_std")
1502
1503        self.is_centroid = True
1504        self.data_dict = data_dict
1505        self._mz_exp = data_dict[Labels.mz]
1506        self._abundance = data_dict[Labels.abundance]
1507
1508        if auto_process:
1509            self.process_mass_spec()
1510
1511    def __simulate_profile__data__(self, exp_mz_centroid, magnitude_centroid):
1512        """Simulate profile data based on Gaussian or Lorentzian peak shape
1513
1514        Notes
1515        -----
1516        Needs theoretical resolving power calculation and define peak shape.
1517        This is a quick fix to trick a line plot be able to plot as sticks for plotting and inspection purposes only.
1518
1519        Parameters
1520        ----------
1521        exp_mz_centroid : list(float)
1522            list of m/z values
1523        magnitude_centroid : list(float)
1524            list of abundance values
1525
1526
1527        Returns
1528        -------
1529        x : list(float)
1530            list of m/z values
1531        y : list(float)
1532            list of abundance values
1533        """
1534
1535        x, y = [], []
1536        for i in range(len(exp_mz_centroid)):
1537            x.append(exp_mz_centroid[i] - 0.0000001)
1538            x.append(exp_mz_centroid[i])
1539            x.append(exp_mz_centroid[i] + 0.0000001)
1540            y.append(0)
1541            y.append(magnitude_centroid[i])
1542            y.append(0)
1543        return x, y
1544
1545    @property
1546    def mz_exp_profile(self):
1547        """Return the m/z profile of the mass spectrum."""
1548        mz_list = []
1549        for mz in self.mz_exp:
1550            mz_list.append(mz - 0.0000001)
1551            mz_list.append(mz)
1552            mz_list.append(mz + 0.0000001)
1553        return mz_list
1554
1555    @mz_exp_profile.setter
1556    def mz_exp_profile(self, _mz_exp):
1557        self._mz_exp = _mz_exp
1558
1559    @property
1560    def abundance_profile(self):
1561        """Return the abundance profile of the mass spectrum."""
1562        ab_list = []
1563        for ab in self.abundance:
1564            ab_list.append(0)
1565            ab_list.append(ab)
1566            ab_list.append(0)
1567        return ab_list
1568
1569    @abundance_profile.setter
1570    def abundance_profile(self, abundance):
1571        self._abundance = abundance
1572
1573    @property
1574    def tic(self):
1575        """Return the total ion current of the mass spectrum."""
1576        return sum(self.abundance)
1577
1578    def process_mass_spec(self):
1579        """Process the mass spectrum."""
1580        import tqdm
1581
1582        # overwrite process_mass_spec
1583        # mspeak objs are usually added inside the PeaKPicking class
1584        # for profile and freq based data
1585        data_dict = self.data_dict
1586        ion_charge = self.polarity
1587
1588        # Check if resolving power is present
1589        rp_present = True
1590        if not data_dict.get(Labels.rp):
1591            rp_present = False
1592        if rp_present and list(data_dict.get(Labels.rp)) == [None] * len(
1593            data_dict.get(Labels.rp)
1594        ):
1595            rp_present = False
1596
1597        # Check if s2n is present
1598        s2n_present = True
1599        if not data_dict.get(Labels.s2n):
1600            s2n_present = False
1601        if s2n_present and list(data_dict.get(Labels.s2n)) == [None] * len(
1602            data_dict.get(Labels.s2n)
1603        ):
1604            s2n_present = False
1605
1606        # Warning if no s2n data but noise thresholding is set to signal_noise
1607        if (
1608            not s2n_present
1609            and self.parameters.mass_spectrum.noise_threshold_method == "signal_noise"
1610        ):
1611            raise Exception("Signal to Noise data is missing for noise thresholding")
1612
1613        # Pull out abundance data
1614        abun = array(data_dict.get(Labels.abundance)).astype(float)
1615
1616        # Get the threshold for filtering if using minima, relative, or absolute abundance thresholding
1617        abundance_threshold, factor = self.get_threshold(abun)
1618
1619        # Set rp_i and s2n_i to None which will be overwritten if present
1620        rp_i, s2n_i = np.nan, np.nan
1621        for index, mz in enumerate(data_dict.get(Labels.mz)):
1622            if rp_present:
1623                if not data_dict.get(Labels.rp)[index]:
1624                    rp_i = np.nan
1625                else:
1626                    rp_i = float(data_dict.get(Labels.rp)[index])
1627            if s2n_present:
1628                if not data_dict.get(Labels.s2n)[index]:
1629                    s2n_i = np.nan
1630                else:
1631                    s2n_i = float(data_dict.get(Labels.s2n)[index])
1632
1633            # centroid peak does not have start and end peak index pos
1634            massspec_indexes = (index, index, index)
1635
1636            # Add peaks based on the noise thresholding method
1637            if (
1638                self.parameters.mass_spectrum.noise_threshold_method
1639                in ["minima", "relative_abundance", "absolute_abundance"]
1640                and abun[index] / factor >= abundance_threshold
1641            ):
1642                self.add_mspeak(
1643                    ion_charge,
1644                    mz,
1645                    abun[index],
1646                    rp_i,
1647                    s2n_i,
1648                    massspec_indexes,
1649                    ms_parent=self,
1650                )
1651            if (
1652                self.parameters.mass_spectrum.noise_threshold_method == "signal_noise"
1653                and s2n_i >= self.parameters.mass_spectrum.noise_threshold_min_s2n
1654            ):
1655                self.add_mspeak(
1656                    ion_charge,
1657                    mz,
1658                    abun[index],
1659                    rp_i,
1660                    s2n_i,
1661                    massspec_indexes,
1662                    ms_parent=self,
1663                )
1664
1665        self.mspeaks = self._mspeaks
1666        self._dynamic_range = self.max_abundance / self.min_abundance
1667        self._set_nominal_masses_start_final_indexes()
1668
1669        if self.label != Labels.thermo_centroid:
1670            if self.settings.noise_threshold_method == "log":
1671                raise Exception("log noise Not tested for centroid data")
1672                # self._baseline_noise, self._baseline_noise_std = self.run_log_noise_threshold_calc()
1673
1674            else:
1675                self._baseline_noise, self._baseline_noise_std = (
1676                    self.run_noise_threshold_calc()
1677                )
1678
1679        del self.data_dict
1680
1681
1682class MassSpecCentroidLowRes(MassSpecCentroid):
1683    """A mass spectrum class when the entry point is on low resolution centroid format
1684
1685    Notes
1686    -----
1687    Does not store MSPeak Objs, will iterate over mz, abundance pairs instead
1688
1689    Parameters
1690    ----------
1691    data_dict : dict {string: numpy array float64 )
1692        contains keys [m/z, Abundance, Resolving Power, S/N]
1693    d_params : dict{'str': float, int or str}
1694        contains the instrument settings and processing settings
1695
1696    Attributes
1697    ----------
1698    _processed_tic : float
1699        store processed total ion current
1700    _abundance : ndarray
1701        The abundance values of the mass spectrum.
1702    _mz_exp : ndarray
1703        The m/z values of the mass spectrum.
1704    """
1705
1706    def __init__(self, data_dict, d_params):
1707        self._set_parameters_objects(d_params)
1708        self._mz_exp = array(data_dict.get(Labels.mz))
1709        self._abundance = array(data_dict.get(Labels.abundance))
1710        self._processed_tic = None
1711
1712    def __len__(self):
1713        return len(self.mz_exp)
1714
1715    def __getitem__(self, position):
1716        return (self.mz_exp[position], self.abundance[position])
1717
1718    @property
1719    def mz_exp(self):
1720        """Return the m/z values of the mass spectrum."""
1721        return self._mz_exp
1722
1723    @property
1724    def abundance(self):
1725        """Return the abundance values of the mass spectrum."""
1726        return self._abundance
1727
1728    @property
1729    def processed_tic(self):
1730        """Return the processed total ion current of the mass spectrum."""
1731        return sum(self._processed_tic)
1732
1733    @property
1734    def tic(self):
1735        """Return the total ion current of the mass spectrum."""
1736        if self._processed_tic:
1737            return self._processed_tic
1738        else:
1739            return sum(self.abundance)
1740
1741    @property
1742    def mz_abun_tuples(self):
1743        """Return the m/z and abundance values of the mass spectrum as a list of tuples."""
1744        r = lambda x: (int(round(x[0], 0), int(round(x[1], 0))))
1745
1746        return [r(i) for i in self]
1747
1748    @property
1749    def mz_abun_dict(self):
1750        """Return the m/z and abundance values of the mass spectrum as a dictionary."""
1751        r = lambda x: int(round(x, 0))
1752
1753        return {r(i[0]): r(i[1]) for i in self}
def overrides(interface_class):
30def overrides(interface_class):
31    """Checks if the method overrides a method from an interface class."""
32
33    def overrider(method):
34        assert method.__name__ in dir(interface_class)
35        return method
36
37    return overrider

Checks if the method overrides a method from an interface class.

  40class MassSpecBase(MassSpecCalc, KendrickGrouping):
  41    """A mass spectrum base class, stores the profile data and instrument settings.
  42
  43    Iteration over a list of MSPeaks classes stored at the _mspeaks attributes.
  44    _mspeaks is populated under the hood by calling process_mass_spec method.
  45    Iteration is null if _mspeaks is empty.
  46
  47    Parameters
  48    ----------
  49    mz_exp : array_like
  50        The m/z values of the mass spectrum.
  51    abundance : array_like
  52        The abundance values of the mass spectrum.
  53    d_params : dict
  54        A dictionary of parameters for the mass spectrum.
  55    **kwargs
  56        Additional keyword arguments.
  57
  58    Attributes
  59    ----------
  60
  61    mspeaks : list
  62        A list of mass peaks.
  63    is_calibrated : bool
  64        Whether the mass spectrum is calibrated.
  65    is_centroid : bool
  66        Whether the mass spectrum is centroided.
  67    has_frequency : bool
  68        Whether the mass spectrum has a frequency domain.
  69    calibration_order : None or int
  70        The order of the mass spectrum's calibration.
  71    calibration_points : None or ndarray
  72        The calibration points of the mass spectrum.
  73    calibration_ref_mzs: None or ndarray
  74        The reference m/z values of the mass spectrum's calibration.
  75    calibration_meas_mzs : None or ndarray
  76        The measured m/z values of the mass spectrum's calibration.
  77    calibration_RMS : None or float
  78        The root mean square of the mass spectrum's calibration.
  79    calibration_segment : None or CalibrationSegment
  80        The calibration segment of the mass spectrum.
  81    _abundance : ndarray
  82        The abundance values of the mass spectrum.
  83    _mz_exp : ndarray
  84        The m/z values of the mass spectrum.
  85    _mspeaks : list
  86        A list of mass peaks.
  87    _dict_nominal_masses_indexes : dict
  88        A dictionary of nominal masses and their indexes.
  89    _baseline_noise : float
  90        The baseline noise of the mass spectrum.
  91    _baseline_noise_std : float
  92        The standard deviation of the baseline noise of the mass spectrum.
  93    _dynamic_range : float or None
  94        The dynamic range of the mass spectrum.
  95    _transient_settings : None or TransientSettings
  96        The transient settings of the mass spectrum.
  97    _frequency_domain : None or FrequencyDomain
  98        The frequency domain of the mass spectrum.
  99    _mz_cal_profile : None or MzCalibrationProfile
 100        The m/z calibration profile of the mass spectrum.
 101
 102    Methods
 103    -------
 104    * process_mass_spec(). Main function to process the mass spectrum,
 105    including calculating the noise threshold, peak picking, and resetting the MSpeak indexes.
 106
 107    See also: MassSpecCentroid(), MassSpecfromFreq(), MassSpecProfile()
 108    """
 109
 110    def __init__(self, mz_exp, abundance, d_params, **kwargs):
 111        self._abundance = array(abundance, dtype=float64)
 112        self._mz_exp = array(mz_exp, dtype=float64)
 113
 114        # objects created after process_mass_spec() function
 115        self._mspeaks = list()
 116        self.mspeaks = list()
 117        self._dict_nominal_masses_indexes = dict()
 118        self._baseline_noise = 0.001
 119        self._baseline_noise_std = 0.001
 120        self._dynamic_range = None
 121        # set to None: initialization occurs inside subclass MassSpecfromFreq
 122        self._transient_settings = None
 123        self._frequency_domain = None
 124        self._mz_cal_profile = None
 125        self.is_calibrated = False
 126
 127        self._set_parameters_objects(d_params)
 128        self._init_settings()
 129
 130        self.is_centroid = False
 131        self.has_frequency = False
 132
 133        self.calibration_order = None
 134        self.calibration_points = None
 135        self.calibration_ref_mzs = None
 136        self.calibration_meas_mzs = None
 137        self.calibration_RMS = None
 138        self.calibration_segment = None
 139        self.calibration_raw_error_median = None
 140        self.calibration_raw_error_stdev = None
 141
 142    def _init_settings(self):
 143        """Initializes the settings for the mass spectrum."""
 144        self._parameters = MSParameters()
 145
 146    def __len__(self):
 147        return len(self.mspeaks)
 148
 149    def __getitem__(self, position) -> MSPeak:
 150        return self.mspeaks[position]
 151
 152    def set_indexes(self, list_indexes):
 153        """Set the mass spectrum to iterate over only the selected MSpeaks indexes.
 154
 155        Parameters
 156        ----------
 157        list_indexes : list of int
 158            A list of integers representing the indexes of the MSpeaks to iterate over.
 159
 160        """
 161        self.mspeaks = [self._mspeaks[i] for i in list_indexes]
 162
 163        for i, mspeak in enumerate(self.mspeaks):
 164            mspeak.index = i
 165
 166        self._set_nominal_masses_start_final_indexes()
 167
 168    def reset_indexes(self):
 169        """Reset the mass spectrum to iterate over all MSpeaks objects.
 170
 171        This method resets the mass spectrum to its original state, allowing iteration over all MSpeaks objects.
 172        It also sets the index of each MSpeak object to its corresponding position in the mass spectrum.
 173
 174        """
 175        self.mspeaks = self._mspeaks
 176
 177        for i, mspeak in enumerate(self.mspeaks):
 178            mspeak.index = i
 179
 180        self._set_nominal_masses_start_final_indexes()
 181
 182    def add_mspeak(
 183        self,
 184        ion_charge,
 185        mz_exp,
 186        abundance,
 187        resolving_power,
 188        signal_to_noise,
 189        massspec_indexes,
 190        exp_freq=None,
 191        ms_parent=None,
 192    ):
 193        """Add a new MSPeak object to the MassSpectrum object.
 194
 195        Parameters
 196        ----------
 197        ion_charge : int
 198            The ion charge of the MSPeak.
 199        mz_exp : float
 200            The experimental m/z value of the MSPeak.
 201        abundance : float
 202            The abundance of the MSPeak.
 203        resolving_power : float
 204            The resolving power of the MSPeak.
 205        signal_to_noise : float
 206            The signal-to-noise ratio of the MSPeak.
 207        massspec_indexes : list
 208            A list of indexes of the MSPeak in the MassSpectrum object.
 209        exp_freq : float, optional
 210            The experimental frequency of the MSPeak. Defaults to None.
 211        ms_parent : MSParent, optional
 212            The MSParent object associated with the MSPeak. Defaults to None.
 213        """
 214        mspeak = MSPeak(
 215            ion_charge,
 216            mz_exp,
 217            abundance,
 218            resolving_power,
 219            signal_to_noise,
 220            massspec_indexes,
 221            len(self._mspeaks),
 222            exp_freq=exp_freq,
 223            ms_parent=ms_parent,
 224        )
 225
 226        self._mspeaks.append(mspeak)
 227
 228    def _set_parameters_objects(self, d_params):
 229        """Set the parameters of the MassSpectrum object.
 230
 231        Parameters
 232        ----------
 233        d_params : dict
 234            A dictionary containing the parameters to set.
 235
 236        Notes
 237        -----
 238        This method sets the following parameters of the MassSpectrum object:
 239        - _calibration_terms
 240        - label
 241        - analyzer
 242        - acquisition_time
 243        - instrument_label
 244        - polarity
 245        - scan_number
 246        - retention_time
 247        - mobility_rt
 248        - mobility_scan
 249        - _filename
 250        - _dir_location
 251        - _baseline_noise
 252        - _baseline_noise_std
 253        - sample_name
 254        """
 255        self._calibration_terms = (
 256            d_params.get("Aterm"),
 257            d_params.get("Bterm"),
 258            d_params.get("Cterm"),
 259        )
 260
 261        self.label = d_params.get(Labels.label)
 262
 263        self.analyzer = d_params.get("analyzer")
 264
 265        self.acquisition_time = d_params.get("acquisition_time")
 266
 267        self.instrument_label = d_params.get("instrument_label")
 268
 269        self.polarity = int(d_params.get("polarity"))
 270
 271        self.scan_number = d_params.get("scan_number")
 272
 273        self.retention_time = d_params.get("rt")
 274
 275        self.mobility_rt = d_params.get("mobility_rt")
 276
 277        self.mobility_scan = d_params.get("mobility_scan")
 278
 279        self._filename = d_params.get("filename_path")
 280
 281        self._dir_location = d_params.get("dir_location")
 282
 283        self._baseline_noise = d_params.get("baseline_noise")
 284
 285        self._baseline_noise_std = d_params.get("baseline_noise_std")
 286
 287        if d_params.get("sample_name") != "Unknown":
 288            self.sample_name = d_params.get("sample_name")
 289            if not self.sample_name:
 290                self.sample_name = self.filename.stem
 291        else:
 292            self.sample_name = self.filename.stem
 293
 294    def reset_cal_therms(self, Aterm, Bterm, C, fas=0):
 295        """Reset calibration terms and recalculate the mass-to-charge ratio and abundance.
 296
 297        Parameters
 298        ----------
 299        Aterm : float
 300            The A-term calibration coefficient.
 301        Bterm : float
 302            The B-term calibration coefficient.
 303        C : float
 304            The C-term calibration coefficient.
 305        fas : float, optional
 306            The frequency amplitude scaling factor. Default is 0.
 307        """
 308        self._calibration_terms = (Aterm, Bterm, C)
 309
 310        self._mz_exp = self._f_to_mz()
 311        self._abundance = self._abundance
 312        self.find_peaks()
 313        self.reset_indexes()
 314
 315    def clear_molecular_formulas(self):
 316        """Clear the molecular formulas for all mspeaks in the MassSpectrum.
 317
 318        Returns
 319        -------
 320        numpy.ndarray
 321            An array of the cleared molecular formulas for each mspeak in the MassSpectrum.
 322        """
 323        self.check_mspeaks()
 324        return array([mspeak.clear_molecular_formulas() for mspeak in self.mspeaks])
 325
 326    def process_mass_spec(self, keep_profile=True):
 327        """Process the mass spectrum.
 328
 329        Parameters
 330        ----------
 331        keep_profile : bool, optional
 332            Whether to keep the profile data after processing. Defaults to True.
 333
 334        Notes
 335        -----
 336        This method does the following:
 337        - calculates the noise threshold
 338        - does peak picking (creates mspeak_objs)
 339        - resets the mspeak_obj indexes
 340        """
 341
 342        # if runned mannually make sure to rerun filter_by_noise_threshold
 343        # calculates noise threshold
 344        # do peak picking( create mspeak_objs)
 345        # reset mspeak_obj the indexes
 346
 347        self.cal_noise_threshold()
 348
 349        self.find_peaks()
 350        self.reset_indexes()
 351
 352        if self.mspeaks:
 353            self._dynamic_range = self.max_abundance / self.min_abundance
 354        else:
 355            self._dynamic_range = 0
 356        if not keep_profile:
 357            self._abundance *= 0
 358            self._mz_exp *= 0
 359
 360    def cal_noise_threshold(self):
 361        """Calculate the noise threshold of the mass spectrum."""
 362
 363        if self.label == Labels.simulated_profile:
 364            self._baseline_noise, self._baseline_noise_std = 0.1, 1
 365
 366        if self.settings.noise_threshold_method == "log":
 367            self._baseline_noise, self._baseline_noise_std = (
 368                self.run_log_noise_threshold_calc()
 369            )
 370
 371        else:
 372            self._baseline_noise, self._baseline_noise_std = (
 373                self.run_noise_threshold_calc()
 374            )
 375
 376    @property
 377    def parameters(self):
 378        """Return the parameters of the mass spectrum."""
 379        return self._parameters
 380
 381    @parameters.setter
 382    def parameters(self, instance_MSParameters):
 383        self._parameters = instance_MSParameters
 384
 385    def set_parameter_from_json(self, parameters_path):
 386        """Set the parameters of the mass spectrum from a JSON file.
 387
 388        Parameters
 389        ----------
 390        parameters_path : str
 391            The path to the JSON file containing the parameters.
 392        """
 393        load_and_set_parameters_ms(self, parameters_path=parameters_path)
 394
 395    def set_parameter_from_toml(self, parameters_path):
 396        load_and_set_toml_parameters_ms(self, parameters_path=parameters_path)
 397
 398    @property
 399    def mspeaks_settings(self):
 400        """Return the MS peak settings of the mass spectrum."""
 401        return self.parameters.ms_peak
 402
 403    @mspeaks_settings.setter
 404    def mspeaks_settings(self, instance_MassSpecPeakSetting):
 405        self.parameters.ms_peak = instance_MassSpecPeakSetting
 406
 407    @property
 408    def settings(self):
 409        """Return the settings of the mass spectrum."""
 410        return self.parameters.mass_spectrum
 411
 412    @settings.setter
 413    def settings(self, instance_MassSpectrumSetting):
 414        self.parameters.mass_spectrum = instance_MassSpectrumSetting
 415
 416    @property
 417    def molecular_search_settings(self):
 418        """Return the molecular search settings of the mass spectrum."""
 419        return self.parameters.molecular_search
 420
 421    @molecular_search_settings.setter
 422    def molecular_search_settings(self, instance_MolecularFormulaSearchSettings):
 423        self.parameters.molecular_search = instance_MolecularFormulaSearchSettings
 424
 425    @property
 426    def mz_cal_profile(self):
 427        """Return the calibrated m/z profile of the mass spectrum."""
 428        return self._mz_cal_profile
 429
 430    @mz_cal_profile.setter
 431    def mz_cal_profile(self, mz_cal_list):
 432        if len(mz_cal_list) == len(self._mz_exp):
 433            self._mz_cal_profile = mz_cal_list
 434        else:
 435            raise Exception(
 436                "calibrated array (%i) is not of the same size of the data (%i)"
 437                % (len(mz_cal_list), len(self.mz_exp_profile))
 438            )
 439
 440    @property
 441    def mz_cal(self):
 442        """Return the calibrated m/z values of the mass spectrum."""
 443        return array([mspeak.mz_cal for mspeak in self.mspeaks])
 444
 445    @mz_cal.setter
 446    def mz_cal(self, mz_cal_list):
 447        if len(mz_cal_list) == len(self.mspeaks):
 448            self.is_calibrated = True
 449            for index, mz_cal in enumerate(mz_cal_list):
 450                self.mspeaks[index].mz_cal = mz_cal
 451        else:
 452            raise Exception(
 453                "calibrated array (%i) is not of the same size of the data (%i)"
 454                % (len(mz_cal_list), len(self._mspeaks))
 455            )
 456
 457    @property
 458    def mz_exp(self):
 459        """Return the experimental m/z values of the mass spectrum."""
 460        self.check_mspeaks()
 461
 462        if self.is_calibrated:
 463            return array([mspeak.mz_cal for mspeak in self.mspeaks])
 464
 465        else:
 466            return array([mspeak.mz_exp for mspeak in self.mspeaks])
 467
 468    @property
 469    def freq_exp_profile(self):
 470        """Return the experimental frequency profile of the mass spectrum."""
 471        return self._frequency_domain
 472
 473    @freq_exp_profile.setter
 474    def freq_exp_profile(self, new_data):
 475        self._frequency_domain = array(new_data)
 476
 477    @property
 478    def freq_exp_pp(self):
 479        """Return the experimental frequency values of the mass spectrum that are used for peak picking."""
 480        _, _, freq = self.prepare_peak_picking_data()
 481        return freq
 482
 483    @property
 484    def mz_exp_profile(self):
 485        """Return the experimental m/z profile of the mass spectrum."""
 486        if self.is_calibrated:
 487            return self.mz_cal_profile
 488        else:
 489            return self._mz_exp
 490
 491    @mz_exp_profile.setter
 492    def mz_exp_profile(self, new_data):
 493        self._mz_exp = array(new_data)
 494
 495    @property
 496    def mz_exp_pp(self):
 497        """Return the experimental m/z values of the mass spectrum that are used for peak picking."""
 498        mz, _, _ = self.prepare_peak_picking_data()
 499        return mz
 500
 501    @property
 502    def abundance_profile(self):
 503        """Return the abundance profile of the mass spectrum."""
 504        return self._abundance
 505
 506    @abundance_profile.setter
 507    def abundance_profile(self, new_data):
 508        self._abundance = array(new_data)
 509
 510    @property
 511    def abundance_profile_pp(self):
 512        """Return the abundance profile of the mass spectrum that is used for peak picking."""
 513        _, abundance, _ = self.prepare_peak_picking_data()
 514        return abundance
 515
 516    @property
 517    def abundance(self):
 518        """Return the abundance values of the mass spectrum."""
 519        self.check_mspeaks()
 520        return array([mspeak.abundance for mspeak in self.mspeaks])
 521
 522    def freq_exp(self):
 523        """Return the experimental frequency values of the mass spectrum."""
 524        self.check_mspeaks()
 525        return array([mspeak.freq_exp for mspeak in self.mspeaks])
 526
 527    @property
 528    def resolving_power(self):
 529        """Return the resolving power values of the mass spectrum."""
 530        self.check_mspeaks()
 531        return array([mspeak.resolving_power for mspeak in self.mspeaks])
 532
 533    @property
 534    def signal_to_noise(self):
 535        self.check_mspeaks()
 536        return array([mspeak.signal_to_noise for mspeak in self.mspeaks])
 537
 538    @property
 539    def nominal_mz(self):
 540        """Return the nominal m/z values of the mass spectrum."""
 541        if self._dict_nominal_masses_indexes:
 542            return sorted(list(self._dict_nominal_masses_indexes.keys()))
 543        else:
 544            raise ValueError("Nominal indexes not yet set")
 545
 546    def get_mz_and_abundance_peaks_tuples(self):
 547        """Return a list of tuples containing the m/z and abundance values of the mass spectrum."""
 548        self.check_mspeaks()
 549        return [(mspeak.mz_exp, mspeak.abundance) for mspeak in self.mspeaks]
 550
 551    @property
 552    def kmd(self):
 553        """Return the Kendrick mass defect values of the mass spectrum."""
 554        self.check_mspeaks()
 555        return array([mspeak.kmd for mspeak in self.mspeaks])
 556
 557    @property
 558    def kendrick_mass(self):
 559        """Return the Kendrick mass values of the mass spectrum."""
 560        self.check_mspeaks()
 561        return array([mspeak.kendrick_mass for mspeak in self.mspeaks])
 562
 563    @property
 564    def max_mz_exp(self):
 565        """Return the maximum experimental m/z value of the mass spectrum."""
 566        return max([mspeak.mz_exp for mspeak in self.mspeaks])
 567
 568    @property
 569    def min_mz_exp(self):
 570        """Return the minimum experimental m/z value of the mass spectrum."""
 571        return min([mspeak.mz_exp for mspeak in self.mspeaks])
 572
 573    @property
 574    def max_abundance(self):
 575        """Return the maximum abundance value of the mass spectrum."""
 576        return max([mspeak.abundance for mspeak in self.mspeaks])
 577
 578    @property
 579    def max_signal_to_noise(self):
 580        """Return the maximum signal-to-noise ratio of the mass spectrum."""
 581        return max([mspeak.signal_to_noise for mspeak in self.mspeaks])
 582
 583    @property
 584    def most_abundant_mspeak(self):
 585        """Return the most abundant MSpeak object of the mass spectrum."""
 586        return max(self.mspeaks, key=lambda m: m.abundance)
 587
 588    @property
 589    def min_abundance(self):
 590        """Return the minimum abundance value of the mass spectrum."""
 591        return min([mspeak.abundance for mspeak in self.mspeaks])
 592
 593    # takes too much cpu time
 594    @property
 595    def dynamic_range(self):
 596        """Return the dynamic range of the mass spectrum."""
 597        return self._dynamic_range
 598
 599    @property
 600    def baseline_noise(self):
 601        """Return the baseline noise of the mass spectrum."""
 602        if self._baseline_noise:
 603            return self._baseline_noise
 604        else:
 605            return None
 606
 607    @property
 608    def baseline_noise_std(self):
 609        """Return the standard deviation of the baseline noise of the mass spectrum."""
 610        if self._baseline_noise_std == 0:
 611            return self._baseline_noise_std
 612        if self._baseline_noise_std:
 613            return self._baseline_noise_std
 614        else:
 615            return None
 616
 617    @property
 618    def Aterm(self):
 619        """Return the A-term calibration coefficient of the mass spectrum."""
 620        return self._calibration_terms[0]
 621
 622    @property
 623    def Bterm(self):
 624        """Return the B-term calibration coefficient of the mass spectrum."""
 625        return self._calibration_terms[1]
 626
 627    @property
 628    def Cterm(self):
 629        """Return the C-term calibration coefficient of the mass spectrum."""
 630        return self._calibration_terms[2]
 631
 632    @property
 633    def filename(self):
 634        """Return the filename of the mass spectrum."""
 635        return Path(self._filename)
 636
 637    @property
 638    def dir_location(self):
 639        """Return the directory location of the mass spectrum."""
 640        return self._dir_location
 641
 642    def sort_by_mz(self):
 643        """Sort the mass spectrum by m/z values."""
 644        return sorted(self, key=lambda m: m.mz_exp)
 645
 646    def sort_by_abundance(self, reverse=False):
 647        """Sort the mass spectrum by abundance values."""
 648        return sorted(self, key=lambda m: m.abundance, reverse=reverse)
 649
 650    @property
 651    def tic(self):
 652        """Return the total ion current of the mass spectrum."""
 653        return trapezoid(self.abundance_profile, self.mz_exp_profile)
 654
 655    def check_mspeaks_warning(self):
 656        """Check if the mass spectrum has MSpeaks objects.
 657
 658        Raises
 659        ------
 660        Warning
 661            If the mass spectrum has no MSpeaks objects.
 662        """
 663        import warnings
 664
 665        if self.mspeaks:
 666            pass
 667        else:
 668            warnings.warn("mspeaks list is empty, continuing without filtering data")
 669
 670    def check_mspeaks(self):
 671        """Check if the mass spectrum has MSpeaks objects.
 672
 673        Raises
 674        ------
 675        Exception
 676            If the mass spectrum has no MSpeaks objects.
 677        """
 678        if self.mspeaks:
 679            pass
 680        else:
 681            raise Exception(
 682                "mspeaks list is empty, please run process_mass_spec() first"
 683            )
 684
 685    def remove_assignment_by_index(self, indexes):
 686        """Remove the molecular formula assignment of the MSpeaks objects at the specified indexes.
 687
 688        Parameters
 689        ----------
 690        indexes : list of int
 691            A list of indexes of the MSpeaks objects to remove the molecular formula assignment from.
 692        """
 693        for i in indexes:
 694            self.mspeaks[i].clear_molecular_formulas()
 695
 696    def filter_by_index(self, list_indexes):
 697        """Filter the mass spectrum by the specified indexes.
 698
 699        Parameters
 700        ----------
 701        list_indexes : list of int
 702            A list of indexes of the MSpeaks objects to drop.
 703
 704        """
 705
 706        self.mspeaks = [
 707            self.mspeaks[i] for i in range(len(self.mspeaks)) if i not in list_indexes
 708        ]
 709
 710        for i, mspeak in enumerate(self.mspeaks):
 711            mspeak.index = i
 712
 713        self._set_nominal_masses_start_final_indexes()
 714
 715    def filter_by_mz(self, min_mz, max_mz):
 716        """Filter the mass spectrum by the specified m/z range.
 717
 718        Parameters
 719        ----------
 720        min_mz : float
 721            The minimum m/z value to keep.
 722        max_mz : float
 723            The maximum m/z value to keep.
 724
 725        """
 726        self.check_mspeaks_warning()
 727        indexes = [
 728            index
 729            for index, mspeak in enumerate(self.mspeaks)
 730            if not min_mz <= mspeak.mz_exp <= max_mz
 731        ]
 732        self.filter_by_index(indexes)
 733
 734    def filter_by_s2n(self, min_s2n, max_s2n=False):
 735        """Filter the mass spectrum by the specified signal-to-noise ratio range.
 736
 737        Parameters
 738        ----------
 739        min_s2n : float
 740            The minimum signal-to-noise ratio to keep.
 741        max_s2n : float, optional
 742            The maximum signal-to-noise ratio to keep. Defaults to False (no maximum).
 743
 744        """
 745        self.check_mspeaks_warning()
 746        if max_s2n:
 747            indexes = [
 748                index
 749                for index, mspeak in enumerate(self.mspeaks)
 750                if not min_s2n <= mspeak.signal_to_noise <= max_s2n
 751            ]
 752        else:
 753            indexes = [
 754                index
 755                for index, mspeak in enumerate(self.mspeaks)
 756                if mspeak.signal_to_noise <= min_s2n
 757            ]
 758        self.filter_by_index(indexes)
 759
 760    def filter_by_abundance(self, min_abund, max_abund=False):
 761        """Filter the mass spectrum by the specified abundance range.
 762
 763        Parameters
 764        ----------
 765        min_abund : float
 766            The minimum abundance to keep.
 767        max_abund : float, optional
 768            The maximum abundance to keep. Defaults to False (no maximum).
 769
 770        """
 771        self.check_mspeaks_warning()
 772        if max_abund:
 773            indexes = [
 774                index
 775                for index, mspeak in enumerate(self.mspeaks)
 776                if not min_abund <= mspeak.abundance <= max_abund
 777            ]
 778        else:
 779            indexes = [
 780                index
 781                for index, mspeak in enumerate(self.mspeaks)
 782                if mspeak.abundance <= min_abund
 783            ]
 784        self.filter_by_index(indexes)
 785
 786    def filter_by_max_resolving_power(self, B, T):
 787        """Filter the mass spectrum by the specified maximum resolving power.
 788
 789        Parameters
 790        ----------
 791        B : float
 792        T : float
 793
 794        """
 795
 796        rpe = lambda m, z: (1.274e7 * z * B * T) / (m * z)
 797
 798        self.check_mspeaks_warning()
 799
 800        indexes_to_remove = [
 801            index
 802            for index, mspeak in enumerate(self.mspeaks)
 803            if mspeak.resolving_power >= rpe(mspeak.mz_exp, mspeak.ion_charge)
 804        ]
 805        self.filter_by_index(indexes_to_remove)
 806
 807    def filter_by_mean_resolving_power(
 808        self, ndeviations=3, plot=False, guess_pars=False
 809    ):
 810        """Filter the mass spectrum by the specified mean resolving power.
 811
 812        Parameters
 813        ----------
 814        ndeviations : float, optional
 815            The number of standard deviations to use for filtering. Defaults to 3.
 816        plot : bool, optional
 817            Whether to plot the resolving power distribution. Defaults to False.
 818        guess_pars : bool, optional
 819            Whether to guess the parameters for the Gaussian model. Defaults to False.
 820
 821        """
 822        self.check_mspeaks_warning()
 823        indexes_to_remove = MeanResolvingPowerFilter(
 824            self, ndeviations, plot, guess_pars
 825        ).main()
 826        self.filter_by_index(indexes_to_remove)
 827
 828    def filter_by_min_resolving_power(self, B, T, apodization_method: str=None, tolerance: float=0):
 829        """Filter the mass spectrum by the calculated minimum theoretical resolving power.
 830
 831        This is currently designed only for FTICR data, and accounts only for magnitude mode data
 832        Accurate results require passing the apodisaion method used to calculate the resolving power.
 833        see the ICRMassPeak function `resolving_power_calc` for more details.
 834
 835        Parameters
 836        ----------
 837        B : Magnetic field strength in Tesla, float
 838        T : transient length in seconds, float
 839        apodization_method : str, optional
 840            The apodization method to use for calculating the resolving power. Defaults to None.
 841        tolerance : float, optional
 842            The tolerance for the threshold. Defaults to 0, i.e. no tolerance
 843
 844        """
 845        if self.analyzer != "ICR":
 846            raise Exception(
 847                "This method is only applicable to ICR mass spectra. "
 848            )
 849
 850        self.check_mspeaks_warning()
 851
 852        indexes_to_remove = [
 853            index
 854            for index, mspeak in enumerate(self.mspeaks)
 855            if mspeak.resolving_power < (1-tolerance) * mspeak.resolving_power_calc(B, T, apodization_method=apodization_method)
 856        ]
 857        self.filter_by_index(indexes_to_remove)
 858
 859    def filter_by_noise_threshold(self):
 860        """Filter the mass spectrum by the noise threshold."""
 861
 862        threshold = self.get_noise_threshold()[1][0]
 863
 864        self.check_mspeaks_warning()
 865
 866        indexes_to_remove = [
 867            index
 868            for index, mspeak in enumerate(self.mspeaks)
 869            if mspeak.abundance <= threshold
 870        ]
 871        self.filter_by_index(indexes_to_remove)
 872
 873    def find_peaks(self):
 874        """Find the peaks of the mass spectrum."""
 875        # needs to clear previous results from peak_picking
 876        self._mspeaks = list()
 877
 878        # then do peak picking
 879        self.do_peak_picking()
 880        # print("A total of %i peaks were found" % len(self._mspeaks))
 881
 882    def change_kendrick_base_all_mspeaks(self, kendrick_dict_base):
 883        """Change the Kendrick base of all MSpeaks objects.
 884
 885        Parameters
 886        ----------
 887        kendrick_dict_base : dict
 888            A dictionary of the Kendrick base to change to.
 889
 890        Notes
 891        -----
 892        Example of kendrick_dict_base parameter: kendrick_dict_base = {"C": 1, "H": 2} or {"C": 1, "H": 1, "O":1} etc
 893        """
 894        self.parameters.ms_peak.kendrick_base = kendrick_dict_base
 895
 896        for mspeak in self.mspeaks:
 897            mspeak.change_kendrick_base(kendrick_dict_base)
 898
 899    def get_nominal_mz_first_last_indexes(self, nominal_mass):
 900        """Return the first and last indexes of the MSpeaks objects with the specified nominal mass.
 901
 902        Parameters
 903        ----------
 904        nominal_mass : int
 905            The nominal mass to get the indexes for.
 906
 907        Returns
 908        -------
 909        tuple
 910            A tuple containing the first and last indexes of the MSpeaks objects with the specified nominal mass.
 911        """
 912        if self._dict_nominal_masses_indexes:
 913            if nominal_mass in self._dict_nominal_masses_indexes.keys():
 914                return (
 915                    self._dict_nominal_masses_indexes.get(nominal_mass)[0],
 916                    self._dict_nominal_masses_indexes.get(nominal_mass)[1] + 1,
 917                )
 918
 919            else:
 920                # import warnings
 921                # uncomment warn to distribution
 922                # warnings.warn("Nominal mass not found in _dict_nominal_masses_indexes, returning (0, 0) for nominal mass %i"%nominal_mass)
 923                return (0, 0)
 924        else:
 925            raise Exception(
 926                "run process_mass_spec() function before trying to access the data"
 927            )
 928
 929    def get_masses_count_by_nominal_mass(self):
 930        """Return a dictionary of the nominal masses and their counts."""
 931
 932        dict_nominal_masses_count = {}
 933
 934        all_nominal_masses = list(set([i.nominal_mz_exp for i in self.mspeaks]))
 935
 936        for nominal_mass in all_nominal_masses:
 937            if nominal_mass not in dict_nominal_masses_count:
 938                dict_nominal_masses_count[nominal_mass] = len(
 939                    list(self.get_nominal_mass_indexes(nominal_mass))
 940                )
 941
 942        return dict_nominal_masses_count
 943
 944    def datapoints_count_by_nominal_mz(self, mz_overlay=0.1):
 945        """Return a dictionary of the nominal masses and their counts.
 946
 947        Parameters
 948        ----------
 949        mz_overlay : float, optional
 950            The m/z overlay to use for counting. Defaults to 0.1.
 951
 952        Returns
 953        -------
 954        dict
 955            A dictionary of the nominal masses and their counts.
 956        """
 957        dict_nominal_masses_count = {}
 958
 959        all_nominal_masses = list(set([i.nominal_mz_exp for i in self.mspeaks]))
 960
 961        for nominal_mass in all_nominal_masses:
 962            if nominal_mass not in dict_nominal_masses_count:
 963                min_mz = nominal_mass - mz_overlay
 964
 965                max_mz = nominal_mass + 1 + mz_overlay
 966
 967                indexes = indexes = where(
 968                    (self.mz_exp_profile > min_mz) & (self.mz_exp_profile < max_mz)
 969                )
 970
 971                dict_nominal_masses_count[nominal_mass] = indexes[0].size
 972
 973        return dict_nominal_masses_count
 974
 975    def get_nominal_mass_indexes(self, nominal_mass, overlay=0.1):
 976        """Return the indexes of the MSpeaks objects with the specified nominal mass.
 977
 978        Parameters
 979        ----------
 980        nominal_mass : int
 981            The nominal mass to get the indexes for.
 982        overlay : float, optional
 983            The m/z overlay to use for counting. Defaults to 0.1.
 984
 985        Returns
 986        -------
 987        generator
 988            A generator of the indexes of the MSpeaks objects with the specified nominal mass.
 989        """
 990        min_mz_to_look = nominal_mass - overlay
 991        max_mz_to_look = nominal_mass + 1 + overlay
 992
 993        return (
 994            i
 995            for i in range(len(self.mspeaks))
 996            if min_mz_to_look <= self.mspeaks[i].mz_exp <= max_mz_to_look
 997        )
 998
 999        # indexes = (i for i in range(len(self.mspeaks)) if min_mz_to_look <= self.mspeaks[i].mz_exp <= max_mz_to_look)
1000        # return indexes
1001
1002    def _set_nominal_masses_start_final_indexes(self):
1003        """Set the start and final indexes of the MSpeaks objects for all nominal masses."""
1004        dict_nominal_masses_indexes = {}
1005
1006        all_nominal_masses = set(i.nominal_mz_exp for i in self.mspeaks)
1007
1008        for nominal_mass in all_nominal_masses:
1009            # indexes = self.get_nominal_mass_indexes(nominal_mass)
1010            # Convert the iterator to a list to avoid multiple calls
1011            indexes = list(self.get_nominal_mass_indexes(nominal_mass))
1012
1013            # If the list is not empty, find the first and last; otherwise, set None
1014            if indexes:
1015                first, last = indexes[0], indexes[-1]
1016            else:
1017                first = last = None
1018            # defaultvalue = None
1019            # first = last = next(indexes, defaultvalue)
1020            # for last in indexes:
1021            #    pass
1022
1023            dict_nominal_masses_indexes[nominal_mass] = (first, last)
1024
1025        self._dict_nominal_masses_indexes = dict_nominal_masses_indexes
1026
1027    def plot_centroid(self, ax=None, c="g"):
1028        """Plot the centroid data of the mass spectrum.
1029
1030        Parameters
1031        ----------
1032        ax : matplotlib.axes.Axes, optional
1033            The matplotlib axes to plot on. Defaults to None.
1034        c : str, optional
1035            The color to use for the plot. Defaults to 'g' (green).
1036
1037        Returns
1038        -------
1039        matplotlib.axes.Axes
1040            The matplotlib axes containing the plot.
1041
1042        Raises
1043        ------
1044        Exception
1045            If no centroid data is found.
1046        """
1047
1048        import matplotlib.pyplot as plt
1049
1050        if self._mspeaks:
1051            if ax is None:
1052                ax = plt.gca()
1053
1054            markerline_a, stemlines_a, baseline_a = ax.stem(
1055                self.mz_exp, self.abundance, linefmt="-", markerfmt=" "
1056            )
1057
1058            plt.setp(markerline_a, "color", c, "linewidth", 2)
1059            plt.setp(stemlines_a, "color", c, "linewidth", 2)
1060            plt.setp(baseline_a, "color", c, "linewidth", 2)
1061
1062            ax.set_xlabel("$\t{m/z}$", fontsize=12)
1063            ax.set_ylabel("Abundance", fontsize=12)
1064            ax.tick_params(axis="both", which="major", labelsize=12)
1065
1066            ax.axes.spines["top"].set_visible(False)
1067            ax.axes.spines["right"].set_visible(False)
1068
1069            ax.get_yaxis().set_visible(False)
1070            ax.spines["left"].set_visible(False)
1071
1072        else:
1073            raise Exception("No centroid data found, please run process_mass_spec")
1074
1075        return ax
1076
1077    def plot_profile_and_noise_threshold(self, ax=None, legend=False):
1078        """Plot the profile data and noise threshold of the mass spectrum.
1079
1080        Parameters
1081        ----------
1082        ax : matplotlib.axes.Axes, optional
1083            The matplotlib axes to plot on. Defaults to None.
1084        legend : bool, optional
1085            Whether to show the legend. Defaults to False.
1086
1087        Returns
1088        -------
1089        matplotlib.axes.Axes
1090            The matplotlib axes containing the plot.
1091
1092        Raises
1093        ------
1094        Exception
1095            If no noise threshold is found.
1096        """
1097        import matplotlib.pyplot as plt
1098
1099        if self.baseline_noise_std and self.baseline_noise_std:
1100            # x = (self.mz_exp_profile.min(), self.mz_exp_profile.max())
1101            baseline = (self.baseline_noise, self.baseline_noise)
1102
1103            # std = self.parameters.mass_spectrum.noise_threshold_min_std
1104            # threshold = self.baseline_noise_std + (std * self.baseline_noise_std)
1105            x, y = self.get_noise_threshold()
1106
1107            if ax is None:
1108                ax = plt.gca()
1109
1110            ax.plot(
1111                self.mz_exp_profile,
1112                self.abundance_profile,
1113                color="green",
1114                label="Spectrum",
1115            )
1116            ax.plot(x, (baseline, baseline), color="yellow", label="Baseline Noise")
1117            ax.plot(x, y, color="red", label="Noise Threshold")
1118
1119            ax.set_xlabel("$\t{m/z}$", fontsize=12)
1120            ax.set_ylabel("Abundance", fontsize=12)
1121            ax.tick_params(axis="both", which="major", labelsize=12)
1122
1123            ax.axes.spines["top"].set_visible(False)
1124            ax.axes.spines["right"].set_visible(False)
1125
1126            ax.get_yaxis().set_visible(False)
1127            ax.spines["left"].set_visible(False)
1128            if legend:
1129                ax.legend()
1130
1131        else:
1132            raise Exception("Calculate noise threshold first")
1133
1134        return ax
1135
1136    def plot_mz_domain_profile(self, color="green", ax=None):
1137        """Plot the m/z domain profile of the mass spectrum.
1138
1139        Parameters
1140        ----------
1141        color : str, optional
1142            The color to use for the plot. Defaults to 'green'.
1143        ax : matplotlib.axes.Axes, optional
1144            The matplotlib axes to plot on. Defaults to None.
1145
1146        Returns
1147        -------
1148        matplotlib.axes.Axes
1149            The matplotlib axes containing the plot.
1150        """
1151
1152        import matplotlib.pyplot as plt
1153
1154        if ax is None:
1155            ax = plt.gca()
1156        ax.plot(self.mz_exp_profile, self.abundance_profile, color=color)
1157        ax.set(xlabel="m/z", ylabel="abundance")
1158
1159        return ax
1160
1161    def to_excel(self, out_file_path, write_metadata=True):
1162        """Export the mass spectrum to an Excel file.
1163
1164        Parameters
1165        ----------
1166        out_file_path : str
1167            The path to the Excel file to export to.
1168        write_metadata : bool, optional
1169            Whether to write the metadata to the Excel file. Defaults to True.
1170
1171        Returns
1172        -------
1173        None
1174        """
1175        from corems.mass_spectrum.output.export import HighResMassSpecExport
1176
1177        exportMS = HighResMassSpecExport(out_file_path, self)
1178        exportMS.to_excel(write_metadata=write_metadata)
1179
1180    def to_hdf(self, out_file_path):
1181        """Export the mass spectrum to an HDF file.
1182
1183        Parameters
1184        ----------
1185        out_file_path : str
1186            The path to the HDF file to export to.
1187
1188        Returns
1189        -------
1190        None
1191        """
1192        from corems.mass_spectrum.output.export import HighResMassSpecExport
1193
1194        exportMS = HighResMassSpecExport(out_file_path, self)
1195        exportMS.to_hdf()
1196
1197    def to_csv(self, out_file_path, write_metadata=True):
1198        """Export the mass spectrum to a CSV file.
1199
1200        Parameters
1201        ----------
1202        out_file_path : str
1203            The path to the CSV file to export to.
1204        write_metadata : bool, optional
1205            Whether to write the metadata to the CSV file. Defaults to True.
1206
1207        """
1208        from corems.mass_spectrum.output.export import HighResMassSpecExport
1209
1210        exportMS = HighResMassSpecExport(out_file_path, self)
1211        exportMS.to_csv(write_metadata=write_metadata)
1212
1213    def to_pandas(self, out_file_path, write_metadata=True):
1214        """Export the mass spectrum to a Pandas dataframe with pkl extension.
1215
1216        Parameters
1217        ----------
1218        out_file_path : str
1219            The path to the CSV file to export to.
1220        write_metadata : bool, optional
1221            Whether to write the metadata to the CSV file. Defaults to True.
1222
1223        """
1224        from corems.mass_spectrum.output.export import HighResMassSpecExport
1225
1226        exportMS = HighResMassSpecExport(out_file_path, self)
1227        exportMS.to_pandas(write_metadata=write_metadata)
1228
1229    def to_dataframe(self, additional_columns=None):
1230        """Return the mass spectrum as a Pandas dataframe.
1231
1232        Parameters
1233        ----------
1234        additional_columns : list, optional
1235            A list of additional columns to include in the dataframe. Defaults to None.
1236            Suitable columns are: "Aromaticity Index", "Aromaticity Index (modified)", and "NOSC"
1237
1238        Returns
1239        -------
1240        pandas.DataFrame
1241            The mass spectrum as a Pandas dataframe.
1242        """
1243        from corems.mass_spectrum.output.export import HighResMassSpecExport
1244
1245        exportMS = HighResMassSpecExport(self.filename, self)
1246        return exportMS.get_pandas_df(additional_columns=additional_columns)
1247
1248    def to_json(self):
1249        """Return the mass spectrum as a JSON file."""
1250        from corems.mass_spectrum.output.export import HighResMassSpecExport
1251
1252        exportMS = HighResMassSpecExport(self.filename, self)
1253        return exportMS.to_json()
1254
1255    def parameters_json(self):
1256        """Return the parameters of the mass spectrum as a JSON string."""
1257        from corems.mass_spectrum.output.export import HighResMassSpecExport
1258
1259        exportMS = HighResMassSpecExport(self.filename, self)
1260        return exportMS.parameters_to_json()
1261
1262    def parameters_toml(self):
1263        """Return the parameters of the mass spectrum as a TOML string."""
1264        from corems.mass_spectrum.output.export import HighResMassSpecExport
1265
1266        exportMS = HighResMassSpecExport(self.filename, self)
1267        return exportMS.parameters_to_toml()

A mass spectrum base class, stores the profile data and instrument settings.

Iteration over a list of MSPeaks classes stored at the _mspeaks attributes. _mspeaks is populated under the hood by calling process_mass_spec method. Iteration is null if _mspeaks is empty.

Parameters
  • mz_exp (array_like): The m/z values of the mass spectrum.
  • abundance (array_like): The abundance values of the mass spectrum.
  • d_params (dict): A dictionary of parameters for the mass spectrum.
  • **kwargs: Additional keyword arguments.
Attributes
  • mspeaks (list): A list of mass peaks.
  • is_calibrated (bool): Whether the mass spectrum is calibrated.
  • is_centroid (bool): Whether the mass spectrum is centroided.
  • has_frequency (bool): Whether the mass spectrum has a frequency domain.
  • calibration_order (None or int): The order of the mass spectrum's calibration.
  • calibration_points (None or ndarray): The calibration points of the mass spectrum.
  • calibration_ref_mzs (None or ndarray): The reference m/z values of the mass spectrum's calibration.
  • calibration_meas_mzs (None or ndarray): The measured m/z values of the mass spectrum's calibration.
  • calibration_RMS (None or float): The root mean square of the mass spectrum's calibration.
  • calibration_segment (None or CalibrationSegment): The calibration segment of the mass spectrum.
  • _abundance (ndarray): The abundance values of the mass spectrum.
  • _mz_exp (ndarray): The m/z values of the mass spectrum.
  • _mspeaks (list): A list of mass peaks.
  • _dict_nominal_masses_indexes (dict): A dictionary of nominal masses and their indexes.
  • _baseline_noise (float): The baseline noise of the mass spectrum.
  • _baseline_noise_std (float): The standard deviation of the baseline noise of the mass spectrum.
  • _dynamic_range (float or None): The dynamic range of the mass spectrum.
  • _transient_settings (None or TransientSettings): The transient settings of the mass spectrum.
  • _frequency_domain (None or FrequencyDomain): The frequency domain of the mass spectrum.
  • _mz_cal_profile (None or MzCalibrationProfile): The m/z calibration profile of the mass spectrum.
Methods
  • process_mass_spec(). Main function to process the mass spectrum, including calculating the noise threshold, peak picking, and resetting the MSpeak indexes.

See also: MassSpecCentroid(), MassSpecfromFreq(), MassSpecProfile()

MassSpecBase(mz_exp, abundance, d_params, **kwargs)
110    def __init__(self, mz_exp, abundance, d_params, **kwargs):
111        self._abundance = array(abundance, dtype=float64)
112        self._mz_exp = array(mz_exp, dtype=float64)
113
114        # objects created after process_mass_spec() function
115        self._mspeaks = list()
116        self.mspeaks = list()
117        self._dict_nominal_masses_indexes = dict()
118        self._baseline_noise = 0.001
119        self._baseline_noise_std = 0.001
120        self._dynamic_range = None
121        # set to None: initialization occurs inside subclass MassSpecfromFreq
122        self._transient_settings = None
123        self._frequency_domain = None
124        self._mz_cal_profile = None
125        self.is_calibrated = False
126
127        self._set_parameters_objects(d_params)
128        self._init_settings()
129
130        self.is_centroid = False
131        self.has_frequency = False
132
133        self.calibration_order = None
134        self.calibration_points = None
135        self.calibration_ref_mzs = None
136        self.calibration_meas_mzs = None
137        self.calibration_RMS = None
138        self.calibration_segment = None
139        self.calibration_raw_error_median = None
140        self.calibration_raw_error_stdev = None
mspeaks
is_calibrated
is_centroid
has_frequency
calibration_order
calibration_points
calibration_ref_mzs
calibration_meas_mzs
calibration_RMS
calibration_segment
calibration_raw_error_median
calibration_raw_error_stdev
def set_indexes(self, list_indexes):
152    def set_indexes(self, list_indexes):
153        """Set the mass spectrum to iterate over only the selected MSpeaks indexes.
154
155        Parameters
156        ----------
157        list_indexes : list of int
158            A list of integers representing the indexes of the MSpeaks to iterate over.
159
160        """
161        self.mspeaks = [self._mspeaks[i] for i in list_indexes]
162
163        for i, mspeak in enumerate(self.mspeaks):
164            mspeak.index = i
165
166        self._set_nominal_masses_start_final_indexes()

Set the mass spectrum to iterate over only the selected MSpeaks indexes.

Parameters
  • list_indexes (list of int): A list of integers representing the indexes of the MSpeaks to iterate over.
def reset_indexes(self):
168    def reset_indexes(self):
169        """Reset the mass spectrum to iterate over all MSpeaks objects.
170
171        This method resets the mass spectrum to its original state, allowing iteration over all MSpeaks objects.
172        It also sets the index of each MSpeak object to its corresponding position in the mass spectrum.
173
174        """
175        self.mspeaks = self._mspeaks
176
177        for i, mspeak in enumerate(self.mspeaks):
178            mspeak.index = i
179
180        self._set_nominal_masses_start_final_indexes()

Reset the mass spectrum to iterate over all MSpeaks objects.

This method resets the mass spectrum to its original state, allowing iteration over all MSpeaks objects. It also sets the index of each MSpeak object to its corresponding position in the mass spectrum.

def add_mspeak( self, ion_charge, mz_exp, abundance, resolving_power, signal_to_noise, massspec_indexes, exp_freq=None, ms_parent=None):
182    def add_mspeak(
183        self,
184        ion_charge,
185        mz_exp,
186        abundance,
187        resolving_power,
188        signal_to_noise,
189        massspec_indexes,
190        exp_freq=None,
191        ms_parent=None,
192    ):
193        """Add a new MSPeak object to the MassSpectrum object.
194
195        Parameters
196        ----------
197        ion_charge : int
198            The ion charge of the MSPeak.
199        mz_exp : float
200            The experimental m/z value of the MSPeak.
201        abundance : float
202            The abundance of the MSPeak.
203        resolving_power : float
204            The resolving power of the MSPeak.
205        signal_to_noise : float
206            The signal-to-noise ratio of the MSPeak.
207        massspec_indexes : list
208            A list of indexes of the MSPeak in the MassSpectrum object.
209        exp_freq : float, optional
210            The experimental frequency of the MSPeak. Defaults to None.
211        ms_parent : MSParent, optional
212            The MSParent object associated with the MSPeak. Defaults to None.
213        """
214        mspeak = MSPeak(
215            ion_charge,
216            mz_exp,
217            abundance,
218            resolving_power,
219            signal_to_noise,
220            massspec_indexes,
221            len(self._mspeaks),
222            exp_freq=exp_freq,
223            ms_parent=ms_parent,
224        )
225
226        self._mspeaks.append(mspeak)

Add a new MSPeak object to the MassSpectrum object.

Parameters
  • ion_charge (int): The ion charge of the MSPeak.
  • mz_exp (float): The experimental m/z value of the MSPeak.
  • abundance (float): The abundance of the MSPeak.
  • resolving_power (float): The resolving power of the MSPeak.
  • signal_to_noise (float): The signal-to-noise ratio of the MSPeak.
  • massspec_indexes (list): A list of indexes of the MSPeak in the MassSpectrum object.
  • exp_freq (float, optional): The experimental frequency of the MSPeak. Defaults to None.
  • ms_parent (MSParent, optional): The MSParent object associated with the MSPeak. Defaults to None.
def reset_cal_therms(self, Aterm, Bterm, C, fas=0):
294    def reset_cal_therms(self, Aterm, Bterm, C, fas=0):
295        """Reset calibration terms and recalculate the mass-to-charge ratio and abundance.
296
297        Parameters
298        ----------
299        Aterm : float
300            The A-term calibration coefficient.
301        Bterm : float
302            The B-term calibration coefficient.
303        C : float
304            The C-term calibration coefficient.
305        fas : float, optional
306            The frequency amplitude scaling factor. Default is 0.
307        """
308        self._calibration_terms = (Aterm, Bterm, C)
309
310        self._mz_exp = self._f_to_mz()
311        self._abundance = self._abundance
312        self.find_peaks()
313        self.reset_indexes()

Reset calibration terms and recalculate the mass-to-charge ratio and abundance.

Parameters
  • Aterm (float): The A-term calibration coefficient.
  • Bterm (float): The B-term calibration coefficient.
  • C (float): The C-term calibration coefficient.
  • fas (float, optional): The frequency amplitude scaling factor. Default is 0.
def clear_molecular_formulas(self):
315    def clear_molecular_formulas(self):
316        """Clear the molecular formulas for all mspeaks in the MassSpectrum.
317
318        Returns
319        -------
320        numpy.ndarray
321            An array of the cleared molecular formulas for each mspeak in the MassSpectrum.
322        """
323        self.check_mspeaks()
324        return array([mspeak.clear_molecular_formulas() for mspeak in self.mspeaks])

Clear the molecular formulas for all mspeaks in the MassSpectrum.

Returns
  • numpy.ndarray: An array of the cleared molecular formulas for each mspeak in the MassSpectrum.
def process_mass_spec(self, keep_profile=True):
326    def process_mass_spec(self, keep_profile=True):
327        """Process the mass spectrum.
328
329        Parameters
330        ----------
331        keep_profile : bool, optional
332            Whether to keep the profile data after processing. Defaults to True.
333
334        Notes
335        -----
336        This method does the following:
337        - calculates the noise threshold
338        - does peak picking (creates mspeak_objs)
339        - resets the mspeak_obj indexes
340        """
341
342        # if runned mannually make sure to rerun filter_by_noise_threshold
343        # calculates noise threshold
344        # do peak picking( create mspeak_objs)
345        # reset mspeak_obj the indexes
346
347        self.cal_noise_threshold()
348
349        self.find_peaks()
350        self.reset_indexes()
351
352        if self.mspeaks:
353            self._dynamic_range = self.max_abundance / self.min_abundance
354        else:
355            self._dynamic_range = 0
356        if not keep_profile:
357            self._abundance *= 0
358            self._mz_exp *= 0

Process the mass spectrum.

Parameters
  • keep_profile (bool, optional): Whether to keep the profile data after processing. Defaults to True.
Notes

This method does the following:

  • calculates the noise threshold
  • does peak picking (creates mspeak_objs)
  • resets the mspeak_obj indexes
def cal_noise_threshold(self):
360    def cal_noise_threshold(self):
361        """Calculate the noise threshold of the mass spectrum."""
362
363        if self.label == Labels.simulated_profile:
364            self._baseline_noise, self._baseline_noise_std = 0.1, 1
365
366        if self.settings.noise_threshold_method == "log":
367            self._baseline_noise, self._baseline_noise_std = (
368                self.run_log_noise_threshold_calc()
369            )
370
371        else:
372            self._baseline_noise, self._baseline_noise_std = (
373                self.run_noise_threshold_calc()
374            )

Calculate the noise threshold of the mass spectrum.

parameters
376    @property
377    def parameters(self):
378        """Return the parameters of the mass spectrum."""
379        return self._parameters

Return the parameters of the mass spectrum.

def set_parameter_from_json(self, parameters_path):
385    def set_parameter_from_json(self, parameters_path):
386        """Set the parameters of the mass spectrum from a JSON file.
387
388        Parameters
389        ----------
390        parameters_path : str
391            The path to the JSON file containing the parameters.
392        """
393        load_and_set_parameters_ms(self, parameters_path=parameters_path)

Set the parameters of the mass spectrum from a JSON file.

Parameters
  • parameters_path (str): The path to the JSON file containing the parameters.
def set_parameter_from_toml(self, parameters_path):
395    def set_parameter_from_toml(self, parameters_path):
396        load_and_set_toml_parameters_ms(self, parameters_path=parameters_path)
mspeaks_settings
398    @property
399    def mspeaks_settings(self):
400        """Return the MS peak settings of the mass spectrum."""
401        return self.parameters.ms_peak

Return the MS peak settings of the mass spectrum.

settings
407    @property
408    def settings(self):
409        """Return the settings of the mass spectrum."""
410        return self.parameters.mass_spectrum

Return the settings of the mass spectrum.

molecular_search_settings
416    @property
417    def molecular_search_settings(self):
418        """Return the molecular search settings of the mass spectrum."""
419        return self.parameters.molecular_search

Return the molecular search settings of the mass spectrum.

mz_cal_profile
425    @property
426    def mz_cal_profile(self):
427        """Return the calibrated m/z profile of the mass spectrum."""
428        return self._mz_cal_profile

Return the calibrated m/z profile of the mass spectrum.

mz_cal
440    @property
441    def mz_cal(self):
442        """Return the calibrated m/z values of the mass spectrum."""
443        return array([mspeak.mz_cal for mspeak in self.mspeaks])

Return the calibrated m/z values of the mass spectrum.

mz_exp
457    @property
458    def mz_exp(self):
459        """Return the experimental m/z values of the mass spectrum."""
460        self.check_mspeaks()
461
462        if self.is_calibrated:
463            return array([mspeak.mz_cal for mspeak in self.mspeaks])
464
465        else:
466            return array([mspeak.mz_exp for mspeak in self.mspeaks])

Return the experimental m/z values of the mass spectrum.

freq_exp_profile
468    @property
469    def freq_exp_profile(self):
470        """Return the experimental frequency profile of the mass spectrum."""
471        return self._frequency_domain

Return the experimental frequency profile of the mass spectrum.

freq_exp_pp
477    @property
478    def freq_exp_pp(self):
479        """Return the experimental frequency values of the mass spectrum that are used for peak picking."""
480        _, _, freq = self.prepare_peak_picking_data()
481        return freq

Return the experimental frequency values of the mass spectrum that are used for peak picking.

mz_exp_profile
483    @property
484    def mz_exp_profile(self):
485        """Return the experimental m/z profile of the mass spectrum."""
486        if self.is_calibrated:
487            return self.mz_cal_profile
488        else:
489            return self._mz_exp

Return the experimental m/z profile of the mass spectrum.

mz_exp_pp
495    @property
496    def mz_exp_pp(self):
497        """Return the experimental m/z values of the mass spectrum that are used for peak picking."""
498        mz, _, _ = self.prepare_peak_picking_data()
499        return mz

Return the experimental m/z values of the mass spectrum that are used for peak picking.

abundance_profile
501    @property
502    def abundance_profile(self):
503        """Return the abundance profile of the mass spectrum."""
504        return self._abundance

Return the abundance profile of the mass spectrum.

abundance_profile_pp
510    @property
511    def abundance_profile_pp(self):
512        """Return the abundance profile of the mass spectrum that is used for peak picking."""
513        _, abundance, _ = self.prepare_peak_picking_data()
514        return abundance

Return the abundance profile of the mass spectrum that is used for peak picking.

abundance
516    @property
517    def abundance(self):
518        """Return the abundance values of the mass spectrum."""
519        self.check_mspeaks()
520        return array([mspeak.abundance for mspeak in self.mspeaks])

Return the abundance values of the mass spectrum.

def freq_exp(self):
522    def freq_exp(self):
523        """Return the experimental frequency values of the mass spectrum."""
524        self.check_mspeaks()
525        return array([mspeak.freq_exp for mspeak in self.mspeaks])

Return the experimental frequency values of the mass spectrum.

resolving_power
527    @property
528    def resolving_power(self):
529        """Return the resolving power values of the mass spectrum."""
530        self.check_mspeaks()
531        return array([mspeak.resolving_power for mspeak in self.mspeaks])

Return the resolving power values of the mass spectrum.

signal_to_noise
533    @property
534    def signal_to_noise(self):
535        self.check_mspeaks()
536        return array([mspeak.signal_to_noise for mspeak in self.mspeaks])
nominal_mz
538    @property
539    def nominal_mz(self):
540        """Return the nominal m/z values of the mass spectrum."""
541        if self._dict_nominal_masses_indexes:
542            return sorted(list(self._dict_nominal_masses_indexes.keys()))
543        else:
544            raise ValueError("Nominal indexes not yet set")

Return the nominal m/z values of the mass spectrum.

def get_mz_and_abundance_peaks_tuples(self):
546    def get_mz_and_abundance_peaks_tuples(self):
547        """Return a list of tuples containing the m/z and abundance values of the mass spectrum."""
548        self.check_mspeaks()
549        return [(mspeak.mz_exp, mspeak.abundance) for mspeak in self.mspeaks]

Return a list of tuples containing the m/z and abundance values of the mass spectrum.

kmd
551    @property
552    def kmd(self):
553        """Return the Kendrick mass defect values of the mass spectrum."""
554        self.check_mspeaks()
555        return array([mspeak.kmd for mspeak in self.mspeaks])

Return the Kendrick mass defect values of the mass spectrum.

kendrick_mass
557    @property
558    def kendrick_mass(self):
559        """Return the Kendrick mass values of the mass spectrum."""
560        self.check_mspeaks()
561        return array([mspeak.kendrick_mass for mspeak in self.mspeaks])

Return the Kendrick mass values of the mass spectrum.

max_mz_exp
563    @property
564    def max_mz_exp(self):
565        """Return the maximum experimental m/z value of the mass spectrum."""
566        return max([mspeak.mz_exp for mspeak in self.mspeaks])

Return the maximum experimental m/z value of the mass spectrum.

min_mz_exp
568    @property
569    def min_mz_exp(self):
570        """Return the minimum experimental m/z value of the mass spectrum."""
571        return min([mspeak.mz_exp for mspeak in self.mspeaks])

Return the minimum experimental m/z value of the mass spectrum.

max_abundance
573    @property
574    def max_abundance(self):
575        """Return the maximum abundance value of the mass spectrum."""
576        return max([mspeak.abundance for mspeak in self.mspeaks])

Return the maximum abundance value of the mass spectrum.

max_signal_to_noise
578    @property
579    def max_signal_to_noise(self):
580        """Return the maximum signal-to-noise ratio of the mass spectrum."""
581        return max([mspeak.signal_to_noise for mspeak in self.mspeaks])

Return the maximum signal-to-noise ratio of the mass spectrum.

most_abundant_mspeak
583    @property
584    def most_abundant_mspeak(self):
585        """Return the most abundant MSpeak object of the mass spectrum."""
586        return max(self.mspeaks, key=lambda m: m.abundance)

Return the most abundant MSpeak object of the mass spectrum.

min_abundance
588    @property
589    def min_abundance(self):
590        """Return the minimum abundance value of the mass spectrum."""
591        return min([mspeak.abundance for mspeak in self.mspeaks])

Return the minimum abundance value of the mass spectrum.

dynamic_range
594    @property
595    def dynamic_range(self):
596        """Return the dynamic range of the mass spectrum."""
597        return self._dynamic_range

Return the dynamic range of the mass spectrum.

baseline_noise
599    @property
600    def baseline_noise(self):
601        """Return the baseline noise of the mass spectrum."""
602        if self._baseline_noise:
603            return self._baseline_noise
604        else:
605            return None

Return the baseline noise of the mass spectrum.

baseline_noise_std
607    @property
608    def baseline_noise_std(self):
609        """Return the standard deviation of the baseline noise of the mass spectrum."""
610        if self._baseline_noise_std == 0:
611            return self._baseline_noise_std
612        if self._baseline_noise_std:
613            return self._baseline_noise_std
614        else:
615            return None

Return the standard deviation of the baseline noise of the mass spectrum.

Aterm
617    @property
618    def Aterm(self):
619        """Return the A-term calibration coefficient of the mass spectrum."""
620        return self._calibration_terms[0]

Return the A-term calibration coefficient of the mass spectrum.

Bterm
622    @property
623    def Bterm(self):
624        """Return the B-term calibration coefficient of the mass spectrum."""
625        return self._calibration_terms[1]

Return the B-term calibration coefficient of the mass spectrum.

Cterm
627    @property
628    def Cterm(self):
629        """Return the C-term calibration coefficient of the mass spectrum."""
630        return self._calibration_terms[2]

Return the C-term calibration coefficient of the mass spectrum.

filename
632    @property
633    def filename(self):
634        """Return the filename of the mass spectrum."""
635        return Path(self._filename)

Return the filename of the mass spectrum.

dir_location
637    @property
638    def dir_location(self):
639        """Return the directory location of the mass spectrum."""
640        return self._dir_location

Return the directory location of the mass spectrum.

def sort_by_mz(self):
642    def sort_by_mz(self):
643        """Sort the mass spectrum by m/z values."""
644        return sorted(self, key=lambda m: m.mz_exp)

Sort the mass spectrum by m/z values.

def sort_by_abundance(self, reverse=False):
646    def sort_by_abundance(self, reverse=False):
647        """Sort the mass spectrum by abundance values."""
648        return sorted(self, key=lambda m: m.abundance, reverse=reverse)

Sort the mass spectrum by abundance values.

tic
650    @property
651    def tic(self):
652        """Return the total ion current of the mass spectrum."""
653        return trapezoid(self.abundance_profile, self.mz_exp_profile)

Return the total ion current of the mass spectrum.

def check_mspeaks_warning(self):
655    def check_mspeaks_warning(self):
656        """Check if the mass spectrum has MSpeaks objects.
657
658        Raises
659        ------
660        Warning
661            If the mass spectrum has no MSpeaks objects.
662        """
663        import warnings
664
665        if self.mspeaks:
666            pass
667        else:
668            warnings.warn("mspeaks list is empty, continuing without filtering data")

Check if the mass spectrum has MSpeaks objects.

Raises
  • Warning: If the mass spectrum has no MSpeaks objects.
def check_mspeaks(self):
670    def check_mspeaks(self):
671        """Check if the mass spectrum has MSpeaks objects.
672
673        Raises
674        ------
675        Exception
676            If the mass spectrum has no MSpeaks objects.
677        """
678        if self.mspeaks:
679            pass
680        else:
681            raise Exception(
682                "mspeaks list is empty, please run process_mass_spec() first"
683            )

Check if the mass spectrum has MSpeaks objects.

Raises
  • Exception: If the mass spectrum has no MSpeaks objects.
def remove_assignment_by_index(self, indexes):
685    def remove_assignment_by_index(self, indexes):
686        """Remove the molecular formula assignment of the MSpeaks objects at the specified indexes.
687
688        Parameters
689        ----------
690        indexes : list of int
691            A list of indexes of the MSpeaks objects to remove the molecular formula assignment from.
692        """
693        for i in indexes:
694            self.mspeaks[i].clear_molecular_formulas()

Remove the molecular formula assignment of the MSpeaks objects at the specified indexes.

Parameters
  • indexes (list of int): A list of indexes of the MSpeaks objects to remove the molecular formula assignment from.
def filter_by_index(self, list_indexes):
696    def filter_by_index(self, list_indexes):
697        """Filter the mass spectrum by the specified indexes.
698
699        Parameters
700        ----------
701        list_indexes : list of int
702            A list of indexes of the MSpeaks objects to drop.
703
704        """
705
706        self.mspeaks = [
707            self.mspeaks[i] for i in range(len(self.mspeaks)) if i not in list_indexes
708        ]
709
710        for i, mspeak in enumerate(self.mspeaks):
711            mspeak.index = i
712
713        self._set_nominal_masses_start_final_indexes()

Filter the mass spectrum by the specified indexes.

Parameters
  • list_indexes (list of int): A list of indexes of the MSpeaks objects to drop.
def filter_by_mz(self, min_mz, max_mz):
715    def filter_by_mz(self, min_mz, max_mz):
716        """Filter the mass spectrum by the specified m/z range.
717
718        Parameters
719        ----------
720        min_mz : float
721            The minimum m/z value to keep.
722        max_mz : float
723            The maximum m/z value to keep.
724
725        """
726        self.check_mspeaks_warning()
727        indexes = [
728            index
729            for index, mspeak in enumerate(self.mspeaks)
730            if not min_mz <= mspeak.mz_exp <= max_mz
731        ]
732        self.filter_by_index(indexes)

Filter the mass spectrum by the specified m/z range.

Parameters
  • min_mz (float): The minimum m/z value to keep.
  • max_mz (float): The maximum m/z value to keep.
def filter_by_s2n(self, min_s2n, max_s2n=False):
734    def filter_by_s2n(self, min_s2n, max_s2n=False):
735        """Filter the mass spectrum by the specified signal-to-noise ratio range.
736
737        Parameters
738        ----------
739        min_s2n : float
740            The minimum signal-to-noise ratio to keep.
741        max_s2n : float, optional
742            The maximum signal-to-noise ratio to keep. Defaults to False (no maximum).
743
744        """
745        self.check_mspeaks_warning()
746        if max_s2n:
747            indexes = [
748                index
749                for index, mspeak in enumerate(self.mspeaks)
750                if not min_s2n <= mspeak.signal_to_noise <= max_s2n
751            ]
752        else:
753            indexes = [
754                index
755                for index, mspeak in enumerate(self.mspeaks)
756                if mspeak.signal_to_noise <= min_s2n
757            ]
758        self.filter_by_index(indexes)

Filter the mass spectrum by the specified signal-to-noise ratio range.

Parameters
  • min_s2n (float): The minimum signal-to-noise ratio to keep.
  • max_s2n (float, optional): The maximum signal-to-noise ratio to keep. Defaults to False (no maximum).
def filter_by_abundance(self, min_abund, max_abund=False):
760    def filter_by_abundance(self, min_abund, max_abund=False):
761        """Filter the mass spectrum by the specified abundance range.
762
763        Parameters
764        ----------
765        min_abund : float
766            The minimum abundance to keep.
767        max_abund : float, optional
768            The maximum abundance to keep. Defaults to False (no maximum).
769
770        """
771        self.check_mspeaks_warning()
772        if max_abund:
773            indexes = [
774                index
775                for index, mspeak in enumerate(self.mspeaks)
776                if not min_abund <= mspeak.abundance <= max_abund
777            ]
778        else:
779            indexes = [
780                index
781                for index, mspeak in enumerate(self.mspeaks)
782                if mspeak.abundance <= min_abund
783            ]
784        self.filter_by_index(indexes)

Filter the mass spectrum by the specified abundance range.

Parameters
  • min_abund (float): The minimum abundance to keep.
  • max_abund (float, optional): The maximum abundance to keep. Defaults to False (no maximum).
def filter_by_max_resolving_power(self, B, T):
786    def filter_by_max_resolving_power(self, B, T):
787        """Filter the mass spectrum by the specified maximum resolving power.
788
789        Parameters
790        ----------
791        B : float
792        T : float
793
794        """
795
796        rpe = lambda m, z: (1.274e7 * z * B * T) / (m * z)
797
798        self.check_mspeaks_warning()
799
800        indexes_to_remove = [
801            index
802            for index, mspeak in enumerate(self.mspeaks)
803            if mspeak.resolving_power >= rpe(mspeak.mz_exp, mspeak.ion_charge)
804        ]
805        self.filter_by_index(indexes_to_remove)

Filter the mass spectrum by the specified maximum resolving power.

Parameters
  • B (float):

  • T (float):

def filter_by_mean_resolving_power(self, ndeviations=3, plot=False, guess_pars=False):
807    def filter_by_mean_resolving_power(
808        self, ndeviations=3, plot=False, guess_pars=False
809    ):
810        """Filter the mass spectrum by the specified mean resolving power.
811
812        Parameters
813        ----------
814        ndeviations : float, optional
815            The number of standard deviations to use for filtering. Defaults to 3.
816        plot : bool, optional
817            Whether to plot the resolving power distribution. Defaults to False.
818        guess_pars : bool, optional
819            Whether to guess the parameters for the Gaussian model. Defaults to False.
820
821        """
822        self.check_mspeaks_warning()
823        indexes_to_remove = MeanResolvingPowerFilter(
824            self, ndeviations, plot, guess_pars
825        ).main()
826        self.filter_by_index(indexes_to_remove)

Filter the mass spectrum by the specified mean resolving power.

Parameters
  • ndeviations (float, optional): The number of standard deviations to use for filtering. Defaults to 3.
  • plot (bool, optional): Whether to plot the resolving power distribution. Defaults to False.
  • guess_pars (bool, optional): Whether to guess the parameters for the Gaussian model. Defaults to False.
def filter_by_min_resolving_power(self, B, T, apodization_method: str = None, tolerance: float = 0):
828    def filter_by_min_resolving_power(self, B, T, apodization_method: str=None, tolerance: float=0):
829        """Filter the mass spectrum by the calculated minimum theoretical resolving power.
830
831        This is currently designed only for FTICR data, and accounts only for magnitude mode data
832        Accurate results require passing the apodisaion method used to calculate the resolving power.
833        see the ICRMassPeak function `resolving_power_calc` for more details.
834
835        Parameters
836        ----------
837        B : Magnetic field strength in Tesla, float
838        T : transient length in seconds, float
839        apodization_method : str, optional
840            The apodization method to use for calculating the resolving power. Defaults to None.
841        tolerance : float, optional
842            The tolerance for the threshold. Defaults to 0, i.e. no tolerance
843
844        """
845        if self.analyzer != "ICR":
846            raise Exception(
847                "This method is only applicable to ICR mass spectra. "
848            )
849
850        self.check_mspeaks_warning()
851
852        indexes_to_remove = [
853            index
854            for index, mspeak in enumerate(self.mspeaks)
855            if mspeak.resolving_power < (1-tolerance) * mspeak.resolving_power_calc(B, T, apodization_method=apodization_method)
856        ]
857        self.filter_by_index(indexes_to_remove)

Filter the mass spectrum by the calculated minimum theoretical resolving power.

This is currently designed only for FTICR data, and accounts only for magnitude mode data Accurate results require passing the apodisaion method used to calculate the resolving power. see the ICRMassPeak function resolving_power_calc for more details.

Parameters
  • B (Magnetic field strength in Tesla, float):

  • T (transient length in seconds, float):

  • apodization_method (str, optional): The apodization method to use for calculating the resolving power. Defaults to None.

  • tolerance (float, optional): The tolerance for the threshold. Defaults to 0, i.e. no tolerance
def filter_by_noise_threshold(self):
859    def filter_by_noise_threshold(self):
860        """Filter the mass spectrum by the noise threshold."""
861
862        threshold = self.get_noise_threshold()[1][0]
863
864        self.check_mspeaks_warning()
865
866        indexes_to_remove = [
867            index
868            for index, mspeak in enumerate(self.mspeaks)
869            if mspeak.abundance <= threshold
870        ]
871        self.filter_by_index(indexes_to_remove)

Filter the mass spectrum by the noise threshold.

def find_peaks(self):
873    def find_peaks(self):
874        """Find the peaks of the mass spectrum."""
875        # needs to clear previous results from peak_picking
876        self._mspeaks = list()
877
878        # then do peak picking
879        self.do_peak_picking()
880        # print("A total of %i peaks were found" % len(self._mspeaks))

Find the peaks of the mass spectrum.

def change_kendrick_base_all_mspeaks(self, kendrick_dict_base):
882    def change_kendrick_base_all_mspeaks(self, kendrick_dict_base):
883        """Change the Kendrick base of all MSpeaks objects.
884
885        Parameters
886        ----------
887        kendrick_dict_base : dict
888            A dictionary of the Kendrick base to change to.
889
890        Notes
891        -----
892        Example of kendrick_dict_base parameter: kendrick_dict_base = {"C": 1, "H": 2} or {"C": 1, "H": 1, "O":1} etc
893        """
894        self.parameters.ms_peak.kendrick_base = kendrick_dict_base
895
896        for mspeak in self.mspeaks:
897            mspeak.change_kendrick_base(kendrick_dict_base)

Change the Kendrick base of all MSpeaks objects.

Parameters
  • kendrick_dict_base (dict): A dictionary of the Kendrick base to change to.
Notes

Example of kendrick_dict_base parameter: kendrick_dict_base = {"C": 1, "H": 2} or {"C": 1, "H": 1, "O":1} etc

def get_nominal_mz_first_last_indexes(self, nominal_mass):
899    def get_nominal_mz_first_last_indexes(self, nominal_mass):
900        """Return the first and last indexes of the MSpeaks objects with the specified nominal mass.
901
902        Parameters
903        ----------
904        nominal_mass : int
905            The nominal mass to get the indexes for.
906
907        Returns
908        -------
909        tuple
910            A tuple containing the first and last indexes of the MSpeaks objects with the specified nominal mass.
911        """
912        if self._dict_nominal_masses_indexes:
913            if nominal_mass in self._dict_nominal_masses_indexes.keys():
914                return (
915                    self._dict_nominal_masses_indexes.get(nominal_mass)[0],
916                    self._dict_nominal_masses_indexes.get(nominal_mass)[1] + 1,
917                )
918
919            else:
920                # import warnings
921                # uncomment warn to distribution
922                # warnings.warn("Nominal mass not found in _dict_nominal_masses_indexes, returning (0, 0) for nominal mass %i"%nominal_mass)
923                return (0, 0)
924        else:
925            raise Exception(
926                "run process_mass_spec() function before trying to access the data"
927            )

Return the first and last indexes of the MSpeaks objects with the specified nominal mass.

Parameters
  • nominal_mass (int): The nominal mass to get the indexes for.
Returns
  • tuple: A tuple containing the first and last indexes of the MSpeaks objects with the specified nominal mass.
def get_masses_count_by_nominal_mass(self):
929    def get_masses_count_by_nominal_mass(self):
930        """Return a dictionary of the nominal masses and their counts."""
931
932        dict_nominal_masses_count = {}
933
934        all_nominal_masses = list(set([i.nominal_mz_exp for i in self.mspeaks]))
935
936        for nominal_mass in all_nominal_masses:
937            if nominal_mass not in dict_nominal_masses_count:
938                dict_nominal_masses_count[nominal_mass] = len(
939                    list(self.get_nominal_mass_indexes(nominal_mass))
940                )
941
942        return dict_nominal_masses_count

Return a dictionary of the nominal masses and their counts.

def datapoints_count_by_nominal_mz(self, mz_overlay=0.1):
944    def datapoints_count_by_nominal_mz(self, mz_overlay=0.1):
945        """Return a dictionary of the nominal masses and their counts.
946
947        Parameters
948        ----------
949        mz_overlay : float, optional
950            The m/z overlay to use for counting. Defaults to 0.1.
951
952        Returns
953        -------
954        dict
955            A dictionary of the nominal masses and their counts.
956        """
957        dict_nominal_masses_count = {}
958
959        all_nominal_masses = list(set([i.nominal_mz_exp for i in self.mspeaks]))
960
961        for nominal_mass in all_nominal_masses:
962            if nominal_mass not in dict_nominal_masses_count:
963                min_mz = nominal_mass - mz_overlay
964
965                max_mz = nominal_mass + 1 + mz_overlay
966
967                indexes = indexes = where(
968                    (self.mz_exp_profile > min_mz) & (self.mz_exp_profile < max_mz)
969                )
970
971                dict_nominal_masses_count[nominal_mass] = indexes[0].size
972
973        return dict_nominal_masses_count

Return a dictionary of the nominal masses and their counts.

Parameters
  • mz_overlay (float, optional): The m/z overlay to use for counting. Defaults to 0.1.
Returns
  • dict: A dictionary of the nominal masses and their counts.
def get_nominal_mass_indexes(self, nominal_mass, overlay=0.1):
 975    def get_nominal_mass_indexes(self, nominal_mass, overlay=0.1):
 976        """Return the indexes of the MSpeaks objects with the specified nominal mass.
 977
 978        Parameters
 979        ----------
 980        nominal_mass : int
 981            The nominal mass to get the indexes for.
 982        overlay : float, optional
 983            The m/z overlay to use for counting. Defaults to 0.1.
 984
 985        Returns
 986        -------
 987        generator
 988            A generator of the indexes of the MSpeaks objects with the specified nominal mass.
 989        """
 990        min_mz_to_look = nominal_mass - overlay
 991        max_mz_to_look = nominal_mass + 1 + overlay
 992
 993        return (
 994            i
 995            for i in range(len(self.mspeaks))
 996            if min_mz_to_look <= self.mspeaks[i].mz_exp <= max_mz_to_look
 997        )
 998
 999        # indexes = (i for i in range(len(self.mspeaks)) if min_mz_to_look <= self.mspeaks[i].mz_exp <= max_mz_to_look)
1000        # return indexes

Return the indexes of the MSpeaks objects with the specified nominal mass.

Parameters
  • nominal_mass (int): The nominal mass to get the indexes for.
  • overlay (float, optional): The m/z overlay to use for counting. Defaults to 0.1.
Returns
  • generator: A generator of the indexes of the MSpeaks objects with the specified nominal mass.
def plot_centroid(self, ax=None, c='g'):
1027    def plot_centroid(self, ax=None, c="g"):
1028        """Plot the centroid data of the mass spectrum.
1029
1030        Parameters
1031        ----------
1032        ax : matplotlib.axes.Axes, optional
1033            The matplotlib axes to plot on. Defaults to None.
1034        c : str, optional
1035            The color to use for the plot. Defaults to 'g' (green).
1036
1037        Returns
1038        -------
1039        matplotlib.axes.Axes
1040            The matplotlib axes containing the plot.
1041
1042        Raises
1043        ------
1044        Exception
1045            If no centroid data is found.
1046        """
1047
1048        import matplotlib.pyplot as plt
1049
1050        if self._mspeaks:
1051            if ax is None:
1052                ax = plt.gca()
1053
1054            markerline_a, stemlines_a, baseline_a = ax.stem(
1055                self.mz_exp, self.abundance, linefmt="-", markerfmt=" "
1056            )
1057
1058            plt.setp(markerline_a, "color", c, "linewidth", 2)
1059            plt.setp(stemlines_a, "color", c, "linewidth", 2)
1060            plt.setp(baseline_a, "color", c, "linewidth", 2)
1061
1062            ax.set_xlabel("$\t{m/z}$", fontsize=12)
1063            ax.set_ylabel("Abundance", fontsize=12)
1064            ax.tick_params(axis="both", which="major", labelsize=12)
1065
1066            ax.axes.spines["top"].set_visible(False)
1067            ax.axes.spines["right"].set_visible(False)
1068
1069            ax.get_yaxis().set_visible(False)
1070            ax.spines["left"].set_visible(False)
1071
1072        else:
1073            raise Exception("No centroid data found, please run process_mass_spec")
1074
1075        return ax

Plot the centroid data of the mass spectrum.

Parameters
  • ax (matplotlib.axes.Axes, optional): The matplotlib axes to plot on. Defaults to None.
  • c (str, optional): The color to use for the plot. Defaults to 'g' (green).
Returns
  • matplotlib.axes.Axes: The matplotlib axes containing the plot.
Raises
  • Exception: If no centroid data is found.
def plot_profile_and_noise_threshold(self, ax=None, legend=False):
1077    def plot_profile_and_noise_threshold(self, ax=None, legend=False):
1078        """Plot the profile data and noise threshold of the mass spectrum.
1079
1080        Parameters
1081        ----------
1082        ax : matplotlib.axes.Axes, optional
1083            The matplotlib axes to plot on. Defaults to None.
1084        legend : bool, optional
1085            Whether to show the legend. Defaults to False.
1086
1087        Returns
1088        -------
1089        matplotlib.axes.Axes
1090            The matplotlib axes containing the plot.
1091
1092        Raises
1093        ------
1094        Exception
1095            If no noise threshold is found.
1096        """
1097        import matplotlib.pyplot as plt
1098
1099        if self.baseline_noise_std and self.baseline_noise_std:
1100            # x = (self.mz_exp_profile.min(), self.mz_exp_profile.max())
1101            baseline = (self.baseline_noise, self.baseline_noise)
1102
1103            # std = self.parameters.mass_spectrum.noise_threshold_min_std
1104            # threshold = self.baseline_noise_std + (std * self.baseline_noise_std)
1105            x, y = self.get_noise_threshold()
1106
1107            if ax is None:
1108                ax = plt.gca()
1109
1110            ax.plot(
1111                self.mz_exp_profile,
1112                self.abundance_profile,
1113                color="green",
1114                label="Spectrum",
1115            )
1116            ax.plot(x, (baseline, baseline), color="yellow", label="Baseline Noise")
1117            ax.plot(x, y, color="red", label="Noise Threshold")
1118
1119            ax.set_xlabel("$\t{m/z}$", fontsize=12)
1120            ax.set_ylabel("Abundance", fontsize=12)
1121            ax.tick_params(axis="both", which="major", labelsize=12)
1122
1123            ax.axes.spines["top"].set_visible(False)
1124            ax.axes.spines["right"].set_visible(False)
1125
1126            ax.get_yaxis().set_visible(False)
1127            ax.spines["left"].set_visible(False)
1128            if legend:
1129                ax.legend()
1130
1131        else:
1132            raise Exception("Calculate noise threshold first")
1133
1134        return ax

Plot the profile data and noise threshold of the mass spectrum.

Parameters
  • ax (matplotlib.axes.Axes, optional): The matplotlib axes to plot on. Defaults to None.
  • legend (bool, optional): Whether to show the legend. Defaults to False.
Returns
  • matplotlib.axes.Axes: The matplotlib axes containing the plot.
Raises
  • Exception: If no noise threshold is found.
def plot_mz_domain_profile(self, color='green', ax=None):
1136    def plot_mz_domain_profile(self, color="green", ax=None):
1137        """Plot the m/z domain profile of the mass spectrum.
1138
1139        Parameters
1140        ----------
1141        color : str, optional
1142            The color to use for the plot. Defaults to 'green'.
1143        ax : matplotlib.axes.Axes, optional
1144            The matplotlib axes to plot on. Defaults to None.
1145
1146        Returns
1147        -------
1148        matplotlib.axes.Axes
1149            The matplotlib axes containing the plot.
1150        """
1151
1152        import matplotlib.pyplot as plt
1153
1154        if ax is None:
1155            ax = plt.gca()
1156        ax.plot(self.mz_exp_profile, self.abundance_profile, color=color)
1157        ax.set(xlabel="m/z", ylabel="abundance")
1158
1159        return ax

Plot the m/z domain profile of the mass spectrum.

Parameters
  • color (str, optional): The color to use for the plot. Defaults to 'green'.
  • ax (matplotlib.axes.Axes, optional): The matplotlib axes to plot on. Defaults to None.
Returns
  • matplotlib.axes.Axes: The matplotlib axes containing the plot.
def to_excel(self, out_file_path, write_metadata=True):
1161    def to_excel(self, out_file_path, write_metadata=True):
1162        """Export the mass spectrum to an Excel file.
1163
1164        Parameters
1165        ----------
1166        out_file_path : str
1167            The path to the Excel file to export to.
1168        write_metadata : bool, optional
1169            Whether to write the metadata to the Excel file. Defaults to True.
1170
1171        Returns
1172        -------
1173        None
1174        """
1175        from corems.mass_spectrum.output.export import HighResMassSpecExport
1176
1177        exportMS = HighResMassSpecExport(out_file_path, self)
1178        exportMS.to_excel(write_metadata=write_metadata)

Export the mass spectrum to an Excel file.

Parameters
  • out_file_path (str): The path to the Excel file to export to.
  • write_metadata (bool, optional): Whether to write the metadata to the Excel file. Defaults to True.
Returns
  • None
def to_hdf(self, out_file_path):
1180    def to_hdf(self, out_file_path):
1181        """Export the mass spectrum to an HDF file.
1182
1183        Parameters
1184        ----------
1185        out_file_path : str
1186            The path to the HDF file to export to.
1187
1188        Returns
1189        -------
1190        None
1191        """
1192        from corems.mass_spectrum.output.export import HighResMassSpecExport
1193
1194        exportMS = HighResMassSpecExport(out_file_path, self)
1195        exportMS.to_hdf()

Export the mass spectrum to an HDF file.

Parameters
  • out_file_path (str): The path to the HDF file to export to.
Returns
  • None
def to_csv(self, out_file_path, write_metadata=True):
1197    def to_csv(self, out_file_path, write_metadata=True):
1198        """Export the mass spectrum to a CSV file.
1199
1200        Parameters
1201        ----------
1202        out_file_path : str
1203            The path to the CSV file to export to.
1204        write_metadata : bool, optional
1205            Whether to write the metadata to the CSV file. Defaults to True.
1206
1207        """
1208        from corems.mass_spectrum.output.export import HighResMassSpecExport
1209
1210        exportMS = HighResMassSpecExport(out_file_path, self)
1211        exportMS.to_csv(write_metadata=write_metadata)

Export the mass spectrum to a CSV file.

Parameters
  • out_file_path (str): The path to the CSV file to export to.
  • write_metadata (bool, optional): Whether to write the metadata to the CSV file. Defaults to True.
def to_pandas(self, out_file_path, write_metadata=True):
1213    def to_pandas(self, out_file_path, write_metadata=True):
1214        """Export the mass spectrum to a Pandas dataframe with pkl extension.
1215
1216        Parameters
1217        ----------
1218        out_file_path : str
1219            The path to the CSV file to export to.
1220        write_metadata : bool, optional
1221            Whether to write the metadata to the CSV file. Defaults to True.
1222
1223        """
1224        from corems.mass_spectrum.output.export import HighResMassSpecExport
1225
1226        exportMS = HighResMassSpecExport(out_file_path, self)
1227        exportMS.to_pandas(write_metadata=write_metadata)

Export the mass spectrum to a Pandas dataframe with pkl extension.

Parameters
  • out_file_path (str): The path to the CSV file to export to.
  • write_metadata (bool, optional): Whether to write the metadata to the CSV file. Defaults to True.
def to_dataframe(self, additional_columns=None):
1229    def to_dataframe(self, additional_columns=None):
1230        """Return the mass spectrum as a Pandas dataframe.
1231
1232        Parameters
1233        ----------
1234        additional_columns : list, optional
1235            A list of additional columns to include in the dataframe. Defaults to None.
1236            Suitable columns are: "Aromaticity Index", "Aromaticity Index (modified)", and "NOSC"
1237
1238        Returns
1239        -------
1240        pandas.DataFrame
1241            The mass spectrum as a Pandas dataframe.
1242        """
1243        from corems.mass_spectrum.output.export import HighResMassSpecExport
1244
1245        exportMS = HighResMassSpecExport(self.filename, self)
1246        return exportMS.get_pandas_df(additional_columns=additional_columns)

Return the mass spectrum as a Pandas dataframe.

Parameters
  • additional_columns (list, optional): A list of additional columns to include in the dataframe. Defaults to None. Suitable columns are: "Aromaticity Index", "Aromaticity Index (modified)", and "NOSC"
Returns
  • pandas.DataFrame: The mass spectrum as a Pandas dataframe.
def to_json(self):
1248    def to_json(self):
1249        """Return the mass spectrum as a JSON file."""
1250        from corems.mass_spectrum.output.export import HighResMassSpecExport
1251
1252        exportMS = HighResMassSpecExport(self.filename, self)
1253        return exportMS.to_json()

Return the mass spectrum as a JSON file.

def parameters_json(self):
1255    def parameters_json(self):
1256        """Return the parameters of the mass spectrum as a JSON string."""
1257        from corems.mass_spectrum.output.export import HighResMassSpecExport
1258
1259        exportMS = HighResMassSpecExport(self.filename, self)
1260        return exportMS.parameters_to_json()

Return the parameters of the mass spectrum as a JSON string.

def parameters_toml(self):
1262    def parameters_toml(self):
1263        """Return the parameters of the mass spectrum as a TOML string."""
1264        from corems.mass_spectrum.output.export import HighResMassSpecExport
1265
1266        exportMS = HighResMassSpecExport(self.filename, self)
1267        return exportMS.parameters_to_toml()

Return the parameters of the mass spectrum as a TOML string.

class MassSpecProfile(MassSpecBase):
1270class MassSpecProfile(MassSpecBase):
1271    """A mass spectrum class when the entry point is on profile format
1272
1273    Notes
1274    -----
1275    Stores the profile data and instrument settings.
1276    Iteration over a list of MSPeaks classes stored at the _mspeaks attributes.
1277    _mspeaks is populated under the hood by calling process_mass_spec method.
1278    Iteration is null if _mspeaks is empty. Many more attributes and methods inherited from MassSpecBase().
1279
1280    Parameters
1281    ----------
1282    data_dict : dict
1283        A dictionary containing the profile data.
1284    d_params : dict{'str': float, int or str}
1285        contains the instrument settings and processing settings
1286    auto_process : bool, optional
1287        Whether to automatically process the mass spectrum. Defaults to True.
1288
1289
1290    Attributes
1291    ----------
1292    _abundance : ndarray
1293        The abundance values of the mass spectrum.
1294    _mz_exp : ndarray
1295        The m/z values of the mass spectrum.
1296    _mspeaks : list
1297        A list of mass peaks.
1298
1299    Methods
1300    ----------
1301    * process_mass_spec(). Process the mass spectrum.
1302
1303    see also: MassSpecBase(), MassSpecfromFreq(), MassSpecCentroid()
1304    """
1305
1306    def __init__(self, data_dict, d_params, auto_process=True):
1307        # print(data_dict.keys())
1308        super().__init__(
1309            data_dict.get(Labels.mz), data_dict.get(Labels.abundance), d_params
1310        )
1311
1312        if auto_process:
1313            self.process_mass_spec()

A mass spectrum class when the entry point is on profile format

Notes

Stores the profile data and instrument settings. Iteration over a list of MSPeaks classes stored at the _mspeaks attributes. _mspeaks is populated under the hood by calling process_mass_spec method. Iteration is null if _mspeaks is empty. Many more attributes and methods inherited from MassSpecBase().

Parameters
  • data_dict (dict): A dictionary containing the profile data.
  • d_params : dict{'str' (float, int or str}): contains the instrument settings and processing settings
  • auto_process (bool, optional): Whether to automatically process the mass spectrum. Defaults to True.
Attributes
  • _abundance (ndarray): The abundance values of the mass spectrum.
  • _mz_exp (ndarray): The m/z values of the mass spectrum.
  • _mspeaks (list): A list of mass peaks.
Methods
  • process_mass_spec(). Process the mass spectrum.

see also: MassSpecBase(), MassSpecfromFreq(), MassSpecCentroid()

MassSpecProfile(data_dict, d_params, auto_process=True)
1306    def __init__(self, data_dict, d_params, auto_process=True):
1307        # print(data_dict.keys())
1308        super().__init__(
1309            data_dict.get(Labels.mz), data_dict.get(Labels.abundance), d_params
1310        )
1311
1312        if auto_process:
1313            self.process_mass_spec()
Inherited Members
MassSpecBase
mspeaks
is_calibrated
is_centroid
has_frequency
calibration_order
calibration_points
calibration_ref_mzs
calibration_meas_mzs
calibration_RMS
calibration_segment
calibration_raw_error_median
calibration_raw_error_stdev
set_indexes
reset_indexes
add_mspeak
reset_cal_therms
clear_molecular_formulas
process_mass_spec
cal_noise_threshold
parameters
set_parameter_from_json
set_parameter_from_toml
mspeaks_settings
settings
molecular_search_settings
mz_cal_profile
mz_cal
mz_exp
freq_exp_profile
freq_exp_pp
mz_exp_profile
mz_exp_pp
abundance_profile
abundance_profile_pp
abundance
freq_exp
resolving_power
signal_to_noise
nominal_mz
get_mz_and_abundance_peaks_tuples
kmd
kendrick_mass
max_mz_exp
min_mz_exp
max_abundance
max_signal_to_noise
most_abundant_mspeak
min_abundance
dynamic_range
baseline_noise
baseline_noise_std
Aterm
Bterm
Cterm
filename
dir_location
sort_by_mz
sort_by_abundance
tic
check_mspeaks_warning
check_mspeaks
remove_assignment_by_index
filter_by_index
filter_by_mz
filter_by_s2n
filter_by_abundance
filter_by_max_resolving_power
filter_by_mean_resolving_power
filter_by_min_resolving_power
filter_by_noise_threshold
find_peaks
change_kendrick_base_all_mspeaks
get_nominal_mz_first_last_indexes
get_masses_count_by_nominal_mass
datapoints_count_by_nominal_mz
get_nominal_mass_indexes
plot_centroid
plot_profile_and_noise_threshold
plot_mz_domain_profile
to_excel
to_hdf
to_csv
to_pandas
to_dataframe
to_json
parameters_json
parameters_toml
corems.mass_spectrum.calc.MassSpectrumCalc.MassSpecCalc
percentage_assigned
percentile_assigned
resolving_power_calc
number_average_molecular_weight
weight_average_molecular_weight
corems.mass_spectrum.calc.PeakPicking.PeakPicking
prepare_peak_picking_data
cut_mz_domain_peak_picking
legacy_cut_mz_domain_peak_picking
extrapolate_axis
extrapolate_axes_for_pp
do_peak_picking
find_minima
linear_fit_calc
calculate_resolving_power
cal_minima
calc_centroid
get_threshold
algebraic_quadratic
find_apex_fit_quadratic
check_prominence
use_the_max
calc_centroid_legacy
corems.mass_spectrum.calc.NoiseCalc.NoiseThresholdCalc
get_noise_threshold
cut_mz_domain_noise
get_noise_average
get_abundance_minima_centroid
run_log_noise_threshold_calc
run_noise_threshold_calc
corems.mass_spectrum.calc.KendrickGroup.KendrickGrouping
mz_odd_even_index_lists
calc_error
populate_kendrick_index_dict_error
populate_kendrick_index_dict_rounding
sort_abundance_kendrick_dict
kendrick_groups_indexes
class MassSpecfromFreq(MassSpecBase):
1316class MassSpecfromFreq(MassSpecBase):
1317    """A mass spectrum class when data entry is on frequency domain
1318
1319    Notes
1320    -----
1321    - Transform to m/z based on the settings stored at d_params
1322    - Stores the profile data and instrument settings
1323    - Iteration over a list of MSPeaks classes stored at the _mspeaks attributes
1324    - _mspeaks is populated under the hood by calling process_mass_spec method
1325    - iteration is null if _mspeaks is empty
1326
1327    Parameters
1328    ----------
1329    frequency_domain : list(float)
1330        all datapoints in frequency domain in Hz
1331    magnitude :  frequency_domain : list(float)
1332        all datapoints in for magnitude of each frequency datapoint
1333    d_params : dict{'str': float, int or str}
1334        contains the instrument settings and processing settings
1335    auto_process : bool, optional
1336        Whether to automatically process the mass spectrum. Defaults to True.
1337    keep_profile : bool, optional
1338        Whether to keep the profile data. Defaults to True.
1339
1340    Attributes
1341    ----------
1342    has_frequency : bool
1343        Whether the mass spectrum has frequency data.
1344    _frequency_domain : list(float)
1345        Frequency domain in Hz
1346    label : str
1347        store label (Bruker, Midas Transient, see Labels class ). It across distinct processing points
1348    _abundance : ndarray
1349        The abundance values of the mass spectrum.
1350    _mz_exp : ndarray
1351        The m/z values of the mass spectrum.
1352    _mspeaks : list
1353        A list of mass peaks.
1354    See Also: all the attributes of MassSpecBase class
1355
1356    Methods
1357    ----------
1358    * _set_mz_domain().
1359        calculates the m_z based on the setting of d_params
1360    * process_mass_spec().  Process the mass spectrum.
1361
1362    see also: MassSpecBase(), MassSpecProfile(), MassSpecCentroid()
1363    """
1364
1365    def __init__(
1366        self,
1367        frequency_domain,
1368        magnitude,
1369        d_params,
1370        auto_process=True,
1371        keep_profile=True,
1372    ):
1373        super().__init__(None, magnitude, d_params)
1374
1375        self._frequency_domain = frequency_domain
1376        self.has_frequency = True
1377        self._set_mz_domain()
1378        self._sort_mz_domain()
1379
1380        self.magnetron_frequency = None
1381        self.magnetron_frequency_sigma = None
1382
1383        # use this call to automatically process data as the object is created, Setting need to be changed before initiating the class to be in effect
1384
1385        if auto_process:
1386            self.process_mass_spec(keep_profile=keep_profile)
1387
1388    def _sort_mz_domain(self):
1389        """Sort the mass spectrum by m/z values."""
1390
1391        if self._mz_exp[0] > self._mz_exp[-1]:
1392            self._mz_exp = self._mz_exp[::-1]
1393            self._abundance = self._abundance[::-1]
1394            self._frequency_domain = self._frequency_domain[::-1]
1395
1396    def _set_mz_domain(self):
1397        """Set the m/z domain of the mass spectrum based on the settings of d_params."""
1398        if self.label == Labels.bruker_frequency:
1399            self._mz_exp = self._f_to_mz_bruker()
1400
1401        else:
1402            self._mz_exp = self._f_to_mz()
1403
1404    @property
1405    def transient_settings(self):
1406        """Return the transient settings of the mass spectrum."""
1407        return self.parameters.transient
1408
1409    @transient_settings.setter
1410    def transient_settings(self, instance_TransientSetting):
1411        self.parameters.transient = instance_TransientSetting
1412
1413    def calc_magnetron_freq(self, max_magnetron_freq=50, magnetron_freq_bins=300):
1414        """Calculates the magnetron frequency of the mass spectrum.
1415
1416        Parameters
1417        ----------
1418        max_magnetron_freq : float, optional
1419            The maximum magnetron frequency. Defaults to 50.
1420        magnetron_freq_bins : int, optional
1421            The number of bins to use for the histogram. Defaults to 300.
1422
1423        Returns
1424        -------
1425        None
1426
1427        Notes
1428        -----
1429        Calculates the magnetron frequency by examining all the picked peaks and the distances between them in the frequency domain.
1430        A histogram of those values below the threshold 'max_magnetron_freq' with the 'magnetron_freq_bins' number of bins is calculated.
1431        A gaussian model is fit to this histogram - the center value of this (statistically probably) the magnetron frequency.
1432        This appears to work well or nOmega datasets, but may not work well for 1x datasets or those with very low magnetron peaks.
1433        """
1434        ms_df = DataFrame(self.freq_exp(), columns=["Freq"])
1435        ms_df["FreqDelta"] = ms_df["Freq"].diff()
1436
1437        freq_hist = histogram(
1438            ms_df[ms_df["FreqDelta"] < max_magnetron_freq]["FreqDelta"],
1439            bins=magnetron_freq_bins,
1440        )
1441
1442        mod = GaussianModel()
1443        pars = mod.guess(freq_hist[0], x=freq_hist[1][:-1])
1444        out = mod.fit(freq_hist[0], pars, x=freq_hist[1][:-1])
1445        self.magnetron_frequency = out.best_values["center"]
1446        self.magnetron_frequency_sigma = out.best_values["sigma"]

A mass spectrum class when data entry is on frequency domain

Notes
  • Transform to m/z based on the settings stored at d_params
  • Stores the profile data and instrument settings
  • Iteration over a list of MSPeaks classes stored at the _mspeaks attributes
  • _mspeaks is populated under the hood by calling process_mass_spec method
  • iteration is null if _mspeaks is empty
Parameters
  • frequency_domain (list(float)): all datapoints in frequency domain in Hz
  • magnitude : frequency_domain (list(float)): all datapoints in for magnitude of each frequency datapoint
  • d_params : dict{'str' (float, int or str}): contains the instrument settings and processing settings
  • auto_process (bool, optional): Whether to automatically process the mass spectrum. Defaults to True.
  • keep_profile (bool, optional): Whether to keep the profile data. Defaults to True.
Attributes
  • has_frequency (bool): Whether the mass spectrum has frequency data.
  • _frequency_domain (list(float)): Frequency domain in Hz
  • label (str): store label (Bruker, Midas Transient, see Labels class ). It across distinct processing points
  • _abundance (ndarray): The abundance values of the mass spectrum.
  • _mz_exp (ndarray): The m/z values of the mass spectrum.
  • _mspeaks (list): A list of mass peaks.
  • See Also (all the attributes of MassSpecBase class):
Methods
  • _set_mz_domain(). calculates the m_z based on the setting of d_params
  • process_mass_spec(). Process the mass spectrum.

see also: MassSpecBase(), MassSpecProfile(), MassSpecCentroid()

MassSpecfromFreq( frequency_domain, magnitude, d_params, auto_process=True, keep_profile=True)
1365    def __init__(
1366        self,
1367        frequency_domain,
1368        magnitude,
1369        d_params,
1370        auto_process=True,
1371        keep_profile=True,
1372    ):
1373        super().__init__(None, magnitude, d_params)
1374
1375        self._frequency_domain = frequency_domain
1376        self.has_frequency = True
1377        self._set_mz_domain()
1378        self._sort_mz_domain()
1379
1380        self.magnetron_frequency = None
1381        self.magnetron_frequency_sigma = None
1382
1383        # use this call to automatically process data as the object is created, Setting need to be changed before initiating the class to be in effect
1384
1385        if auto_process:
1386            self.process_mass_spec(keep_profile=keep_profile)
has_frequency
magnetron_frequency
magnetron_frequency_sigma
transient_settings
1404    @property
1405    def transient_settings(self):
1406        """Return the transient settings of the mass spectrum."""
1407        return self.parameters.transient

Return the transient settings of the mass spectrum.

def calc_magnetron_freq(self, max_magnetron_freq=50, magnetron_freq_bins=300):
1413    def calc_magnetron_freq(self, max_magnetron_freq=50, magnetron_freq_bins=300):
1414        """Calculates the magnetron frequency of the mass spectrum.
1415
1416        Parameters
1417        ----------
1418        max_magnetron_freq : float, optional
1419            The maximum magnetron frequency. Defaults to 50.
1420        magnetron_freq_bins : int, optional
1421            The number of bins to use for the histogram. Defaults to 300.
1422
1423        Returns
1424        -------
1425        None
1426
1427        Notes
1428        -----
1429        Calculates the magnetron frequency by examining all the picked peaks and the distances between them in the frequency domain.
1430        A histogram of those values below the threshold 'max_magnetron_freq' with the 'magnetron_freq_bins' number of bins is calculated.
1431        A gaussian model is fit to this histogram - the center value of this (statistically probably) the magnetron frequency.
1432        This appears to work well or nOmega datasets, but may not work well for 1x datasets or those with very low magnetron peaks.
1433        """
1434        ms_df = DataFrame(self.freq_exp(), columns=["Freq"])
1435        ms_df["FreqDelta"] = ms_df["Freq"].diff()
1436
1437        freq_hist = histogram(
1438            ms_df[ms_df["FreqDelta"] < max_magnetron_freq]["FreqDelta"],
1439            bins=magnetron_freq_bins,
1440        )
1441
1442        mod = GaussianModel()
1443        pars = mod.guess(freq_hist[0], x=freq_hist[1][:-1])
1444        out = mod.fit(freq_hist[0], pars, x=freq_hist[1][:-1])
1445        self.magnetron_frequency = out.best_values["center"]
1446        self.magnetron_frequency_sigma = out.best_values["sigma"]

Calculates the magnetron frequency of the mass spectrum.

Parameters
  • max_magnetron_freq (float, optional): The maximum magnetron frequency. Defaults to 50.
  • magnetron_freq_bins (int, optional): The number of bins to use for the histogram. Defaults to 300.
Returns
  • None
Notes

Calculates the magnetron frequency by examining all the picked peaks and the distances between them in the frequency domain. A histogram of those values below the threshold 'max_magnetron_freq' with the 'magnetron_freq_bins' number of bins is calculated. A gaussian model is fit to this histogram - the center value of this (statistically probably) the magnetron frequency. This appears to work well or nOmega datasets, but may not work well for 1x datasets or those with very low magnetron peaks.

Inherited Members
MassSpecBase
mspeaks
is_calibrated
is_centroid
calibration_order
calibration_points
calibration_ref_mzs
calibration_meas_mzs
calibration_RMS
calibration_segment
calibration_raw_error_median
calibration_raw_error_stdev
set_indexes
reset_indexes
add_mspeak
reset_cal_therms
clear_molecular_formulas
process_mass_spec
cal_noise_threshold
parameters
set_parameter_from_json
set_parameter_from_toml
mspeaks_settings
settings
molecular_search_settings
mz_cal_profile
mz_cal
mz_exp
freq_exp_profile
freq_exp_pp
mz_exp_profile
mz_exp_pp
abundance_profile
abundance_profile_pp
abundance
freq_exp
resolving_power
signal_to_noise
nominal_mz
get_mz_and_abundance_peaks_tuples
kmd
kendrick_mass
max_mz_exp
min_mz_exp
max_abundance
max_signal_to_noise
most_abundant_mspeak
min_abundance
dynamic_range
baseline_noise
baseline_noise_std
Aterm
Bterm
Cterm
filename
dir_location
sort_by_mz
sort_by_abundance
tic
check_mspeaks_warning
check_mspeaks
remove_assignment_by_index
filter_by_index
filter_by_mz
filter_by_s2n
filter_by_abundance
filter_by_max_resolving_power
filter_by_mean_resolving_power
filter_by_min_resolving_power
filter_by_noise_threshold
find_peaks
change_kendrick_base_all_mspeaks
get_nominal_mz_first_last_indexes
get_masses_count_by_nominal_mass
datapoints_count_by_nominal_mz
get_nominal_mass_indexes
plot_centroid
plot_profile_and_noise_threshold
plot_mz_domain_profile
to_excel
to_hdf
to_csv
to_pandas
to_dataframe
to_json
parameters_json
parameters_toml
corems.mass_spectrum.calc.MassSpectrumCalc.MassSpecCalc
percentage_assigned
percentile_assigned
resolving_power_calc
number_average_molecular_weight
weight_average_molecular_weight
corems.mass_spectrum.calc.PeakPicking.PeakPicking
prepare_peak_picking_data
cut_mz_domain_peak_picking
legacy_cut_mz_domain_peak_picking
extrapolate_axis
extrapolate_axes_for_pp
do_peak_picking
find_minima
linear_fit_calc
calculate_resolving_power
cal_minima
calc_centroid
get_threshold
algebraic_quadratic
find_apex_fit_quadratic
check_prominence
use_the_max
calc_centroid_legacy
corems.mass_spectrum.calc.NoiseCalc.NoiseThresholdCalc
get_noise_threshold
cut_mz_domain_noise
get_noise_average
get_abundance_minima_centroid
run_log_noise_threshold_calc
run_noise_threshold_calc
corems.mass_spectrum.calc.KendrickGroup.KendrickGrouping
mz_odd_even_index_lists
calc_error
populate_kendrick_index_dict_error
populate_kendrick_index_dict_rounding
sort_abundance_kendrick_dict
kendrick_groups_indexes
class MassSpecCentroid(MassSpecBase):
1449class MassSpecCentroid(MassSpecBase):
1450    """A mass spectrum class when the entry point is on centroid format
1451
1452    Notes
1453    -----
1454    - Stores the centroid data and instrument settings
1455    - Simulate profile data based on Gaussian or Lorentzian peak shape
1456    - Iteration over a list of MSPeaks classes stored at the _mspeaks attributes
1457    - _mspeaks is populated under the hood by calling process_mass_spec method
1458    - iteration is null if _mspeaks is empty
1459
1460    Parameters
1461    ----------
1462    data_dict : dict {string: numpy array float64 )
1463        contains keys [m/z, Abundance, Resolving Power, S/N]
1464    d_params : dict{'str': float, int or str}
1465        contains the instrument settings and processing settings
1466    auto_process : bool, optional
1467        Whether to automatically process the mass spectrum. Defaults to True.
1468
1469    Attributes
1470    ----------
1471    label : str
1472        store label (Bruker, Midas Transient, see Labels class)
1473    _baseline_noise : float
1474        store baseline noise
1475    _baseline_noise_std : float
1476        store baseline noise std
1477    _abundance : ndarray
1478        The abundance values of the mass spectrum.
1479    _mz_exp : ndarray
1480        The m/z values of the mass spectrum.
1481    _mspeaks : list
1482        A list of mass peaks.
1483
1484
1485    Methods
1486    ----------
1487    * process_mass_spec().
1488        Process the mass spectrum. Overriden from MassSpecBase. Populates the _mspeaks list with MSpeaks class using the centroid data.
1489    * __simulate_profile__data__().
1490        Simulate profile data based on Gaussian or Lorentzian peak shape. Needs theoretical resolving power calculation and define peak shape, intended for plotting and inspection purposes only.
1491
1492    see also: MassSpecBase(), MassSpecfromFreq(), MassSpecProfile()
1493    """
1494
1495    def __init__(self, data_dict, d_params, auto_process=True):
1496        super().__init__([], [], d_params)
1497
1498        self._set_parameters_objects(d_params)
1499
1500        if self.label == Labels.thermo_centroid:
1501            self._baseline_noise = d_params.get("baseline_noise")
1502            self._baseline_noise_std = d_params.get("baseline_noise_std")
1503
1504        self.is_centroid = True
1505        self.data_dict = data_dict
1506        self._mz_exp = data_dict[Labels.mz]
1507        self._abundance = data_dict[Labels.abundance]
1508
1509        if auto_process:
1510            self.process_mass_spec()
1511
1512    def __simulate_profile__data__(self, exp_mz_centroid, magnitude_centroid):
1513        """Simulate profile data based on Gaussian or Lorentzian peak shape
1514
1515        Notes
1516        -----
1517        Needs theoretical resolving power calculation and define peak shape.
1518        This is a quick fix to trick a line plot be able to plot as sticks for plotting and inspection purposes only.
1519
1520        Parameters
1521        ----------
1522        exp_mz_centroid : list(float)
1523            list of m/z values
1524        magnitude_centroid : list(float)
1525            list of abundance values
1526
1527
1528        Returns
1529        -------
1530        x : list(float)
1531            list of m/z values
1532        y : list(float)
1533            list of abundance values
1534        """
1535
1536        x, y = [], []
1537        for i in range(len(exp_mz_centroid)):
1538            x.append(exp_mz_centroid[i] - 0.0000001)
1539            x.append(exp_mz_centroid[i])
1540            x.append(exp_mz_centroid[i] + 0.0000001)
1541            y.append(0)
1542            y.append(magnitude_centroid[i])
1543            y.append(0)
1544        return x, y
1545
1546    @property
1547    def mz_exp_profile(self):
1548        """Return the m/z profile of the mass spectrum."""
1549        mz_list = []
1550        for mz in self.mz_exp:
1551            mz_list.append(mz - 0.0000001)
1552            mz_list.append(mz)
1553            mz_list.append(mz + 0.0000001)
1554        return mz_list
1555
1556    @mz_exp_profile.setter
1557    def mz_exp_profile(self, _mz_exp):
1558        self._mz_exp = _mz_exp
1559
1560    @property
1561    def abundance_profile(self):
1562        """Return the abundance profile of the mass spectrum."""
1563        ab_list = []
1564        for ab in self.abundance:
1565            ab_list.append(0)
1566            ab_list.append(ab)
1567            ab_list.append(0)
1568        return ab_list
1569
1570    @abundance_profile.setter
1571    def abundance_profile(self, abundance):
1572        self._abundance = abundance
1573
1574    @property
1575    def tic(self):
1576        """Return the total ion current of the mass spectrum."""
1577        return sum(self.abundance)
1578
1579    def process_mass_spec(self):
1580        """Process the mass spectrum."""
1581        import tqdm
1582
1583        # overwrite process_mass_spec
1584        # mspeak objs are usually added inside the PeaKPicking class
1585        # for profile and freq based data
1586        data_dict = self.data_dict
1587        ion_charge = self.polarity
1588
1589        # Check if resolving power is present
1590        rp_present = True
1591        if not data_dict.get(Labels.rp):
1592            rp_present = False
1593        if rp_present and list(data_dict.get(Labels.rp)) == [None] * len(
1594            data_dict.get(Labels.rp)
1595        ):
1596            rp_present = False
1597
1598        # Check if s2n is present
1599        s2n_present = True
1600        if not data_dict.get(Labels.s2n):
1601            s2n_present = False
1602        if s2n_present and list(data_dict.get(Labels.s2n)) == [None] * len(
1603            data_dict.get(Labels.s2n)
1604        ):
1605            s2n_present = False
1606
1607        # Warning if no s2n data but noise thresholding is set to signal_noise
1608        if (
1609            not s2n_present
1610            and self.parameters.mass_spectrum.noise_threshold_method == "signal_noise"
1611        ):
1612            raise Exception("Signal to Noise data is missing for noise thresholding")
1613
1614        # Pull out abundance data
1615        abun = array(data_dict.get(Labels.abundance)).astype(float)
1616
1617        # Get the threshold for filtering if using minima, relative, or absolute abundance thresholding
1618        abundance_threshold, factor = self.get_threshold(abun)
1619
1620        # Set rp_i and s2n_i to None which will be overwritten if present
1621        rp_i, s2n_i = np.nan, np.nan
1622        for index, mz in enumerate(data_dict.get(Labels.mz)):
1623            if rp_present:
1624                if not data_dict.get(Labels.rp)[index]:
1625                    rp_i = np.nan
1626                else:
1627                    rp_i = float(data_dict.get(Labels.rp)[index])
1628            if s2n_present:
1629                if not data_dict.get(Labels.s2n)[index]:
1630                    s2n_i = np.nan
1631                else:
1632                    s2n_i = float(data_dict.get(Labels.s2n)[index])
1633
1634            # centroid peak does not have start and end peak index pos
1635            massspec_indexes = (index, index, index)
1636
1637            # Add peaks based on the noise thresholding method
1638            if (
1639                self.parameters.mass_spectrum.noise_threshold_method
1640                in ["minima", "relative_abundance", "absolute_abundance"]
1641                and abun[index] / factor >= abundance_threshold
1642            ):
1643                self.add_mspeak(
1644                    ion_charge,
1645                    mz,
1646                    abun[index],
1647                    rp_i,
1648                    s2n_i,
1649                    massspec_indexes,
1650                    ms_parent=self,
1651                )
1652            if (
1653                self.parameters.mass_spectrum.noise_threshold_method == "signal_noise"
1654                and s2n_i >= self.parameters.mass_spectrum.noise_threshold_min_s2n
1655            ):
1656                self.add_mspeak(
1657                    ion_charge,
1658                    mz,
1659                    abun[index],
1660                    rp_i,
1661                    s2n_i,
1662                    massspec_indexes,
1663                    ms_parent=self,
1664                )
1665
1666        self.mspeaks = self._mspeaks
1667        self._dynamic_range = self.max_abundance / self.min_abundance
1668        self._set_nominal_masses_start_final_indexes()
1669
1670        if self.label != Labels.thermo_centroid:
1671            if self.settings.noise_threshold_method == "log":
1672                raise Exception("log noise Not tested for centroid data")
1673                # self._baseline_noise, self._baseline_noise_std = self.run_log_noise_threshold_calc()
1674
1675            else:
1676                self._baseline_noise, self._baseline_noise_std = (
1677                    self.run_noise_threshold_calc()
1678                )
1679
1680        del self.data_dict

A mass spectrum class when the entry point is on centroid format

Notes
  • Stores the centroid data and instrument settings
  • Simulate profile data based on Gaussian or Lorentzian peak shape
  • Iteration over a list of MSPeaks classes stored at the _mspeaks attributes
  • _mspeaks is populated under the hood by calling process_mass_spec method
  • iteration is null if _mspeaks is empty
Parameters
  • data_dict : dict {string (numpy array float64 )): contains keys [m/z, Abundance, Resolving Power, S/N]
  • d_params : dict{'str' (float, int or str}): contains the instrument settings and processing settings
  • auto_process (bool, optional): Whether to automatically process the mass spectrum. Defaults to True.
Attributes
  • label (str): store label (Bruker, Midas Transient, see Labels class)
  • _baseline_noise (float): store baseline noise
  • _baseline_noise_std (float): store baseline noise std
  • _abundance (ndarray): The abundance values of the mass spectrum.
  • _mz_exp (ndarray): The m/z values of the mass spectrum.
  • _mspeaks (list): A list of mass peaks.
Methods
  • process_mass_spec(). Process the mass spectrum. Overriden from MassSpecBase. Populates the _mspeaks list with MSpeaks class using the centroid data.
  • __simulate_profile__data__(). Simulate profile data based on Gaussian or Lorentzian peak shape. Needs theoretical resolving power calculation and define peak shape, intended for plotting and inspection purposes only.

see also: MassSpecBase(), MassSpecfromFreq(), MassSpecProfile()

MassSpecCentroid(data_dict, d_params, auto_process=True)
1495    def __init__(self, data_dict, d_params, auto_process=True):
1496        super().__init__([], [], d_params)
1497
1498        self._set_parameters_objects(d_params)
1499
1500        if self.label == Labels.thermo_centroid:
1501            self._baseline_noise = d_params.get("baseline_noise")
1502            self._baseline_noise_std = d_params.get("baseline_noise_std")
1503
1504        self.is_centroid = True
1505        self.data_dict = data_dict
1506        self._mz_exp = data_dict[Labels.mz]
1507        self._abundance = data_dict[Labels.abundance]
1508
1509        if auto_process:
1510            self.process_mass_spec()
is_centroid
data_dict
mz_exp_profile
1546    @property
1547    def mz_exp_profile(self):
1548        """Return the m/z profile of the mass spectrum."""
1549        mz_list = []
1550        for mz in self.mz_exp:
1551            mz_list.append(mz - 0.0000001)
1552            mz_list.append(mz)
1553            mz_list.append(mz + 0.0000001)
1554        return mz_list

Return the m/z profile of the mass spectrum.

abundance_profile
1560    @property
1561    def abundance_profile(self):
1562        """Return the abundance profile of the mass spectrum."""
1563        ab_list = []
1564        for ab in self.abundance:
1565            ab_list.append(0)
1566            ab_list.append(ab)
1567            ab_list.append(0)
1568        return ab_list

Return the abundance profile of the mass spectrum.

tic
1574    @property
1575    def tic(self):
1576        """Return the total ion current of the mass spectrum."""
1577        return sum(self.abundance)

Return the total ion current of the mass spectrum.

def process_mass_spec(self):
1579    def process_mass_spec(self):
1580        """Process the mass spectrum."""
1581        import tqdm
1582
1583        # overwrite process_mass_spec
1584        # mspeak objs are usually added inside the PeaKPicking class
1585        # for profile and freq based data
1586        data_dict = self.data_dict
1587        ion_charge = self.polarity
1588
1589        # Check if resolving power is present
1590        rp_present = True
1591        if not data_dict.get(Labels.rp):
1592            rp_present = False
1593        if rp_present and list(data_dict.get(Labels.rp)) == [None] * len(
1594            data_dict.get(Labels.rp)
1595        ):
1596            rp_present = False
1597
1598        # Check if s2n is present
1599        s2n_present = True
1600        if not data_dict.get(Labels.s2n):
1601            s2n_present = False
1602        if s2n_present and list(data_dict.get(Labels.s2n)) == [None] * len(
1603            data_dict.get(Labels.s2n)
1604        ):
1605            s2n_present = False
1606
1607        # Warning if no s2n data but noise thresholding is set to signal_noise
1608        if (
1609            not s2n_present
1610            and self.parameters.mass_spectrum.noise_threshold_method == "signal_noise"
1611        ):
1612            raise Exception("Signal to Noise data is missing for noise thresholding")
1613
1614        # Pull out abundance data
1615        abun = array(data_dict.get(Labels.abundance)).astype(float)
1616
1617        # Get the threshold for filtering if using minima, relative, or absolute abundance thresholding
1618        abundance_threshold, factor = self.get_threshold(abun)
1619
1620        # Set rp_i and s2n_i to None which will be overwritten if present
1621        rp_i, s2n_i = np.nan, np.nan
1622        for index, mz in enumerate(data_dict.get(Labels.mz)):
1623            if rp_present:
1624                if not data_dict.get(Labels.rp)[index]:
1625                    rp_i = np.nan
1626                else:
1627                    rp_i = float(data_dict.get(Labels.rp)[index])
1628            if s2n_present:
1629                if not data_dict.get(Labels.s2n)[index]:
1630                    s2n_i = np.nan
1631                else:
1632                    s2n_i = float(data_dict.get(Labels.s2n)[index])
1633
1634            # centroid peak does not have start and end peak index pos
1635            massspec_indexes = (index, index, index)
1636
1637            # Add peaks based on the noise thresholding method
1638            if (
1639                self.parameters.mass_spectrum.noise_threshold_method
1640                in ["minima", "relative_abundance", "absolute_abundance"]
1641                and abun[index] / factor >= abundance_threshold
1642            ):
1643                self.add_mspeak(
1644                    ion_charge,
1645                    mz,
1646                    abun[index],
1647                    rp_i,
1648                    s2n_i,
1649                    massspec_indexes,
1650                    ms_parent=self,
1651                )
1652            if (
1653                self.parameters.mass_spectrum.noise_threshold_method == "signal_noise"
1654                and s2n_i >= self.parameters.mass_spectrum.noise_threshold_min_s2n
1655            ):
1656                self.add_mspeak(
1657                    ion_charge,
1658                    mz,
1659                    abun[index],
1660                    rp_i,
1661                    s2n_i,
1662                    massspec_indexes,
1663                    ms_parent=self,
1664                )
1665
1666        self.mspeaks = self._mspeaks
1667        self._dynamic_range = self.max_abundance / self.min_abundance
1668        self._set_nominal_masses_start_final_indexes()
1669
1670        if self.label != Labels.thermo_centroid:
1671            if self.settings.noise_threshold_method == "log":
1672                raise Exception("log noise Not tested for centroid data")
1673                # self._baseline_noise, self._baseline_noise_std = self.run_log_noise_threshold_calc()
1674
1675            else:
1676                self._baseline_noise, self._baseline_noise_std = (
1677                    self.run_noise_threshold_calc()
1678                )
1679
1680        del self.data_dict

Process the mass spectrum.

Inherited Members
MassSpecBase
mspeaks
is_calibrated
has_frequency
calibration_order
calibration_points
calibration_ref_mzs
calibration_meas_mzs
calibration_RMS
calibration_segment
calibration_raw_error_median
calibration_raw_error_stdev
set_indexes
reset_indexes
add_mspeak
reset_cal_therms
clear_molecular_formulas
cal_noise_threshold
parameters
set_parameter_from_json
set_parameter_from_toml
mspeaks_settings
settings
molecular_search_settings
mz_cal_profile
mz_cal
mz_exp
freq_exp_profile
freq_exp_pp
mz_exp_pp
abundance_profile_pp
abundance
freq_exp
resolving_power
signal_to_noise
nominal_mz
get_mz_and_abundance_peaks_tuples
kmd
kendrick_mass
max_mz_exp
min_mz_exp
max_abundance
max_signal_to_noise
most_abundant_mspeak
min_abundance
dynamic_range
baseline_noise
baseline_noise_std
Aterm
Bterm
Cterm
filename
dir_location
sort_by_mz
sort_by_abundance
check_mspeaks_warning
check_mspeaks
remove_assignment_by_index
filter_by_index
filter_by_mz
filter_by_s2n
filter_by_abundance
filter_by_max_resolving_power
filter_by_mean_resolving_power
filter_by_min_resolving_power
filter_by_noise_threshold
find_peaks
change_kendrick_base_all_mspeaks
get_nominal_mz_first_last_indexes
get_masses_count_by_nominal_mass
datapoints_count_by_nominal_mz
get_nominal_mass_indexes
plot_centroid
plot_profile_and_noise_threshold
plot_mz_domain_profile
to_excel
to_hdf
to_csv
to_pandas
to_dataframe
to_json
parameters_json
parameters_toml
corems.mass_spectrum.calc.MassSpectrumCalc.MassSpecCalc
percentage_assigned
percentile_assigned
resolving_power_calc
number_average_molecular_weight
weight_average_molecular_weight
corems.mass_spectrum.calc.PeakPicking.PeakPicking
prepare_peak_picking_data
cut_mz_domain_peak_picking
legacy_cut_mz_domain_peak_picking
extrapolate_axis
extrapolate_axes_for_pp
do_peak_picking
find_minima
linear_fit_calc
calculate_resolving_power
cal_minima
calc_centroid
get_threshold
algebraic_quadratic
find_apex_fit_quadratic
check_prominence
use_the_max
calc_centroid_legacy
corems.mass_spectrum.calc.NoiseCalc.NoiseThresholdCalc
get_noise_threshold
cut_mz_domain_noise
get_noise_average
get_abundance_minima_centroid
run_log_noise_threshold_calc
run_noise_threshold_calc
corems.mass_spectrum.calc.KendrickGroup.KendrickGrouping
mz_odd_even_index_lists
calc_error
populate_kendrick_index_dict_error
populate_kendrick_index_dict_rounding
sort_abundance_kendrick_dict
kendrick_groups_indexes
class MassSpecCentroidLowRes(MassSpecCentroid):
1683class MassSpecCentroidLowRes(MassSpecCentroid):
1684    """A mass spectrum class when the entry point is on low resolution centroid format
1685
1686    Notes
1687    -----
1688    Does not store MSPeak Objs, will iterate over mz, abundance pairs instead
1689
1690    Parameters
1691    ----------
1692    data_dict : dict {string: numpy array float64 )
1693        contains keys [m/z, Abundance, Resolving Power, S/N]
1694    d_params : dict{'str': float, int or str}
1695        contains the instrument settings and processing settings
1696
1697    Attributes
1698    ----------
1699    _processed_tic : float
1700        store processed total ion current
1701    _abundance : ndarray
1702        The abundance values of the mass spectrum.
1703    _mz_exp : ndarray
1704        The m/z values of the mass spectrum.
1705    """
1706
1707    def __init__(self, data_dict, d_params):
1708        self._set_parameters_objects(d_params)
1709        self._mz_exp = array(data_dict.get(Labels.mz))
1710        self._abundance = array(data_dict.get(Labels.abundance))
1711        self._processed_tic = None
1712
1713    def __len__(self):
1714        return len(self.mz_exp)
1715
1716    def __getitem__(self, position):
1717        return (self.mz_exp[position], self.abundance[position])
1718
1719    @property
1720    def mz_exp(self):
1721        """Return the m/z values of the mass spectrum."""
1722        return self._mz_exp
1723
1724    @property
1725    def abundance(self):
1726        """Return the abundance values of the mass spectrum."""
1727        return self._abundance
1728
1729    @property
1730    def processed_tic(self):
1731        """Return the processed total ion current of the mass spectrum."""
1732        return sum(self._processed_tic)
1733
1734    @property
1735    def tic(self):
1736        """Return the total ion current of the mass spectrum."""
1737        if self._processed_tic:
1738            return self._processed_tic
1739        else:
1740            return sum(self.abundance)
1741
1742    @property
1743    def mz_abun_tuples(self):
1744        """Return the m/z and abundance values of the mass spectrum as a list of tuples."""
1745        r = lambda x: (int(round(x[0], 0), int(round(x[1], 0))))
1746
1747        return [r(i) for i in self]
1748
1749    @property
1750    def mz_abun_dict(self):
1751        """Return the m/z and abundance values of the mass spectrum as a dictionary."""
1752        r = lambda x: int(round(x, 0))
1753
1754        return {r(i[0]): r(i[1]) for i in self}

A mass spectrum class when the entry point is on low resolution centroid format

Notes

Does not store MSPeak Objs, will iterate over mz, abundance pairs instead

Parameters
  • data_dict : dict {string (numpy array float64 )): contains keys [m/z, Abundance, Resolving Power, S/N]
  • d_params : dict{'str' (float, int or str}): contains the instrument settings and processing settings
Attributes
  • _processed_tic (float): store processed total ion current
  • _abundance (ndarray): The abundance values of the mass spectrum.
  • _mz_exp (ndarray): The m/z values of the mass spectrum.
MassSpecCentroidLowRes(data_dict, d_params)
1707    def __init__(self, data_dict, d_params):
1708        self._set_parameters_objects(d_params)
1709        self._mz_exp = array(data_dict.get(Labels.mz))
1710        self._abundance = array(data_dict.get(Labels.abundance))
1711        self._processed_tic = None
mz_exp
1719    @property
1720    def mz_exp(self):
1721        """Return the m/z values of the mass spectrum."""
1722        return self._mz_exp

Return the m/z values of the mass spectrum.

abundance
1724    @property
1725    def abundance(self):
1726        """Return the abundance values of the mass spectrum."""
1727        return self._abundance

Return the abundance values of the mass spectrum.

processed_tic
1729    @property
1730    def processed_tic(self):
1731        """Return the processed total ion current of the mass spectrum."""
1732        return sum(self._processed_tic)

Return the processed total ion current of the mass spectrum.

tic
1734    @property
1735    def tic(self):
1736        """Return the total ion current of the mass spectrum."""
1737        if self._processed_tic:
1738            return self._processed_tic
1739        else:
1740            return sum(self.abundance)

Return the total ion current of the mass spectrum.

mz_abun_tuples
1742    @property
1743    def mz_abun_tuples(self):
1744        """Return the m/z and abundance values of the mass spectrum as a list of tuples."""
1745        r = lambda x: (int(round(x[0], 0), int(round(x[1], 0))))
1746
1747        return [r(i) for i in self]

Return the m/z and abundance values of the mass spectrum as a list of tuples.

mz_abun_dict
1749    @property
1750    def mz_abun_dict(self):
1751        """Return the m/z and abundance values of the mass spectrum as a dictionary."""
1752        r = lambda x: int(round(x, 0))
1753
1754        return {r(i[0]): r(i[1]) for i in self}

Return the m/z and abundance values of the mass spectrum as a dictionary.

Inherited Members
MassSpecCentroid
is_centroid
data_dict
mz_exp_profile
abundance_profile
process_mass_spec
MassSpecBase
mspeaks
is_calibrated
has_frequency
calibration_order
calibration_points
calibration_ref_mzs
calibration_meas_mzs
calibration_RMS
calibration_segment
calibration_raw_error_median
calibration_raw_error_stdev
set_indexes
reset_indexes
add_mspeak
reset_cal_therms
clear_molecular_formulas
cal_noise_threshold
parameters
set_parameter_from_json
set_parameter_from_toml
mspeaks_settings
settings
molecular_search_settings
mz_cal_profile
mz_cal
freq_exp_profile
freq_exp_pp
mz_exp_pp
abundance_profile_pp
freq_exp
resolving_power
signal_to_noise
nominal_mz
get_mz_and_abundance_peaks_tuples
kmd
kendrick_mass
max_mz_exp
min_mz_exp
max_abundance
max_signal_to_noise
most_abundant_mspeak
min_abundance
dynamic_range
baseline_noise
baseline_noise_std
Aterm
Bterm
Cterm
filename
dir_location
sort_by_mz
sort_by_abundance
check_mspeaks_warning
check_mspeaks
remove_assignment_by_index
filter_by_index
filter_by_mz
filter_by_s2n
filter_by_abundance
filter_by_max_resolving_power
filter_by_mean_resolving_power
filter_by_min_resolving_power
filter_by_noise_threshold
find_peaks
change_kendrick_base_all_mspeaks
get_nominal_mz_first_last_indexes
get_masses_count_by_nominal_mass
datapoints_count_by_nominal_mz
get_nominal_mass_indexes
plot_centroid
plot_profile_and_noise_threshold
plot_mz_domain_profile
to_excel
to_hdf
to_csv
to_pandas
to_dataframe
to_json
parameters_json
parameters_toml
corems.mass_spectrum.calc.MassSpectrumCalc.MassSpecCalc
percentage_assigned
percentile_assigned
resolving_power_calc
number_average_molecular_weight
weight_average_molecular_weight
corems.mass_spectrum.calc.PeakPicking.PeakPicking
prepare_peak_picking_data
cut_mz_domain_peak_picking
legacy_cut_mz_domain_peak_picking
extrapolate_axis
extrapolate_axes_for_pp
do_peak_picking
find_minima
linear_fit_calc
calculate_resolving_power
cal_minima
calc_centroid
get_threshold
algebraic_quadratic
find_apex_fit_quadratic
check_prominence
use_the_max
calc_centroid_legacy
corems.mass_spectrum.calc.NoiseCalc.NoiseThresholdCalc
get_noise_threshold
cut_mz_domain_noise
get_noise_average
get_abundance_minima_centroid
run_log_noise_threshold_calc
run_noise_threshold_calc
corems.mass_spectrum.calc.KendrickGroup.KendrickGrouping
mz_odd_even_index_lists
calc_error
populate_kendrick_index_dict_error
populate_kendrick_index_dict_rounding
sort_abundance_kendrick_dict
kendrick_groups_indexes