corems.mass_spectrum.calc.AutoRecalibration
Created on March 23 2023
@author: Will Kew
Modules for automatic mass internal recalibration
1# -*- coding: utf-8 -*- 2""" 3Created on March 23 2023 4 5@author: Will Kew 6 7Modules for automatic mass internal recalibration 8""" 9 10from lmfit.models import GaussianModel 11import seaborn as sns 12import pandas as pd 13import numpy as np 14import matplotlib.pyplot as plt 15from corems.molecular_id.search.molecularFormulaSearch import SearchMolecularFormulas 16import copy 17 18 19class HighResRecalibration: 20 """ 21 This class is designed for high resolution (FTICR, Orbitrap) data of complex mixture, e.g. Organic matter 22 23 The tool first does a broad mass range search for the most commonly expected ion type (i.e. CHO, deprotonated - for negative ESI) 24 And then the assigned data mass error distribution is searched, with a gaussian fit to the most prominent range. 25 This tool works when the data are of sufficient quality, and not outwith the typical expected range of the mass analyzer 26 It presumes the mean error is out by 0-several ppm, but that the spread of error values is modest (<2ppm) 27 28 Parameters 29 ---------- 30 mass_spectrum : MassSpectrum 31 CoreMS mass spectrum object 32 plot : bool, optional 33 Whether to plot the error distribution. The default is False. 34 docker : bool, optional 35 Whether to use the docker database. The default is True. If not, it uses a dynamically generated sqlite database. 36 ppmFWHMprior : float, optional 37 The FWHM of the prior distribution (ppm). The default is 3. 38 ppmRangeprior : float, optional 39 The range of the prior distribution (ppm). The default is 15. 40 41 Methods 42 -------- 43 * determine_error_boundaries(). Determine the error boundaries for recalibration space. 44 45 Notes 46 ----- 47 This initialisation function creates a copy of the MassSpectrum object to avoid over-writing assignments. 48 Possible future task is to make the base class copyable. 49 50 """ 51 52 def __init__( 53 self, 54 mass_spectrum, 55 plot: bool = False, 56 docker: bool = True, 57 ppmFWHMprior: float = 3, 58 ppmRangeprior: float = 15, 59 ): 60 self.mass_spectrum = copy.deepcopy(mass_spectrum) 61 self.plot = plot 62 self.docker = docker 63 self.ppmFWHMprior = ppmFWHMprior 64 self.ppmRangeprior = ppmRangeprior 65 66 def set_uncal_settings(self): 67 """Set uncalibrated formula search settings 68 69 This function serves the uncalibrated data (hence broad error tolerance) 70 It only allows CHO formula in deprotonated ion type- as most common for SRFA ESI negative mode 71 72 This will not work for positive mode data, or for other ion types, or other expected elemental searches. 73 74 """ 75 # TODO rework this. 76 77 if self.docker: 78 self.mass_spectrum.molecular_search_settings.url_database = "postgresql+psycopg2://coremsappdb:coremsapppnnl@localhost:5432/coremsapp" 79 else: 80 self.mass_spectrum.molecular_search_settings.url_database = None 81 self.mass_spectrum.molecular_search_settings.error_method = None 82 self.mass_spectrum.molecular_search_settings.score_method = "prob_score" 83 84 self.mass_spectrum.molecular_search_settings.min_ppm_error = ( 85 -1 * self.ppmRangeprior / 2 86 ) # -7.5 87 self.mass_spectrum.molecular_search_settings.max_ppm_error = ( 88 self.ppmRangeprior / 2 89 ) # 7.5 90 91 self.mass_spectrum.molecular_search_settings.min_dbe = 0 92 self.mass_spectrum.molecular_search_settings.max_dbe = 50 93 94 self.mass_spectrum.molecular_search_settings.use_isotopologue_filter = False 95 self.mass_spectrum.molecular_search_settings.min_abun_error = -30 96 self.mass_spectrum.molecular_search_settings.max_abun_error = 70 97 98 self.mass_spectrum.molecular_search_settings.use_min_peaks_filter = True 99 self.mass_spectrum.molecular_search_settings.min_peaks_per_class = ( 100 10 # default is 15 101 ) 102 103 self.mass_spectrum.molecular_search_settings.usedAtoms["C"] = (1, 90) 104 self.mass_spectrum.molecular_search_settings.usedAtoms["H"] = (4, 200) 105 self.mass_spectrum.molecular_search_settings.usedAtoms["O"] = (1, 23) 106 self.mass_spectrum.molecular_search_settings.usedAtoms["N"] = (0, 0) 107 self.mass_spectrum.molecular_search_settings.usedAtoms["S"] = (0, 0) 108 self.mass_spectrum.molecular_search_settings.usedAtoms["P"] = (0, 0) 109 110 self.mass_spectrum.molecular_search_settings.isProtonated = True 111 self.mass_spectrum.molecular_search_settings.isRadical = False 112 self.mass_spectrum.molecular_search_settings.isAdduct = False 113 114 def positive_search_settings(self): 115 """Set the positive mode elemental search settings""" 116 self.mass_spectrum.molecular_search_settings.isProtonated = False 117 self.mass_spectrum.molecular_search_settings.isAdduct = True 118 self.mass_spectrum.molecular_search_settings.adduct_atoms_pos = ["Na"] 119 120 @staticmethod 121 def get_error_range( 122 errors: list, ppmFWHMprior: float = 3, plot_logic: bool = False 123 ): 124 """Get the error range from the error distribution 125 126 Using lmfit and seaborn kdeplot to extract the error range from the error distribution of assigned species. 127 128 Parameters 129 ---------- 130 errors : list 131 list of the errors of the assigned species (ppm) 132 ppmFWHMprior : float, optional 133 The FWHM of the prior distribution (ppm). The default is 3. 134 plot_logic : bool, optional 135 Whether to plot the error distribution. The default is False. 136 137 Returns 138 ------- 139 mean_error : float 140 mean mass error of the Gaussian distribution (ppm) 141 fwhm_error : float 142 full width half max of the gaussian error distribution (ppm) 143 ppm_thresh : list 144 recommended thresholds for the recalibration parameters (ppm) 145 Consists of [mean_error-fwhm_error,mean_error+fwhm_error] 146 147 """ 148 # Create an isolated figure so stale lines from other tests/plots 149 # do not pollute get_lines()[0] (matplotlib global state issue) 150 fig, ax = plt.subplots() 151 kde = sns.kdeplot(errors, ax=ax) 152 153 kde_data = ax.get_lines()[0].get_data() 154 155 tmpdf = pd.Series(index=kde_data[0], data=kde_data[1]) 156 kde_apex_ppm = tmpdf.idxmax() 157 kde_apex_val = tmpdf.max() 158 159 plt.close(fig) 160 plt.close("all") 161 162 lmmodel = GaussianModel() 163 lmpars = lmmodel.guess(kde_data[1], x=kde_data[0]) 164 lmpars["sigma"].value = 2.3548 / ppmFWHMprior 165 lmpars["center"].value = kde_apex_ppm 166 lmpars["amplitude"].value = kde_apex_val 167 lmout = lmmodel.fit(kde_data[1], lmpars, x=kde_data[0]) 168 169 if plot_logic: 170 fig, ax = plt.subplots(figsize=(8, 4)) 171 lmout.plot_fit( 172 ax=ax, data_kws={"color": "tab:blue"}, fit_kws={"color": "tab:red"} 173 ) 174 ax.set_xlabel("$m/z$ Error (ppm)") 175 ax.set_ylabel("Density") 176 plt.legend(facecolor="white", framealpha=0) 177 178 mean_error = lmout.best_values["center"] 179 std_error = lmout.best_values["sigma"] 180 # FWHM from Sigma = approx. 2.355*sigma 181 # fwhm_error = 2*np.sqrt(2*np.log(2))*std_error 182 fwhm_error = std_error * np.sqrt(8 * np.log(2)) 183 184 ppm_thresh = [mean_error - fwhm_error, mean_error + fwhm_error] 185 return mean_error, fwhm_error, ppm_thresh 186 187 def determine_error_boundaries(self): 188 """Determine the error boundaries for recalibration space 189 190 This is the main function in this class 191 Sets the Molecular Formulas search settings, performs the initial formula search 192 Converts the data to a dataframe, and gets the error range 193 Returns the error thresholds. 194 195 Returns 196 ------- 197 mean_error : float 198 mean mass error of the Gaussian distribution (ppm) 199 fwhm_error : float 200 full width half max of the gaussian error distribution (ppm) 201 ppm_thresh : list 202 recommended thresholds for the recalibration parameters (ppm) 203 Consists of [mean_error-fwhm_error,mean_error+fwhm_error] 204 """ 205 206 # Set the search settings 207 self.set_uncal_settings() 208 209 # Set the positive mode settings 210 # To do - have user defineable settings? 211 if self.mass_spectrum.polarity == 1: 212 self.positive_search_settings() 213 214 # Search MFs 215 SearchMolecularFormulas( 216 self.mass_spectrum, first_hit=True 217 ).run_worker_mass_spectrum() 218 219 # Exporting to a DF is ~30x slower than just getting the errors, so this is fast. 220 errors = [] 221 for mspeak in self.mass_spectrum.mspeaks: 222 if len(mspeak.molecular_formulas) > 0: 223 errors.append(mspeak.best_molecular_formula_candidate.mz_error) 224 225 # If there are NO assignments, it'll fail on the next step. Need to check for that 226 nassign = len(errors) 227 # Here we say at least 5 features assigned are needed - it probably should be greater, but we are just trying to stop it breaking the code 228 # We want to make sure the spectrum is capture in the database though - so we return the stats entries (0 assignments) and the number of assignments 229 if nassign < 5: 230 if self.mass_spectrum.parameters.mass_spectrum.verbose_processing: 231 print("fewer than 5 peaks assigned, cannot determine error range") 232 return np.nan, np.nan, [np.nan, np.nan] 233 else: 234 mean_error, fwhm_error, ppm_thresh = self.get_error_range( 235 errors, self.ppmFWHMprior, self.plot 236 ) 237 return mean_error, fwhm_error, ppm_thresh
20class HighResRecalibration: 21 """ 22 This class is designed for high resolution (FTICR, Orbitrap) data of complex mixture, e.g. Organic matter 23 24 The tool first does a broad mass range search for the most commonly expected ion type (i.e. CHO, deprotonated - for negative ESI) 25 And then the assigned data mass error distribution is searched, with a gaussian fit to the most prominent range. 26 This tool works when the data are of sufficient quality, and not outwith the typical expected range of the mass analyzer 27 It presumes the mean error is out by 0-several ppm, but that the spread of error values is modest (<2ppm) 28 29 Parameters 30 ---------- 31 mass_spectrum : MassSpectrum 32 CoreMS mass spectrum object 33 plot : bool, optional 34 Whether to plot the error distribution. The default is False. 35 docker : bool, optional 36 Whether to use the docker database. The default is True. If not, it uses a dynamically generated sqlite database. 37 ppmFWHMprior : float, optional 38 The FWHM of the prior distribution (ppm). The default is 3. 39 ppmRangeprior : float, optional 40 The range of the prior distribution (ppm). The default is 15. 41 42 Methods 43 -------- 44 * determine_error_boundaries(). Determine the error boundaries for recalibration space. 45 46 Notes 47 ----- 48 This initialisation function creates a copy of the MassSpectrum object to avoid over-writing assignments. 49 Possible future task is to make the base class copyable. 50 51 """ 52 53 def __init__( 54 self, 55 mass_spectrum, 56 plot: bool = False, 57 docker: bool = True, 58 ppmFWHMprior: float = 3, 59 ppmRangeprior: float = 15, 60 ): 61 self.mass_spectrum = copy.deepcopy(mass_spectrum) 62 self.plot = plot 63 self.docker = docker 64 self.ppmFWHMprior = ppmFWHMprior 65 self.ppmRangeprior = ppmRangeprior 66 67 def set_uncal_settings(self): 68 """Set uncalibrated formula search settings 69 70 This function serves the uncalibrated data (hence broad error tolerance) 71 It only allows CHO formula in deprotonated ion type- as most common for SRFA ESI negative mode 72 73 This will not work for positive mode data, or for other ion types, or other expected elemental searches. 74 75 """ 76 # TODO rework this. 77 78 if self.docker: 79 self.mass_spectrum.molecular_search_settings.url_database = "postgresql+psycopg2://coremsappdb:coremsapppnnl@localhost:5432/coremsapp" 80 else: 81 self.mass_spectrum.molecular_search_settings.url_database = None 82 self.mass_spectrum.molecular_search_settings.error_method = None 83 self.mass_spectrum.molecular_search_settings.score_method = "prob_score" 84 85 self.mass_spectrum.molecular_search_settings.min_ppm_error = ( 86 -1 * self.ppmRangeprior / 2 87 ) # -7.5 88 self.mass_spectrum.molecular_search_settings.max_ppm_error = ( 89 self.ppmRangeprior / 2 90 ) # 7.5 91 92 self.mass_spectrum.molecular_search_settings.min_dbe = 0 93 self.mass_spectrum.molecular_search_settings.max_dbe = 50 94 95 self.mass_spectrum.molecular_search_settings.use_isotopologue_filter = False 96 self.mass_spectrum.molecular_search_settings.min_abun_error = -30 97 self.mass_spectrum.molecular_search_settings.max_abun_error = 70 98 99 self.mass_spectrum.molecular_search_settings.use_min_peaks_filter = True 100 self.mass_spectrum.molecular_search_settings.min_peaks_per_class = ( 101 10 # default is 15 102 ) 103 104 self.mass_spectrum.molecular_search_settings.usedAtoms["C"] = (1, 90) 105 self.mass_spectrum.molecular_search_settings.usedAtoms["H"] = (4, 200) 106 self.mass_spectrum.molecular_search_settings.usedAtoms["O"] = (1, 23) 107 self.mass_spectrum.molecular_search_settings.usedAtoms["N"] = (0, 0) 108 self.mass_spectrum.molecular_search_settings.usedAtoms["S"] = (0, 0) 109 self.mass_spectrum.molecular_search_settings.usedAtoms["P"] = (0, 0) 110 111 self.mass_spectrum.molecular_search_settings.isProtonated = True 112 self.mass_spectrum.molecular_search_settings.isRadical = False 113 self.mass_spectrum.molecular_search_settings.isAdduct = False 114 115 def positive_search_settings(self): 116 """Set the positive mode elemental search settings""" 117 self.mass_spectrum.molecular_search_settings.isProtonated = False 118 self.mass_spectrum.molecular_search_settings.isAdduct = True 119 self.mass_spectrum.molecular_search_settings.adduct_atoms_pos = ["Na"] 120 121 @staticmethod 122 def get_error_range( 123 errors: list, ppmFWHMprior: float = 3, plot_logic: bool = False 124 ): 125 """Get the error range from the error distribution 126 127 Using lmfit and seaborn kdeplot to extract the error range from the error distribution of assigned species. 128 129 Parameters 130 ---------- 131 errors : list 132 list of the errors of the assigned species (ppm) 133 ppmFWHMprior : float, optional 134 The FWHM of the prior distribution (ppm). The default is 3. 135 plot_logic : bool, optional 136 Whether to plot the error distribution. The default is False. 137 138 Returns 139 ------- 140 mean_error : float 141 mean mass error of the Gaussian distribution (ppm) 142 fwhm_error : float 143 full width half max of the gaussian error distribution (ppm) 144 ppm_thresh : list 145 recommended thresholds for the recalibration parameters (ppm) 146 Consists of [mean_error-fwhm_error,mean_error+fwhm_error] 147 148 """ 149 # Create an isolated figure so stale lines from other tests/plots 150 # do not pollute get_lines()[0] (matplotlib global state issue) 151 fig, ax = plt.subplots() 152 kde = sns.kdeplot(errors, ax=ax) 153 154 kde_data = ax.get_lines()[0].get_data() 155 156 tmpdf = pd.Series(index=kde_data[0], data=kde_data[1]) 157 kde_apex_ppm = tmpdf.idxmax() 158 kde_apex_val = tmpdf.max() 159 160 plt.close(fig) 161 plt.close("all") 162 163 lmmodel = GaussianModel() 164 lmpars = lmmodel.guess(kde_data[1], x=kde_data[0]) 165 lmpars["sigma"].value = 2.3548 / ppmFWHMprior 166 lmpars["center"].value = kde_apex_ppm 167 lmpars["amplitude"].value = kde_apex_val 168 lmout = lmmodel.fit(kde_data[1], lmpars, x=kde_data[0]) 169 170 if plot_logic: 171 fig, ax = plt.subplots(figsize=(8, 4)) 172 lmout.plot_fit( 173 ax=ax, data_kws={"color": "tab:blue"}, fit_kws={"color": "tab:red"} 174 ) 175 ax.set_xlabel("$m/z$ Error (ppm)") 176 ax.set_ylabel("Density") 177 plt.legend(facecolor="white", framealpha=0) 178 179 mean_error = lmout.best_values["center"] 180 std_error = lmout.best_values["sigma"] 181 # FWHM from Sigma = approx. 2.355*sigma 182 # fwhm_error = 2*np.sqrt(2*np.log(2))*std_error 183 fwhm_error = std_error * np.sqrt(8 * np.log(2)) 184 185 ppm_thresh = [mean_error - fwhm_error, mean_error + fwhm_error] 186 return mean_error, fwhm_error, ppm_thresh 187 188 def determine_error_boundaries(self): 189 """Determine the error boundaries for recalibration space 190 191 This is the main function in this class 192 Sets the Molecular Formulas search settings, performs the initial formula search 193 Converts the data to a dataframe, and gets the error range 194 Returns the error thresholds. 195 196 Returns 197 ------- 198 mean_error : float 199 mean mass error of the Gaussian distribution (ppm) 200 fwhm_error : float 201 full width half max of the gaussian error distribution (ppm) 202 ppm_thresh : list 203 recommended thresholds for the recalibration parameters (ppm) 204 Consists of [mean_error-fwhm_error,mean_error+fwhm_error] 205 """ 206 207 # Set the search settings 208 self.set_uncal_settings() 209 210 # Set the positive mode settings 211 # To do - have user defineable settings? 212 if self.mass_spectrum.polarity == 1: 213 self.positive_search_settings() 214 215 # Search MFs 216 SearchMolecularFormulas( 217 self.mass_spectrum, first_hit=True 218 ).run_worker_mass_spectrum() 219 220 # Exporting to a DF is ~30x slower than just getting the errors, so this is fast. 221 errors = [] 222 for mspeak in self.mass_spectrum.mspeaks: 223 if len(mspeak.molecular_formulas) > 0: 224 errors.append(mspeak.best_molecular_formula_candidate.mz_error) 225 226 # If there are NO assignments, it'll fail on the next step. Need to check for that 227 nassign = len(errors) 228 # Here we say at least 5 features assigned are needed - it probably should be greater, but we are just trying to stop it breaking the code 229 # We want to make sure the spectrum is capture in the database though - so we return the stats entries (0 assignments) and the number of assignments 230 if nassign < 5: 231 if self.mass_spectrum.parameters.mass_spectrum.verbose_processing: 232 print("fewer than 5 peaks assigned, cannot determine error range") 233 return np.nan, np.nan, [np.nan, np.nan] 234 else: 235 mean_error, fwhm_error, ppm_thresh = self.get_error_range( 236 errors, self.ppmFWHMprior, self.plot 237 ) 238 return mean_error, fwhm_error, ppm_thresh
This class is designed for high resolution (FTICR, Orbitrap) data of complex mixture, e.g. Organic matter
The tool first does a broad mass range search for the most commonly expected ion type (i.e. CHO, deprotonated - for negative ESI) And then the assigned data mass error distribution is searched, with a gaussian fit to the most prominent range. This tool works when the data are of sufficient quality, and not outwith the typical expected range of the mass analyzer It presumes the mean error is out by 0-several ppm, but that the spread of error values is modest (<2ppm)
Parameters
- mass_spectrum (MassSpectrum): CoreMS mass spectrum object
- plot (bool, optional): Whether to plot the error distribution. The default is False.
- docker (bool, optional): Whether to use the docker database. The default is True. If not, it uses a dynamically generated sqlite database.
- ppmFWHMprior (float, optional): The FWHM of the prior distribution (ppm). The default is 3.
- ppmRangeprior (float, optional): The range of the prior distribution (ppm). The default is 15.
Methods
- determine_error_boundaries(). Determine the error boundaries for recalibration space.
Notes
This initialisation function creates a copy of the MassSpectrum object to avoid over-writing assignments. Possible future task is to make the base class copyable.
53 def __init__( 54 self, 55 mass_spectrum, 56 plot: bool = False, 57 docker: bool = True, 58 ppmFWHMprior: float = 3, 59 ppmRangeprior: float = 15, 60 ): 61 self.mass_spectrum = copy.deepcopy(mass_spectrum) 62 self.plot = plot 63 self.docker = docker 64 self.ppmFWHMprior = ppmFWHMprior 65 self.ppmRangeprior = ppmRangeprior
67 def set_uncal_settings(self): 68 """Set uncalibrated formula search settings 69 70 This function serves the uncalibrated data (hence broad error tolerance) 71 It only allows CHO formula in deprotonated ion type- as most common for SRFA ESI negative mode 72 73 This will not work for positive mode data, or for other ion types, or other expected elemental searches. 74 75 """ 76 # TODO rework this. 77 78 if self.docker: 79 self.mass_spectrum.molecular_search_settings.url_database = "postgresql+psycopg2://coremsappdb:coremsapppnnl@localhost:5432/coremsapp" 80 else: 81 self.mass_spectrum.molecular_search_settings.url_database = None 82 self.mass_spectrum.molecular_search_settings.error_method = None 83 self.mass_spectrum.molecular_search_settings.score_method = "prob_score" 84 85 self.mass_spectrum.molecular_search_settings.min_ppm_error = ( 86 -1 * self.ppmRangeprior / 2 87 ) # -7.5 88 self.mass_spectrum.molecular_search_settings.max_ppm_error = ( 89 self.ppmRangeprior / 2 90 ) # 7.5 91 92 self.mass_spectrum.molecular_search_settings.min_dbe = 0 93 self.mass_spectrum.molecular_search_settings.max_dbe = 50 94 95 self.mass_spectrum.molecular_search_settings.use_isotopologue_filter = False 96 self.mass_spectrum.molecular_search_settings.min_abun_error = -30 97 self.mass_spectrum.molecular_search_settings.max_abun_error = 70 98 99 self.mass_spectrum.molecular_search_settings.use_min_peaks_filter = True 100 self.mass_spectrum.molecular_search_settings.min_peaks_per_class = ( 101 10 # default is 15 102 ) 103 104 self.mass_spectrum.molecular_search_settings.usedAtoms["C"] = (1, 90) 105 self.mass_spectrum.molecular_search_settings.usedAtoms["H"] = (4, 200) 106 self.mass_spectrum.molecular_search_settings.usedAtoms["O"] = (1, 23) 107 self.mass_spectrum.molecular_search_settings.usedAtoms["N"] = (0, 0) 108 self.mass_spectrum.molecular_search_settings.usedAtoms["S"] = (0, 0) 109 self.mass_spectrum.molecular_search_settings.usedAtoms["P"] = (0, 0) 110 111 self.mass_spectrum.molecular_search_settings.isProtonated = True 112 self.mass_spectrum.molecular_search_settings.isRadical = False 113 self.mass_spectrum.molecular_search_settings.isAdduct = False
Set uncalibrated formula search settings
This function serves the uncalibrated data (hence broad error tolerance) It only allows CHO formula in deprotonated ion type- as most common for SRFA ESI negative mode
This will not work for positive mode data, or for other ion types, or other expected elemental searches.
115 def positive_search_settings(self): 116 """Set the positive mode elemental search settings""" 117 self.mass_spectrum.molecular_search_settings.isProtonated = False 118 self.mass_spectrum.molecular_search_settings.isAdduct = True 119 self.mass_spectrum.molecular_search_settings.adduct_atoms_pos = ["Na"]
Set the positive mode elemental search settings
121 @staticmethod 122 def get_error_range( 123 errors: list, ppmFWHMprior: float = 3, plot_logic: bool = False 124 ): 125 """Get the error range from the error distribution 126 127 Using lmfit and seaborn kdeplot to extract the error range from the error distribution of assigned species. 128 129 Parameters 130 ---------- 131 errors : list 132 list of the errors of the assigned species (ppm) 133 ppmFWHMprior : float, optional 134 The FWHM of the prior distribution (ppm). The default is 3. 135 plot_logic : bool, optional 136 Whether to plot the error distribution. The default is False. 137 138 Returns 139 ------- 140 mean_error : float 141 mean mass error of the Gaussian distribution (ppm) 142 fwhm_error : float 143 full width half max of the gaussian error distribution (ppm) 144 ppm_thresh : list 145 recommended thresholds for the recalibration parameters (ppm) 146 Consists of [mean_error-fwhm_error,mean_error+fwhm_error] 147 148 """ 149 # Create an isolated figure so stale lines from other tests/plots 150 # do not pollute get_lines()[0] (matplotlib global state issue) 151 fig, ax = plt.subplots() 152 kde = sns.kdeplot(errors, ax=ax) 153 154 kde_data = ax.get_lines()[0].get_data() 155 156 tmpdf = pd.Series(index=kde_data[0], data=kde_data[1]) 157 kde_apex_ppm = tmpdf.idxmax() 158 kde_apex_val = tmpdf.max() 159 160 plt.close(fig) 161 plt.close("all") 162 163 lmmodel = GaussianModel() 164 lmpars = lmmodel.guess(kde_data[1], x=kde_data[0]) 165 lmpars["sigma"].value = 2.3548 / ppmFWHMprior 166 lmpars["center"].value = kde_apex_ppm 167 lmpars["amplitude"].value = kde_apex_val 168 lmout = lmmodel.fit(kde_data[1], lmpars, x=kde_data[0]) 169 170 if plot_logic: 171 fig, ax = plt.subplots(figsize=(8, 4)) 172 lmout.plot_fit( 173 ax=ax, data_kws={"color": "tab:blue"}, fit_kws={"color": "tab:red"} 174 ) 175 ax.set_xlabel("$m/z$ Error (ppm)") 176 ax.set_ylabel("Density") 177 plt.legend(facecolor="white", framealpha=0) 178 179 mean_error = lmout.best_values["center"] 180 std_error = lmout.best_values["sigma"] 181 # FWHM from Sigma = approx. 2.355*sigma 182 # fwhm_error = 2*np.sqrt(2*np.log(2))*std_error 183 fwhm_error = std_error * np.sqrt(8 * np.log(2)) 184 185 ppm_thresh = [mean_error - fwhm_error, mean_error + fwhm_error] 186 return mean_error, fwhm_error, ppm_thresh
Get the error range from the error distribution
Using lmfit and seaborn kdeplot to extract the error range from the error distribution of assigned species.
Parameters
- errors (list): list of the errors of the assigned species (ppm)
- ppmFWHMprior (float, optional): The FWHM of the prior distribution (ppm). The default is 3.
- plot_logic (bool, optional): Whether to plot the error distribution. The default is False.
Returns
- mean_error (float): mean mass error of the Gaussian distribution (ppm)
- fwhm_error (float): full width half max of the gaussian error distribution (ppm)
- ppm_thresh (list): recommended thresholds for the recalibration parameters (ppm) Consists of [mean_error-fwhm_error,mean_error+fwhm_error]
188 def determine_error_boundaries(self): 189 """Determine the error boundaries for recalibration space 190 191 This is the main function in this class 192 Sets the Molecular Formulas search settings, performs the initial formula search 193 Converts the data to a dataframe, and gets the error range 194 Returns the error thresholds. 195 196 Returns 197 ------- 198 mean_error : float 199 mean mass error of the Gaussian distribution (ppm) 200 fwhm_error : float 201 full width half max of the gaussian error distribution (ppm) 202 ppm_thresh : list 203 recommended thresholds for the recalibration parameters (ppm) 204 Consists of [mean_error-fwhm_error,mean_error+fwhm_error] 205 """ 206 207 # Set the search settings 208 self.set_uncal_settings() 209 210 # Set the positive mode settings 211 # To do - have user defineable settings? 212 if self.mass_spectrum.polarity == 1: 213 self.positive_search_settings() 214 215 # Search MFs 216 SearchMolecularFormulas( 217 self.mass_spectrum, first_hit=True 218 ).run_worker_mass_spectrum() 219 220 # Exporting to a DF is ~30x slower than just getting the errors, so this is fast. 221 errors = [] 222 for mspeak in self.mass_spectrum.mspeaks: 223 if len(mspeak.molecular_formulas) > 0: 224 errors.append(mspeak.best_molecular_formula_candidate.mz_error) 225 226 # If there are NO assignments, it'll fail on the next step. Need to check for that 227 nassign = len(errors) 228 # Here we say at least 5 features assigned are needed - it probably should be greater, but we are just trying to stop it breaking the code 229 # We want to make sure the spectrum is capture in the database though - so we return the stats entries (0 assignments) and the number of assignments 230 if nassign < 5: 231 if self.mass_spectrum.parameters.mass_spectrum.verbose_processing: 232 print("fewer than 5 peaks assigned, cannot determine error range") 233 return np.nan, np.nan, [np.nan, np.nan] 234 else: 235 mean_error, fwhm_error, ppm_thresh = self.get_error_range( 236 errors, self.ppmFWHMprior, self.plot 237 ) 238 return mean_error, fwhm_error, ppm_thresh
Determine the error boundaries for recalibration space
This is the main function in this class Sets the Molecular Formulas search settings, performs the initial formula search Converts the data to a dataframe, and gets the error range Returns the error thresholds.
Returns
- mean_error (float): mean mass error of the Gaussian distribution (ppm)
- fwhm_error (float): full width half max of the gaussian error distribution (ppm)
- ppm_thresh (list): recommended thresholds for the recalibration parameters (ppm) Consists of [mean_error-fwhm_error,mean_error+fwhm_error]