3939 The maximum number of calls to the curve fitting function.
4040_error_metric : str
4141 The error metric to use for post-hoc measures of model fit error.
42+
43+ Run Modes
44+ ---------
4245_debug : bool
4346 Whether the object is set in debug mode.
4447 This should be controlled by using the `set_debug_mode` method.
48+ _check_data : bool
49+ Whether to check added data for NaN or Inf values, and fail out if present.
50+ This should be controlled by using the `set_check_data_mode` method.
4551
4652Code Notes
4753----------
@@ -184,12 +190,16 @@ def __init__(self, peak_width_limits=(0.5, 12.0), max_n_peaks=np.inf, min_peak_h
184190 # The maximum number of calls to the curve fitting function
185191 self ._maxfev = 5000
186192 # The error metric to calculate, post model fitting. See `_calc_error` for options
187- # Note: this is used to check error post-hoc , not an objective function for fitting models
193+ # Note: this is for checking error post fitting , not an objective function for fitting
188194 self ._error_metric = 'MAE'
189- # Set whether in debug mode, in which an error is raised if a model fit fails
195+
196+ ## RUN MODES
197+ # Set default debug mode - controls if an error is raised if model fitting is unsuccessful
190198 self ._debug = False
199+ # Set default check data mode - controls if an error is raised if NaN / Inf data are added
200+ self ._check_data = True
191201
192- # Set internal settings, based on inputs, & initialize data & results attributes
202+ # Set internal settings, based on inputs, and initialize data & results attributes
193203 self ._reset_internal_settings ()
194204 self ._reset_data_results (True , True , True )
195205
@@ -312,7 +322,7 @@ def add_data(self, freqs, power_spectrum, freq_range=None, clear_results=True):
312322 clear_results = self .has_model and clear_results )
313323
314324 self .freqs , self .power_spectrum , self .freq_range , self .freq_res = \
315- self ._prepare_data (freqs , power_spectrum , freq_range , 1 , self . verbose )
325+ self ._prepare_data (freqs , power_spectrum , freq_range , 1 )
316326
317327
318328 def add_settings (self , fooof_settings ):
@@ -432,6 +442,14 @@ def fit(self, freqs=None, power_spectrum=None, freq_range=None):
432442 # In rare cases, the model fails to fit, and so uses try / except
433443 try :
434444
445+ # If not set to fail on NaN or Inf data at add time, check data here
446+ # This serves as a catch all for curve_fits which will fail given NaN or Inf
447+ # Because FitError's are by default caught, this allows fitting to continue
448+ if not self ._check_data :
449+ if np .any (np .isinf (self .power_spectrum )) or np .any (np .isnan (self .power_spectrum )):
450+ raise FitError ("Model fitting was skipped because there are NaN or Inf "
451+ "values in the data, which preclude model fitting." )
452+
435453 # Fit the aperiodic component
436454 self .aperiodic_params_ = self ._robust_ap_fit (self .freqs , self .power_spectrum )
437455 self ._ap_fit = gen_aperiodic (self .freqs , self .aperiodic_params_ )
@@ -675,7 +693,7 @@ def copy(self):
675693
676694
677695 def set_debug_mode (self , debug ):
678- """Set whether debug mode, wherein an error is raised if fitting is unsuccessful.
696+ """Set debug mode, which controls if an error is raised if model fitting is unsuccessful.
679697
680698 Parameters
681699 ----------
@@ -686,6 +704,18 @@ def set_debug_mode(self, debug):
686704 self ._debug = debug
687705
688706
707+ def set_check_data_mode (self , check_data ):
708+ """Set check data mode, which controls if an error is raised if NaN or Inf data are added.
709+
710+ Parameters
711+ ----------
712+ check_data : bool
713+ Whether to run in check data mode.
714+ """
715+
716+ self ._check_data = check_data
717+
718+
689719 def _check_width_limits (self ):
690720 """Check and warn about peak width limits / frequency resolution interaction."""
691721
@@ -795,7 +825,8 @@ def _robust_ap_fit(self, freqs, power_spectrum):
795825 raise FitError ("Model fitting failed due to not finding "
796826 "parameters in the robust aperiodic fit." )
797827 except TypeError :
798- raise FitError ("Model fitting failed due to sub-sampling in the robust aperiodic fit." )
828+ raise FitError ("Model fitting failed due to sub-sampling "
829+ "in the robust aperiodic fit." )
799830
800831 return aperiodic_params
801832
@@ -1110,8 +1141,7 @@ def _calc_error(self, metric=None):
11101141 raise ValueError (msg )
11111142
11121143
1113- @staticmethod
1114- def _prepare_data (freqs , power_spectrum , freq_range , spectra_dim = 1 , verbose = True ):
1144+ def _prepare_data (self , freqs , power_spectrum , freq_range , spectra_dim = 1 ):
11151145 """Prepare input data for adding to current object.
11161146
11171147 Parameters
@@ -1125,8 +1155,6 @@ def _prepare_data(freqs, power_spectrum, freq_range, spectra_dim=1, verbose=True
11251155 Frequency range to restrict power spectrum to. If None, keeps the entire range.
11261156 spectra_dim : int, optional, default: 1
11271157 Dimensionality that the power spectra should have.
1128- verbose : bool, optional
1129- Whether to be verbose in printing out warnings.
11301158
11311159 Returns
11321160 -------
@@ -1181,7 +1209,7 @@ def _prepare_data(freqs, power_spectrum, freq_range, spectra_dim=1, verbose=True
11811209 # Aperiodic fit gets an inf if freq of 0 is included, which leads to an error
11821210 if freqs [0 ] == 0.0 :
11831211 freqs , power_spectrum = trim_spectrum (freqs , power_spectrum , [freqs [1 ], freqs .max ()])
1184- if verbose :
1212+ if self . verbose :
11851213 print ("\n FOOOF WARNING: Skipping frequency == 0, "
11861214 "as this causes a problem with fitting." )
11871215
@@ -1192,12 +1220,13 @@ def _prepare_data(freqs, power_spectrum, freq_range, spectra_dim=1, verbose=True
11921220 # Log power values
11931221 power_spectrum = np .log10 (power_spectrum )
11941222
1195- # Check if there are any infs / nans, and raise an error if so
1196- if np .any (np .isinf (power_spectrum )) or np .any (np .isnan (power_spectrum )):
1197- raise DataError ("The input power spectra data, after logging, contains NaNs or Infs. "
1198- "This will cause the fitting to fail. "
1199- "One reason this can happen is if inputs are already logged. "
1200- "Inputs data should be in linear spacing, not log." )
1223+ if self ._check_data :
1224+ # Check if there are any infs / nans, and raise an error if so
1225+ if np .any (np .isinf (power_spectrum )) or np .any (np .isnan (power_spectrum )):
1226+ raise DataError ("The input power spectra data, after logging, contains NaNs or Infs. "
1227+ "This will cause the fitting to fail. "
1228+ "One reason this can happen is if inputs are already logged. "
1229+ "Inputs data should be in linear spacing, not log." )
12011230
12021231 return freqs , power_spectrum , freq_range , freq_res
12031232
0 commit comments