def test_adds(): """Tests methods that add data to FOOOF objects. Checks: add_data, add_settings, add_results. """ # Note: uses it's own tfm, to not add stuff to the global one tfm = get_tfm() # Test adding data freqs, pows = np.array([1, 2, 3]), np.array([10, 10, 10]) tfm.add_data(freqs, pows) assert np.all(tfm.freqs == freqs) assert np.all(tfm.power_spectrum == np.log10(pows)) # Test adding settings fooof_settings = FOOOFSettings([1, 4], 6, 0, 2, 'fixed') tfm.add_settings(fooof_settings) for setting in get_description()['settings']: assert getattr(tfm, setting) == getattr(fooof_settings, setting) # Test adding meta data fooof_meta_data = FOOOFMetaData([3, 40], 0.5) tfm.add_meta_data(fooof_meta_data) for meta_dat in get_description()['meta_data']: assert getattr(tfm, meta_dat) == getattr(fooof_meta_data, meta_dat) # Test adding results fooof_results = FOOOFResults([1, 1], [10, 0.5, 0.5], 0.95, 0.02, [10, 0.5, 0.25]) tfm.add_results(fooof_results) for setting in get_description()['results']: assert getattr(tfm, setting) == getattr(fooof_results, setting.strip('_'))
def test_fg_get_fooof(tfg): """Check return of an individual model fit to a FOOOF object from FOOOFGroup.""" desc = get_description() # Check without regenerating tfm0 = tfg.get_fooof(0, False) assert tfm0 # Check that settings are copied over properly for setting in desc['settings']: assert getattr(tfg, setting) == getattr(tfm0, setting) # Check with regenerating tfm1 = tfg.get_fooof(1, True) assert tfm1 # Check that regenerated model is created for result in desc['results']: assert np.all(getattr(tfm1, result)) # Test when object has no data (clear a copy of tfg) new_tfg = tfg.copy() new_tfg._reset_data_results(False, True, True, True) tfm2 = new_tfg.get_fooof(0, True) assert tfm2 # Check that data info is copied over properly for meta_dat in desc['meta_data']: assert getattr(tfm2, meta_dat)
def load_json(file_name, file_path): """Load json file. Parameters ---------- file_name : str or FileObject, optional File from which to load data. file_path : str Path to directory from which to load. Returns ------- dat : dict Dictionary of data loaded from file. """ # Load data from file if isinstance(file_name, str): with open(fpath(file_path, fname(file_name, 'json')), 'r') as infile: dat = json.load(infile) elif isinstance(file_name, io.IOBase): dat = json.loads(file_name.readline()) # Get dictionary of available attributes, and convert specified lists back into arrays dat = dict_lst_to_array(dat, get_description()['arrays']) return dat
def save_fm(fm, file_name, file_path=None, append=False, save_results=False, save_settings=False, save_data=False): """Save out data, results and/or settings from FOOOF object. Saves out to a JSON file. Parameters ---------- fm : FOOOF() object FOOOF object from which to save data. file_name : str or FileObject File to which to save data. file_path : str, optional Path to directory in which to save. If not provided, saves to current directory. append : bool, optional, default: False Whether to append to an existing file, if available. This option is only valid (and only used) if file_name is a str. save_results : bool, optional Whether to save out FOOOF model fit results. save_settings : bool, optional Whether to save out FOOOF settings. save_data : bool, optional Whether to save out input data. """ # Convert object to dictionary & convert all arrays to lists - for JSON serializing obj_dict = dict_array_to_lst(fm.__dict__) # Set and select which variables to keep. Use a set to drop any potential overlap # Note that results also saves frequency information to be able to recreate freq vector attributes = get_description() keep = set((attributes['results'] + attributes['meta_data'] if save_results else []) + \ (attributes['settings'] if save_settings else []) + \ (attributes['data'] if save_data else [])) obj_dict = dict_select_keys(obj_dict, keep) # Save out - create new file, (creates a JSON file) if isinstance(file_name, str) and not append: with open(fpath(file_path, fname(file_name, 'json')), 'w') as outfile: json.dump(obj_dict, outfile) # Save out - append to file_name (appends to a JSONlines file) elif isinstance(file_name, str) and append: with open(fpath(file_path, fname(file_name, 'json')), 'a') as outfile: json.dump(obj_dict, outfile) outfile.write('\n') # Save out - append to given file object (appends to a JSONlines file) elif isinstance(file_name, io.IOBase): json.dump(obj_dict, file_name) file_name.write('\n') else: raise ValueError('Save file not understood.')
def test_fooof_results(): results = FOOOFResults([], [], None, None, []) assert results # Check that the object has the correct fields, given the object description results_fields = get_description()['results'] for field in results_fields: getattr(results, field.strip('_')) assert True
def test_fooof_settings(): settings = FOOOFSettings([], None, None, None, None) assert settings # Check that the object has the correct fields, given the object description settings_fields = get_description()['settings'] for field in settings_fields: getattr(settings, field) assert True
def get_results(self): """Return model fit parameters and goodness of fit metrics in a FOOOFResults object. Returns ------- FOOOFResults Object containing the FOOOF model fit results from the current FOOOF object. """ return FOOOFResults(**{key.strip('_') : getattr(self, key) \ for key in get_description()['results']})
def get_settings(self): """Return user defined settings of the FOOOF object. Returns ------- FOOOFSettings Object containing the settings from the current FOOOF object. """ return FOOOFSettings( ** {key: getattr(self, key) for key in get_description()['settings']})
def add_meta_data(self, fooof_meta_data): """Add data information into object from a FOOOFMetaData object. Parameters ---------- fooof_meta_data : FOOOFMetaData A FOOOF meta data object containing meta data information. """ for meta_dat in get_description()['meta_data']: setattr(self, meta_dat, getattr(fooof_meta_data, meta_dat)) self._regenerate_freqs()
def add_settings(self, fooof_settings): """Add settings into object from a FOOOFSettings object. Parameters ---------- fooof_settings : FOOOFSettings A FOOOF data object containing the settings for a FOOOF model. """ for setting in get_description()['settings']: setattr(self, setting, getattr(fooof_settings, setting)) self._check_loaded_settings(fooof_settings._asdict())
def get_meta_data(self): """Return data information from the FOOOF object. Returns ------- FOOOFMetaData Object containing meta data from the current FOOOF object. """ return FOOOFMetaData(**{ key: getattr(self, key) for key in get_description()['meta_data'] })
def _check_loaded_results(self, data): """Check if results have been added and check data. Parameters ---------- data : dict A dictionary of data that has been added to the object. """ # If results loaded, check dimensions of peak parameters # This fixes an issue where they end up the wrong shape if they are empty (no peaks) if set(get_description()['results']).issubset(set(data.keys())): self.peak_params_ = check_array_dim(self.peak_params_) self.gaussian_params_ = check_array_dim(self.gaussian_params_)
def test_fooof_resets(): """Check that all relevant data is cleared in the resest method.""" # Note: uses it's own tfm, to not clear the global one tfm = get_tfm() tfm._reset_data_results() tfm._reset_internal_settings() desc = get_description() for data in ['data', 'results', 'model_components']: for field in desc[data]: assert getattr(tfm, field) == None assert tfm.freqs == None and tfm.fooofed_spectrum_ == None
def _check_loaded_settings(self, data): """Check if settings added, and update the object as needed. Parameters ---------- data : dict A dictionary of data that has been added to the object. """ # If settings not loaded from file, clear from object, so that default # settings, which are potentially wrong for loaded data, aren't kept if not set(get_description()['settings']).issubset(set(data.keys())): # Reset all public settings to None for setting in get_description()['settings']: setattr(self, setting, None) # Infer whether knee fitting was used, if aperiodic params have been loaded if np.all(self.aperiodic_params_): self.aperiodic_mode = infer_ap_func(self.aperiodic_params_) # Reset internal settings so that they are consistent with what was loaded # Note that this will set internal settings to None, if public settings unavailable self._reset_internal_settings()
def get_info(f_obj, aspect): """Get a specified selection of information from a FOOOF derived object. Parameters ---------- f_obj : FOOOF or FOOOFGroup FOOOF derived object to get attributes from. aspect : {'settings', 'meta_data', 'results'} Which set of attributes to compare the objects across. Returns ------- dict The set of specified info from the FOOOF derived object. """ return {key : getattr(f_obj, key) for key in get_description()[aspect]}
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(verbose=False) 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_description()['results']: cur_res = getattr(tfm, result) assert cur_res is None or np.all(np.isnan(cur_res))
def test_load_file_contents(): """Check that loaded files contain the contents they should. Note that is this test fails, it likely stems from an issue from saving. """ file_name = 'test_fooof_str_all' file_path = pkg.resource_filename(__name__, 'test_files') loaded_data = load_json(file_name, file_path) desc = get_description() # Check settings for setting in desc['settings']: assert setting in loaded_data.keys() # Check results for result in desc['results']: assert result in loaded_data.keys() # Check results for datum in desc['data']: assert datum in loaded_data.keys()
"""Instantiated objects that can be used as 'helper items' for working with FOOOF.""" from fooof.core.info import get_description, get_peak_indices ################################################################################################### ################################################################################################### OBJ_DESC = get_description() PEAK_INDS = get_peak_indices()