corems.mass_spectrum.calc.MassSpectrumCalc

  1__author__ = "Yuri E. Corilo"
  2__date__ = "Jun 27, 2019"
  3
  4from numpy import power, multiply, sqrt, array, mean
  5from corems.mass_spectrum.calc.NoiseCalc import NoiseThresholdCalc
  6from corems.mass_spectrum.calc.PeakPicking import PeakPicking
  7
  8
  9class MassSpecCalc(PeakPicking, NoiseThresholdCalc):
 10    """Class for Mass Spectrum Calculations
 11
 12    Class including numerical calculations related to mass spectrum class
 13    Inherited PeakPicking and NoiseThresholdCalc ensuring its methods are
 14    available to the instantiated mass spectrum class object
 15
 16    Parameters
 17    -------
 18    mass_spectrum : MassSpectrum
 19        CoreMS mass spectrum object
 20
 21    Attributes
 22    --------
 23    All Attributes are derivative from the MassSpecBase Class
 24
 25    Methods
 26    --------
 27    * check_mspeaks().
 28        Check if the mspeaks attribute is populated
 29    * sort_by_abundance().
 30        Sort the mspeaks by abundance
 31    * percentile_assigned(report_error=False).
 32        Calculate the percentage of assigned peaks
 33    * resolving_power_calc(B, T).
 34        Calculate the resolving power
 35    * number_average_molecular_weight(profile=False).
 36        Calculate the number average molecular weight
 37    * weight_average_molecular_weight(profile=False).
 38        Calculate the weight average molecular weight
 39    """
 40
 41    def percentage_assigned(self, report_error: bool = False, mute_output: bool = False):
 42        """Percentage of peaks which are assigned
 43
 44        Calculates the percentage and relative abundance of assigned peaks in the spectrum.
 45        Includes protection against division by zero with explicit handling of edge cases.
 46
 47        Parameters
 48        -----------
 49        report_error: bool, optional
 50            Report the RMS error of the assigned peaks. Default is False.
 51        mute_output: bool, optional
 52            Override the verbose setting. Default is False.
 53            If True, the function will silence results
 54
 55        Returns
 56        -------
 57        tuple
 58            If report_error is False:
 59                (assigned_count, unassigned_count, total_percent, total_relative_abundance)
 60            If report_error is True:
 61                (assigned_count, unassigned_count, total_percent, total_relative_abundance, rms_error)
 62                where rms_error is None if no assigned peaks exist
 63        
 64        Notes
 65        -----
 66        Edge cases are handled with explicit reporting:
 67        - If no peaks detected: returns (0, 0, 0.0, 0.0[, None]) with message
 68        - If no abundance data: returns (i, j, 0.0, 0.0[, None]) with message
 69        - If no assigned peaks but peaks exist: returns with rms_error=None and explanatory message
 70        """
 71        verbose = self.parameters.mass_spectrum.verbose_processing
 72        assign_abun = 0
 73        not_assign_abun = 0
 74        i = 0
 75        j = 0
 76        if report_error:
 77            error = []
 78        for mspeak in self.sort_by_abundance():
 79            if mspeak.is_assigned:
 80                i += 1
 81                assign_abun += mspeak.abundance
 82                if report_error:
 83                    error.append(mspeak.best_molecular_formula_candidate.mz_error)
 84
 85            else:
 86                j += 1
 87                not_assign_abun += mspeak.abundance
 88
 89        # Protect against division by zero
 90        total_peaks = i + j
 91        total_abundance = assign_abun + not_assign_abun
 92        
 93        # Handle edge cases
 94        if total_peaks == 0:
 95            if verbose and not mute_output:
 96                print("No peaks detected in spectrum")
 97            if report_error:
 98                return i, j, 0.0, 0.0, None
 99            else:
