def test_fooof_checks(): """Test various checks, errors and edge cases in FOOOF.""" xs, ys = gen_power_spectrum([3, 50], [50, 2], [10, 0.5, 2]) tfm = FOOOF() # Check dimension error with raises(ValueError): tfm.fit(xs, np.reshape(ys, [1, len(ys)])) # Check shape mismatch error with raises(ValueError): tfm.fit(xs[:-1], ys) # Check trim_spectrum range tfm.fit(xs, ys, [3, 40]) # Check freq of 0 issue xs, ys = gen_power_spectrum([3, 50], [50, 2], [10, 0.5, 2]) tfm.fit(xs, ys) assert tfm.freqs[0] != 0 # Check fit, and string report model error (no data / model fit) tfm = FOOOF() with raises(ValueError): tfm.fit()
def test_fooof_report(skip_if_no_mpl): """Check that running the top level model method runs.""" tfm = FOOOF() tfm.report(*gen_power_spectrum([3, 50], [50, 2], [10, 0.5, 2, 20, 0.3, 4])) assert tfm
def test_fooof_fit_knee(): """Test FOOOF fit, with a knee.""" bgp = [50, 2, 1] gauss_params = [10, 0.5, 2, 20, 0.3, 4] xs, ys = gen_power_spectrum([3, 50], bgp, gauss_params) tfm = FOOOF(background_mode='knee') tfm.fit(xs, ys) # Note: currently, this test has no accuracy checking at all assert True
def get_tfm(): """Get a FOOOF object, with a fit power spectrum, for testing.""" freq_range = [3, 50] bg_params = [50, 2] gauss_params = [10, 0.5, 2, 20, 0.3, 4] xs, ys = gen_power_spectrum(freq_range, bg_params, gauss_params) tfm = FOOOF() tfm.fit(xs, ys) return tfm
def test_fooof_fit_nk(): """Test FOOOF fit, no knee.""" bgp = [50, 2] gauss_params = [10, 0.5, 2, 20, 0.3, 4] xs, ys = gen_power_spectrum([3, 50], bgp, gauss_params) tfm = FOOOF() tfm.fit(xs, ys) # Check model results - background parameters assert np.all(np.isclose(bgp, tfm.background_params_, [0.5, 0.1])) # Check model results - gaussian parameters for ii, gauss in enumerate(group_three(gauss_params)): assert np.all(np.isclose(gauss, tfm._gaussian_params[ii], [1.5, 0.25, 0.5]))
def test_fooof_fit_failure(): """Test that fit handles a failure.""" # Use a new FOOOF, that is monkey-patched to raise an error # This mimicks the main fit-failure, without requiring bad data / waiting for it to fail. tfm = FOOOF() def raise_runtime_error(*args, **kwargs): raise RuntimeError('Test-MonkeyPatch') tfm._fit_peaks = raise_runtime_error # Run a FOOOF fit - this should raise an error, but continue in try/except tfm.fit(*gen_power_spectrum([3, 50], [50, 2], [10, 0.5, 2, 20, 0.3, 4])) # Check after failing out of fit, all results are reset for result in get_obj_desc()['results']: cur_res = getattr(tfm, result) assert cur_res is None or np.all(np.isnan(cur_res))
############################################################################### # Generate a noisy synthetic power spectrum # Set the frequency range to generate the power spectrum f_range = [1, 50] # Set aperiodic background signal parameters, as [offset, slope] bg_params = [20, 2] # Gaussian peak parameters gauss_params = [10, 1.0, 2.5, 20, 0.8, 2, 32, 0.6, 1] # Set the level of noise to generate the power spectrum with nlv = 0.1 # Create a synthetic power spectrum freqs, spectrum = gen_power_spectrum(f_range, bg_params, gauss_params, nlv) ############################################################################### # Fit an (unconstrained) FOOOF model, liable to overfit fm = FOOOF() fm.report(freqs, spectrum) ############################################################################### # # Notice that in the above fit, we are very likely to think that FOOOF has been overzealous in fitting peaks, and is therefore overfitting. # # This is also suggested by the model r-squared, which is suspiciously high, given the amount of noise we expect. # # To reduce this kind of overfitting, we can update the FOOOF parameters.