100                return i, j, 0.0, 0.0
101        
102        if total_abundance == 0:
103            if verbose and not mute_output:
104                print("No abundance data detected in spectrum")
105            if report_error:
106                return i, j, 0.0, 0.0, None
107            else:
108                return i, j, 0.0, 0.0
109        
110        total_percent = (i / total_peaks * 100) if total_peaks > 0 else 0.0
111        total_relative_abundance = (assign_abun / total_abundance * 100) if total_abundance > 0 else 0.0
112        
113        if report_error:
114            rms_error = None
115            if i > 0:
116                rms_error = sqrt(mean(array(error) ** 2))
117            if verbose and not mute_output:
118                if i == 0:
119                    print(
120                        "No assigned peaks detected - cannot calculate RMS error. %i unassigned peaks, total = %.2f %%, relative abundance = %.2f %%"
121                        % (j, total_percent, total_relative_abundance)
122                    )
123                else:
124                    print(
125                        "%i assigned peaks and %i unassigned peaks, total  = %.2f %%, relative abundance = %.2f %%, RMS error (best candidate) (ppm) = %.3f"
126                        % (i, j, total_percent, total_relative_abundance, rms_error)
127                    )
128            return i, j, total_percent, total_relative_abundance, rms_error
129
130        else:
131            if verbose and not mute_output:
132                print(
133                    "%i assigned peaks and %i unassigned peaks , total  = %.2f %%, relative abundance = %.2f %%"
134                    % (
135                        i,
136                        j,
137                        total_percent,
138                        total_relative_abundance,
139                    )
140                )
141            return i, j, total_percent, total_relative_abundance
142
143    def percentile_assigned(self, report_error: bool = False, mute_output: bool = False):
144        """Deprecated: Use percentage_assigned() instead.
145
146        This method is deprecated and will be removed in a future version.
147        The function returns a percentage, not a percentile, so the name has been corrected.
148
149        Parameters
150        -----------
151        report_error: bool, optional
152            Report the error of the assigned peaks. Default is False.
153        mute_output: bool, optional
154            Override the verbose setting. Default is False.
155
156        Returns
157        -------
158        tuple
159            Refer to percentage_assigned() for return value details.
160        """
161        import warnings
162        warnings.warn(
163            "percentile_assigned() is deprecated and will be removed in a future version. "
164            "Use percentage_assigned() instead, as the function returns a percentage, not a percentile.",
165            DeprecationWarning,
166            stacklevel=2
167        )
168        return self.percentage_assigned(report_error=report_error, mute_output=mute_output)
169
170    def resolving_power_calc(self, B: float, T: float):
171        """Calculate the theoretical resolving power
172
173        Calls on the MSPeak object function to calculate the resolving power of a peak, this calcs for all peaks in a spectrum.
174
175        Parameters
176        -----------
177        T : float
178            transient time
179        B : float
180            Magnetic Filed Strength (Tesla)
181
182        References
183        ----------
184        1. Marshall et al. (Mass Spectrom Rev. 1998 Jan-Feb;17(1):1-35.)
185                DOI: 10.1002/(SICI)1098-2787(1998)17:1<1::AID-MAS1>3.0.CO;2-K
186
187        """
188
189        self.check_mspeaks()
190        return array([mspeak.resolving_power_calc(B, T) for mspeak in self.mspeaks])
191
192    def _f_to_mz(self):
193        """Ledford equation for converting frequency(Hz) to m/z
194
195        Returns
196        ----------
197        mz_domain : numpy array
198            m/z domain after conversion from frequency
199        """
200        Aterm, Bterm, Cterm = self.Aterm, self.Bterm, self.Cterm
201        # Check if the Bterm of Ledford equation scales with the ICR trap voltage or not then Bterm = Bterm*trap_voltage
202
203        if Cterm == 0:
204            if Bterm == 0:
205                # uncalibrated data
206                mz_domain = Aterm / self.freq_exp_profile
207
208            else:
209                mz_domain = (Aterm / (self.freq_exp_profile)) + (
210                    Bterm / power((self.freq_exp_profile), 2)
211                )
212
213        # @will I need you insight here, not sure what is the inverted ledford equation that Bruker refers to
214        else:
215            mz_domain = (
216                (Aterm / self.freq_exp_profile)
217                + (Bterm / power(self.freq_exp_profile, 2))
218                + Cterm
219            )
220
221        return mz_domain
222
223    def _f_to_mz_bruker(self):
224        """Frequency to m/z conversion (Bruker)
225        Bruker equations for converting frequency (Hz) to m/z,
226        nOmega acquisition is not yet implemented here.
227        However, nOmega should work for commerical Bruker 2xR systems as A Term is automatically defined for 2X or 1X by the instrument
228
229
230        Returns
231        ----------
232        numpy.array(float)
233            m/z domain after conversion from frequency
234        """
235        Aterm, Bterm, Cterm = self.Aterm, self.Bterm, self.Cterm
236        # Check if the Bterm of Ledford equation scales with the ICR trap voltage or not then Bterm = Bterm*trap_voltage
237        if Cterm == 0:
238            if Bterm == 0:
239                # uncalibrated data
240                return Aterm / self.freq_exp_profile
241
242            else:
243                # calc2
244                return Aterm / (self.freq_exp_profile + Bterm)
245
246        # @will I need you insight here, not sure what is the inverted ledford equation that Bruker refers to
247        else:
248            diff = Aterm * Aterm
249
250            # this sign(diff + 4) changes on older aquistion software
251            diff = diff + 4 * Cterm * (self.freq_exp_profile - Bterm)
252            diff = sqrt(diff)
253            diff = -Aterm + diff
254            # calc3
255            return (2 * Cterm) / diff
256            return diff / 2 * (self.freq_exp_profile - Bterm)
257
258    def number_average_molecular_weight(self, profile: bool = False):
259        """Average molecular weight calculation
260
261        Parameters
262        ----------
263        profile : bool, optional
264            is data profile or centroid mode. The default is False (e.g. Centroid data)
265
266        Returns
267        -------
268        float
269            The average molecular weight.
270
271        """
272        # mode is profile or centroid data
273        if profile:
274            a = multiply(self.mz_exp_profile, self.abundance_profile)
275            b = self.abundance_profile
276            return a.sum() / b.sum()
277
278        else:
279            return sum(self.mz_exp * self.abundance) / sum(self.abundance)
280
281    def weight_average_molecular_weight(self, profile: bool = False):
282        """
283        Weighted Average molecular weight calculation
284
285
286        Returns
287        -------
288        float
289            The weight average molecular weight.
290
291        """
292
293        # implement from MassSpectralPeaks objs
294
295        if profile:
296            a = multiply(power(self.mz_exp_profile, 2), self.abundance_profile)
297            b = self.mz_exp_profile * self.abundance_profile
298            return a.sum() / b.sum()
299
300        else:
301            return sum(power(self.mz_exp, 2) * self.abundance) / sum(
302                self.mz_exp * self.abundance
303            )
 10class MassSpecCalc(PeakPicking, NoiseThresholdCalc):
 11    """Class for Mass Spectrum Calculations
 12
 13    Class including numerical calculations related to mass spectrum class
 14    Inherited PeakPicking and NoiseThresholdCalc ensuring its methods are
 15    available to the instantiated mass spectrum class object
 16
 17    Parameters
 18    -------
 19    mass_spectrum : MassSpectrum
 20        CoreMS mass spectrum object
 21
 22    Attributes
 23    --------
 24    All Attributes are derivative from the MassSpecBase Class
 25
 26    Methods
 27    --------
 28    * check_mspeaks().
 29        Check if the mspeaks attribute is populated
 30    * sort_by_abundance().
 31        Sort the mspeaks by abundance
 32    * percentile_assigned(report_error=False).
 33        Calculate the percentage of assigned peaks
 34    * resolving_power_calc(B, T).
 35        Calculate the resolving power
 36    * number_average_molecular_weight(profile=False).
 37        Calculate the number average molecular weight
 38    * weight_average_molecular_weight(profile=False).
 39        Calculate the weight average molecular weight
 40    """
 41
 42    def percentage_assigned(self, report_error: bool = False, mute_output: bool = False):
 43        """Percentage of peaks which are assigned
 44
 45        Calculates the percentage and relative abundance of assigned peaks in the spectrum.
 46        Includes protection against division by zero with explicit handling of edge cases.
 47
 48        Parameters
 49        -----------
 50        report_error: bool, optional
 51            Report the RMS error of the assigned peaks. Default is False.
 52        mute_output: bool, optional
 53            Override the verbose setting. Default is False.
 54            If True, the function will silence results
 55
 56        Returns
 57        -------
 58        tuple
 59            If report_error is False:
 60                (assigned_count, unassigned_count, total_percent, total_relative_abundance)
 61            If report_error is True:
 62                (assigned_count, unassigned_count, total_percent, total_relative_abundance, rms_error)
 63                where rms_error is None if no assigned peaks exist
 64        
 65        Notes
 66        -----
 67        Edge cases are handled with explicit reporting:
 68        - If no peaks detected: returns (0, 0, 0.0, 0.0[, None]) with message
 69        - If no abundance data: returns (i, j, 0.0, 0.0[, None]) with message
 70        - If no assigned peaks but peaks exist: returns with rms_error=None and explanatory message
 71        """
 72        verbose = self.parameters.mass_spectrum.verbose_processing
 73        assign_abun = 0
 74        not_assign_abun = 0
 75        i = 0
 76        j = 0
 77        if report_error:
 78            error = []
 79        for mspeak in self.sort_by_abundance():
 80            if mspeak.is_assigned:
 81                i += 1
 82                assign_abun += mspeak.abundance
 83                if report_error:
 84                    error.append(mspeak.best_molecular_formula_candidate.mz_error)
 85
 86            else:
 87                j += 1
 88                not_assign_abun += mspeak.abundance
 89
 90        # Protect against division by zero
 91        total_peaks = i + j
 92        total_abundance = assign_abun + not_assign_abun
 93        
 94        # Handle edge cases
 95        if total_peaks == 0:
 96            if verbose and not mute_output:
 97                print("No peaks detected in spectrum")
 98            if report_error:
 99                return i, j, 0.0, 0.0, None
100            else:
101                return i, j, 0.0, 0.0
102        
103        if total_abundance == 0:
104            if verbose and not mute_output:
105                print("No abundance data detected in spectrum")
106            if report_error:
107                return i, j, 0.0, 0.0, None
108            else:
109                return i, j, 0.0, 0.0
110        
111        total_percent = (i / total_peaks * 100) if total_peaks > 0 else 0.0
112        total_relative_abundance = (assign_abun / total_abundance * 100) if total_abundance > 0 else 0.0
113        
114        if report_error:
115            rms_error = None
116            if i > 0:
117                rms_error = sqrt(mean(array(error) ** 2))
118            if verbose and not mute_output:
119                if i == 0:
120                    print(
121                        "No assigned peaks detected - cannot calculate RMS error. %i unassigned peaks, total = %.2f %%, relative abundance = %.2f %%"
122                        % (j, total_percent, total_relative_abundance)
123                    )
124                else:
125                    print(
126                        "%i assigned peaks and %i unassigned peaks, total  = %.2f %%, relative abundance = %.2f %%, RMS error (best candidate) (ppm) = %.3f"
127                        % (i, j, total_percent, total_relative_abundance, rms_error)
128                    )
129            return i, j, total_percent, total_relative_abundance, rms_error
130
131        else:
132            if verbose and not mute_output:
133                print(
134                    "%i assigned peaks and %i unassigned peaks , total  = %.2f %%, relative abundance = %.2f %%"
135                    % (
136                        i,
137                        j,
138                        total_percent,
139                        total_relative_abundance,
140                    )
141                )
142            return i, j, total_percent, total_relative_abundance
143
144    def percentile_assigned(self, report_error: bool = False, mute_output: bool = False):
145        """Deprecated: Use percentage_assigned() instead.
146
147        This method is deprecated and will be removed in a future version.
148        The function returns a percentage, not a percentile, so the name has been corrected.
149
150        Parameters
151        -----------
152        report_error: bool, optional
153            Report the error of the assigned peaks. Default is False.
154        mute_output: bool, optional
155            Override the verbose setting. Default is False.
156
157        Returns
158        -------
159        tuple
160            Refer to percentage_assigned() for return value details.
161        """
162        import warnings
163        warnings.warn(
164            "percentile_assigned() is deprecated and will be removed in a future version. "
165            "Use percentage_assigned() instead, as the function returns a percentage, not a percentile.",
166            DeprecationWarning,
167            stacklevel=2
168        )
169        return self.percentage_assigned(report_error=report_error, mute_output=mute_output)
170
171    def resolving_power_calc(self, B: float, T: float):
172        """Calculate the theoretical resolving power
173
174        Calls on the MSPeak object function to calculate the resolving power of a peak, this calcs for all peaks in a spectrum.
175
176        Parameters
177        -----------
178        T : float
179            transient time
180        B : float
181            Magnetic Filed Strength (Tesla)
182
183        References
184        ----------
185        1. Marshall et al. (Mass Spectrom Rev. 1998 Jan-Feb;17(1):1-35.)
186                DOI: 10.1002/(SICI)1098-2787(1998)17:1<1::AID-MAS1>3.0.CO;2-K
187
188        """
189
190        self.check_mspeaks()
191        return array([mspeak.resolving_power_calc(B, T) for mspeak in self.mspeaks])
192
193    def _f_to_mz(self):
194        """Ledford equation for converting frequency(Hz) to m/z
195
196        Returns
197        ----------
198        mz_domain : numpy array
199            m/z domain after conversion from frequency
200        """
201        Aterm, Bterm, Cterm = self.Aterm, self.Bterm, self.Cterm
202        # Check if the Bterm of Ledford equation scales with the ICR trap voltage or not then Bterm = Bterm*trap_voltage
203
204        if Cterm == 0:
205            if Bterm == 0:
206                # uncalibrated data
207                mz_domain = Aterm / self.freq_exp_profile
208
209            else:
210                mz_domain = (Aterm / (self.freq_exp_profile)) + (
211                    Bterm / power((self.freq_exp_profile), 2)
212                )
213
214        # @will I need you insight here, not sure what is the inverted ledford equation that Bruker refers to
215        else:
216            mz_domain = (
217                (Aterm / self.freq_exp_profile)
218                + (Bterm / power(self.freq_exp_profile, 2))
219                + Cterm
220            )
221
222        return mz_domain
223
224    def _f_to_mz_bruker(self):
225        """Frequency to m/z conversion (Bruker)
226        Bruker equations for converting frequency (Hz) to m/z,
227        nOmega acquisition is not yet implemented here.
228        However, nOmega should work for commerical Bruker 2xR systems as A Term is automatically defined for 2X or 1X by the instrument
229
230
231        Returns
232        ----------
233        numpy.array(float)
234            m/z domain after conversion from frequency
235        """
236        Aterm, Bterm, Cterm = self.Aterm, self.Bterm, self.Cterm
237        # Check if the Bterm of Ledford equation scales with the ICR trap voltage or not then Bterm = Bterm*trap_voltage
238        if Cterm == 0:
239            if Bterm == 0:
240                # uncalibrated data
241                return Aterm / self.freq_exp_profile
242
243            else:
244                # calc2
245                return Aterm / (self.freq_exp_profile + Bterm)
246
247        # @will I need you insight here, not sure what is the inverted ledford equation that Bruker refers to
248        else:
249            diff = Aterm * Aterm
250
251            # this sign(diff + 4) changes on older aquistion software
252            diff = diff + 4 * Cterm * (self.freq_exp_profile - Bterm)
253            diff = sqrt(diff)
254            diff = -Aterm + diff
255            # calc3
256            return (2 * Cterm) / diff
257            return diff / 2 * (self.freq_exp_profile - Bterm)
258
259    def number_average_molecular_weight(self, profile: bool = False):
260        """Average molecular weight calculation
261
262        Parameters
263        ----------
264        profile : bool, optional
265            is data profile or centroid mode. The default is False (e.g. Centroid data)
266
267        Returns
268        -------
269        float
270            The average molecular weight.
271
272        """
273        # mode is profile or centroid data
274        if profile:
275            a = multiply(self.mz_exp_profile, self.abundance_profile)
276            b = self.abundance_profile
277            return a.sum() / b.sum()
278
279        else:
280            return sum(self.mz_exp * self.abundance) / sum(self.abundance)
281
282    def weight_average_molecular_weight(self, profile: bool = False):
283        """
284        Weighted Average molecular weight calculation
285
286
287        Returns
288        -------
289        float
290            The weight average molecular weight.
291
292        """
293
294        # implement from MassSpectralPeaks objs
295
296        if profile:
297            a = multiply(power(self.mz_exp_profile, 2), self.abundance_profile)
298            b = self.mz_exp_profile * self.abundance_profile
299            return a.sum() / b.sum()
300
301        else:
302            return sum(power(self.mz_exp, 2) * self.abundance) / sum(
303                self.mz_exp * self.abundance
304            )

Class for Mass Spectrum Calculations

Class including numerical calculations related to mass spectrum class Inherited PeakPicking and NoiseThresholdCalc ensuring its methods are available to the instantiated mass spectrum class object

Parameters
  • mass_spectrum (MassSpectrum): CoreMS mass spectrum object
Attributes
  • All Attributes are derivative from the MassSpecBase Class
Methods
  • check_mspeaks(). Check if the mspeaks attribute is populated
  • sort_by_abundance(). Sort the mspeaks by abundance
  • percentile_assigned(report_error=False). Calculate the percentage of assigned peaks
  • resolving_power_calc(B, T). Calculate the resolving power
  • number_average_molecular_weight(profile=False). Calculate the number average molecular weight
  • weight_average_molecular_weight(profile=False). Calculate the weight average molecular weight
def percentage_assigned(self, report_error: bool = False, mute_output: bool = False):
 42    def percentage_assigned(self, report_error: bool = False, mute_output: bool = False):
 43        """Percentage of peaks which are assigned
 44
 45        Calculates the percentage and relative abundance of assigned peaks in the spectrum.
 46        Includes protection against division by zero with explicit handling of edge cases.
 47
 48        Parameters
 49        -----------
 50        report_error: bool, optional
 51            Report the RMS error of the assigned peaks. Default is False.
 52        mute_output: bool, optional
 53            Override the verbose setting. Default is False.
 54            If True, the function will silence results
 55
 56        Returns
 57        -------
 58        tuple
 59            If report_error is False:
 60                (assigned_count, unassigned_count, total_percent, total_relative_abundance)
 61            If report_error is True:
 62                (assigned_count, unassigned_count, total_percent, total_relative_abundance, rms_error)
 63                where rms_error is None if no assigned peaks exist
 64        
 65        Notes
 66        -----
 67        Edge cases are handled with explicit reporting:
 68        - If no peaks detected: returns (0, 0, 0.0, 0.0[, None]) with message
 69        - If no abundance data: returns (i, j, 0.0, 0.0[, None]) with message
 70        - If no assigned peaks but peaks exist: returns with rms_error=None and explanatory message
 71        """
 72        verbose = self.parameters.mass_spectrum.verbose_processing
 73        assign_abun = 0
 74        not_assign_abun = 0
 75        i = 0
 76        j = 0
 77        if report_error:
 78            error = []
 79        for mspeak in self.sort_by_abundance():
 80            if mspeak.is_assigned:
 81                i += 1
 82                assign_abun += mspeak.abundance
 83                if report_error:
 84                    error.append(mspeak.best_molecular_formula_candidate.mz_error)
 85
 86            else:
 87                j += 1
 88                not_assign_abun += mspeak.abundance
 89
 90        # Protect against division by zero
 91        total_peaks = i + j
 92        total_abundance = assign_abun + not_assign_abun
 93        
 94        # Handle edge cases
 95        if total_peaks == 0:
 96            if verbose and not mute_output:
 97                print("No peaks detected in spectrum")
 98            if report_error:
 99                return i, j, 0.0, 0.0, None
100            else:
101                return i, j, 0.0, 0.0
102        
103        if total_abundance == 0:
104            if verbose and not mute_output:
105                print("No abundance data detected in spectrum")
106            if report_error:
107                return i, j, 0.0, 0.0, None
108            else:
109                return i, j, 0.0, 0.0
110        
111        total_percent = (i / total_peaks * 100) if total_peaks > 0 else 0.0
112        total_relative_abundance = (assign_abun / total_abundance * 100) if total_abundance > 0 else 0.0
113        
114        if report_error:
115            rms_error = None
116            if i > 0:
117                rms_error = sqrt(mean(array(error) ** 2))
118            if verbose and not mute_output:
119                if i == 0:
120                    print(
121                        "No assigned peaks detected - cannot calculate RMS error. %i unassigned peaks, total = %.2f %%, relative abundance = %.2f %%"
122                        % (j, total_percent, total_relative_abundance)
123                    )
124                else:
125                    print(
126                        "%i assigned peaks and %i unassigned peaks, total  = %.2f %%, relative abundance = %.2f %%, RMS error (best candidate) (ppm) = %.3f"
127                        % (i, j, total_percent, total_relative_abundance, rms_error)
128                    )
129            return i, j, total_percent, total_relative_abundance, rms_error
130
131        else:
132            if verbose and not mute_output:
133                print(
134                    "%i assigned peaks and %i unassigned peaks , total  = %.2f %%, relative abundance = %.2f %%"
135                    % (
136                        i,
137                        j,
138                        total_percent,
139                        total_relative_abundance,
140                    )
141                )
142            return i, j, total_percent, total_relative_abundance

Percentage of peaks which are assigned

Calculates the percentage and relative abundance of assigned peaks in the spectrum. Includes protection against division by zero with explicit handling of edge cases.

Parameters
  • report_error (bool, optional): Report the RMS error of the assigned peaks. Default is False.
  • mute_output (bool, optional): Override the verbose setting. Default is False. If True, the function will silence results
Returns
  • tuple: If report_error is False: (assigned_count, unassigned_count, total_percent, total_relative_abundance) If report_error is True: (assigned_count, unassigned_count, total_percent, total_relative_abundance, rms_error) where rms_error is None if no assigned peaks exist
Notes

Edge cases are handled with explicit reporting:

  • If no peaks detected: returns (0, 0, 0.0, 0.0[, None]) with message
  • If no abundance data: returns (i, j, 0.0, 0.0[, None]) with message
  • If no assigned peaks but peaks exist: returns with rms_error=None and explanatory message
def percentile_assigned(self, report_error: bool = False, mute_output: bool = False):
144    def percentile_assigned(self, report_error: bool = False, mute_output: bool = False):
145        """Deprecated: Use percentage_assigned() instead.
146
147        This method is deprecated and will be removed in a future version.
148        The function returns a percentage, not a percentile, so the name has been corrected.
149
150        Parameters
151        -----------
152        report_error: bool, optional
153            Report the error of the assigned peaks. Default is False.
154        mute_output: bool, optional
155            Override the verbose setting. Default is False.
156
157        Returns
158        -------
159        tuple
160            Refer to percentage_assigned() for return value details.
161        """
162        import warnings
163        warnings.warn(
164            "percentile_assigned() is deprecated and will be removed in a future version. "
165            "Use percentage_assigned() instead, as the function returns a percentage, not a percentile.",
166            DeprecationWarning,
167            stacklevel=2
168        )
169        return self.percentage_assigned(report_error=report_error, mute_output=mute_output)

Deprecated: Use percentage_assigned() instead.

This method is deprecated and will be removed in a future version. The function returns a percentage, not a percentile, so the name has been corrected.

Parameters
  • report_error (bool, optional): Report the error of the assigned peaks. Default is False.
  • mute_output (bool, optional): Override the verbose setting. Default is False.
Returns
  • tuple: Refer to percentage_assigned() for return value details.
def resolving_power_calc(self, B: float, T: float):
171    def resolving_power_calc(self, B: float, T: float):
172        """Calculate the theoretical resolving power
173
174        Calls on the MSPeak object function to calculate the resolving power of a peak, this calcs for all peaks in a spectrum.
175
176        Parameters
177        -----------
178        T : float
179            transient time
180        B : float
181            Magnetic Filed Strength (Tesla)
182
183        References
184        ----------
185        1. Marshall et al. (Mass Spectrom Rev. 1998 Jan-Feb;17(1):1-35.)
186                DOI: 10.1002/(SICI)1098-2787(1998)17:1<1::AID-MAS1>3.0.CO;2-K
187
188        """
189
190        self.check_mspeaks()
191        return array([mspeak.resolving_power_calc(B, T) for mspeak in self.mspeaks])

Calculate the theoretical resolving power

Calls on the MSPeak object function to calculate the resolving power of a peak, this calcs for all peaks in a spectrum.

Parameters
  • T (float): transient time
  • B (float): Magnetic Filed Strength (Tesla)
References
  1. Marshall et al. (Mass Spectrom Rev. 1998 Jan-Feb;17(1):1-35.) DOI: 10.1002/(SICI)1098-2787(1998)17:1<1::AID-MAS1>3.0.CO;2-K
def number_average_molecular_weight(self, profile: bool = False):
259    def number_average_molecular_weight(self, profile: bool = False):
260        """Average molecular weight calculation
261
262        Parameters
263        ----------
264        profile : bool, optional
265            is data profile or centroid mode. The default is False (e.g. Centroid data)
266
267        Returns
268        -------
269        float
270            The average molecular weight.
271
272        """
273        # mode is profile or centroid data
274        if profile:
275            a = multiply(self.mz_exp_profile, self.abundance_profile)
276            b = self.abundance_profile
277            return a.sum() / b.sum()
278
279        else:
280            return sum(self.mz_exp * self.abundance) / sum(self.abundance)

Average molecular weight calculation

Parameters
  • profile (bool, optional): is data profile or centroid mode. The default is False (e.g. Centroid data)
Returns
  • float: The average molecular weight.
def weight_average_molecular_weight(self, profile: bool = False):
282    def weight_average_molecular_weight(self, profile: bool = False):
283        """
284        Weighted Average molecular weight calculation
285
286
287        Returns
288        -------
289        float
290            The weight average molecular weight.
291
292        """
293
294        # implement from MassSpectralPeaks objs
295
296        if profile:
297            a = multiply(power(self.mz_exp_profile, 2), self.abundance_profile)
298            b = self.mz_exp_profile * self.abundance_profile
299            return a.sum() / b.sum()
300
301        else:
302            return sum(power(self.mz_exp, 2) * self.abundance) / sum(
303                self.mz_exp * self.abundance
304            )

Weighted Average molecular weight calculation

Returns
  • float: The weight average molecular weight.