Skip to content

Commit 018b618

Browse files
authored
Merge pull request #17 from fooof-tools/dev
Update fooof_mat to match FOOOF 1.0
2 parents 5b25794 + cd39963 commit 018b618

13 files changed

+147
-81
lines changed

README.md

Lines changed: 61 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,76 +1,96 @@
11
# FOOOF - Matlab Wrapper
22

3-
This repository offers a Matlab wrapper for [FOOOF](https://github.com/fooof-tools/fooof) with Matlab.
3+
This repository offers a Matlab wrapper for [FOOOF](https://github.com/fooof-tools/fooof).
44

5-
All [descriptions](https://github.com/fooof-tools/fooof/README.md) and [tutorials](https://github.com/fooof-tools/fooof/tutorial) for FOOOF are in the [main repository](https://github.com/fooof-tools/fooof), and a full description of the method is available in the [paper](https://www.biorxiv.org/content/early/2018/04/11/299859).
5+
The main documentation for FOOOF is on the [documentation site](https://fooof-tools.github.io/fooof/).
66

7-
This repository describes the Matlab wrapper, in which you call the Python implementation of FOOOF from Matlab, never having to interact directly with Python. An alternative approach is to use a primarily
7+
This repository describes the Matlab wrapper, in which you call the Python implementation of FOOOF from Matlab, never having to interact directly with Python.
88

9-
There are two approaches offered here for using FOOOF with Matlab - a Matlab Wrapper, and a Matlab->Python->Matlab workflow. Note that these options both still use the Python implementation under the hood, and so do require a working Python install - but that should be easy to do, and instructions are provided below to do so.
10-
11-
### Reference
12-
13-
If you use this code in your project, please cite:
14-
15-
Haller M, Donoghue T, Peterson E, Varma P, Sebastian P, Gao R, Noto T, Knight RT, Shestyuk A,
16-
Voytek B (2018) Parameterizing Neural Power Spectra. bioRxiv, 299859.
17-
doi: https://doi.org/10.1101/299859
9+
Note that, as an alternative to using the wrapper from Matlab, you can also try the
10+
[Matlab->Python->Matlab](https://github.com/fooof-tools/mat_py_mat)
11+
approach, in which there are examples for using FOOOF, in Python, integrated into a primarily Matlab workflow.
1812

1913
## FOOOF_MAT
2014

21-
The Matlab wrapper, is Matlab code that calls the Python implementation of FOOOF. This requires that you have Python & FOOOF installed, but does not require you to ever use or write Python code yourself.
15+
The Matlab wrapper is Matlab code that calls the Python implementation of FOOOF. This requires that you have Python & FOOOF installed, but does not require you to ever use or write Python code yourself.
2216

23-
To use the wrapper, first install Python & FOOOF - there are instructions to do so below. Then clone or download this repository, and then use the the provided matlab code to run FOOOF. The only function you need to run is 'fooof.m', which has documentation on inputs and outputs.
17+
To use the wrapper, first install Python & FOOOF - there are instructions to do so below. Then clone or download this repository, and use the provided Matlab code to run FOOOF. Typically, the only function you will need to run is 'fooof.m', which has documentation on inputs and outputs.
2418

25-
Note that this is a very minimal wrapper - it provides access only to the core algorithm, and not to any of the extra utilities, such as plotting the model outputs. As the algorithm is really the purpose of FOOOF, you are not lacking any functionality in that sense - all the inputs settings and model outputs are available to you.
19+
Note that this is a very minimal wrapper - it provides access only to the core algorithm, and does not offer access to most of the extra utilities in the Python module. However, since the algorithm is the core purpose of FOOOF, you do have full access to the model itself, including all inputs settings and model outputs.
2620

2721
#### Dependencies
2822

2923
This Matlab wrapper uses the Python support introduced by Matlab in 2014b, and as such requires that version, or higher, to run.
3024

31-
#### pyversion
25+
## Installing Python & FOOOF
26+
27+
Both workflows above require that Python & FOOOF be installed. The easiest way to do this is as follows:
28+
29+
#### Install Python
30+
31+
To call Python from Matlab, you will need to have Python installed.
3232

33-
Once you have downloaded Python, you shouldn't need to do anything for Matlab to be able to call Python - as long as your Matlab is using the correct Python. If it's not working, this is likely the problem.
33+
One option to install Python, as well as all the dependencies you need and including tools like Jupyter notebook, is to use the Anaconda distribution. To do so, go to the [Anaconda Website](https://www.anaconda.com/download/) and download the latest version Python3 version available. Install the file you download, and then you should be good to go!
34+
35+
Note that your computer may already have a version of Python, but you should still go an install a new one. This ensures that you can have a new version of Python where you can install new modules, without interfering with your system Python.
36+
37+
You can also install Python without using Anaconda, for example directly from [python.org](https://www.python.org/downloads/). This might be useful, as Matlab doesn't always seem to work well with the Anaconda distribution.
38+
39+
If you are having trouble getting Python set up with Matlab, this
40+
[blog post](https://irenevigueguix.wordpress.com/2020/03/25/loading-python-into-matlab/)
41+
also offers a step-by-step guide.
42+
43+
#### Install FOOOF
44+
45+
FOOOF can be installed through pip, meaning you just have to run the following from the command line:
46+
47+
`pip install fooof`
48+
49+
If you're on mac, 'command line' means terminal - after installing anaconda, just copy the above command into the terminal, and it should work. If you're on windows, you will need to run this in 'anaconda command prompt' which is basically a command line specifically for managing Python with Anaconda.
3450

35-
You can run `pyversion` to see which Python you are using. Note that you must do this _after installing Python and FOOOF_ (instruction to do so below).
51+
#### Calling Python from Matlab
52+
53+
Once you have downloaded Python, you shouldn't need to do anything for Matlab to be able to
54+
[call Python](https://www.mathworks.com/help/matlab/call-python-libraries.html).
55+
56+
The most common problem seems to be if Matlab is not using the correct version or location for Python. If calling Python is not working, then checking and setting where Matlab is calling Python from is likely the solution.
57+
58+
To check and update which Python Matlab is using, you can use
59+
[pyversion](https://www.mathworks.com/help/matlab/ref/pyversion.html), or
60+
[pyenv](https://www.mathworks.com/help/matlab/ref/pyenv.html)
61+
if you are on a newer version of Matlab (>= R2019b).
62+
63+
For example, you can run `pyversion` to see which Python you are using, and update it if required.
64+
65+
Note that you must do this _after installing Python and FOOOF_.
3666
```
37-
% Check which python is being used.
67+
% Check which python is being used
3868
pyversion
3969
4070
% The print out from above should tell you which Python you are calling
41-
% It should show that you are using Python version 3.6.
42-
% It should also show that the 'home' of this python is in the anaconda folder
71+
% It should show that you are using Python version 3.X
72+
% If you are using anaconda, it should show your Python is in the anaconda folder
4373
% If either of these things are not right, reset which Python you are using, as below
4474
4575
% Set python version to use
4676
% Note: you must do this first thing after opening Matlab (relaunch if you need to)
4777
% You should only ever have to run this at most, once.
48-
% Note: you're anaconda folder might be `anaconda3` instead of `anaconda`
78+
% You might need to change the path to where your python or anaconda install is
79+
% For example, your anaconda folder might be `anaconda3` instead of `anaconda`
80+
% or your anaconda path might be somewhere else, for example, '/opt/anaconda3/bin/python'
4981
pyversion('/anaconda/bin/python')
5082
```
5183

52-
## Installing Python & FOOOF
53-
54-
Both workflows above require that Python & FOOOF be installed. The easiest way to do this is as follows:
55-
56-
#### Install Python with Anaconda
57-
58-
To install Python, as well as all the dependencies you need and including tools like Jupyter notebook, go to the [Anaconda Website](https://www.anaconda.com/download/) and download the Python 3.6 version. Install the file you download, and then you're good to go!
59-
60-
Note that your computer may well have a version of Python - but you should still go an install a new one with Anaconda - this ensures that you have all the dependencies you need, and leaves your system Python alone, for safety.
84+
## Reference
6185

62-
Once you've downloaded Anaconda, you will have a program called 'Anaconda Navigator', which you can use to launch Juypter notebooks, if you want. For more information on using notebooks, check out [project Jupyter](http://jupyter.org).
63-
64-
#### Install FOOOF
65-
66-
FOOOF can be installed through pip, meaning you just have to run the following from the command line:
67-
68-
`pip install fooof`
86+
If you use this code in your project, please cite:
6987

70-
If you're on mac, 'command line' means terminal - after installing anaconda, just copy the above command into the terminal, and it should work. If you're on windows, you will need to run this in 'anaconda command prompt' which is basically a command line specifically for managing Python with Anaconda.
88+
Haller M, Donoghue T, Peterson E, Varma P, Sebastian P, Gao R, Noto T, Knight RT, Shestyuk A,
89+
Voytek B (2018) Parameterizing Neural Power Spectra. bioRxiv, 299859.
90+
doi: https://doi.org/10.1101/299859
7191

7292
## Potential Matlab Implementation
7393

74-
The above workflows still use the Python implementation of FOOOF. This has some perks, in that running the exact same code means that there are no worries about maintaining and verying the consistency between multiple implementations of the code. However, it does still require this somewhat annoying coordinating between languages, if one wants to use Matlab. The only way to get around this would be to have a re-implemenation of the algorithm in Matlab, in which case it could be used in a stand-alone manner.
94+
This Matlab wrapper still uses the Python implementation of FOOOF.
7595

76-
As of right now, there are no plans on our end for a full re-implementation of the algorithm in Matlab - it's non-trivial to re-write, test, confirm equivalence, and then continuously maintain two versions. That said, the code is open, so if want to try and do this yourself, go for it!
96+
As of right now, there are no plans for us to create a full re-implementation of the algorithm in Matlab, as it is a large project to re-write, test, confirm equivalence, and then continuously maintain two versions.
File renamed without changes.
File renamed without changes.

examples/example_wrapper_multi_psd.m renamed to examples/fooof_example_multi_spectra.m

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,27 @@
11
%% FOOOF Matlab Wrapper Example - Multiple PSDs
2+
%
3+
% This example computes example power spectra models on a group of
4+
% power spectra, and prints out the results.
5+
%
6+
7+
%% Run Example
28

39
% Load data
4-
load('dat/ch_dat_one.mat');
5-
load('dat/ch_dat_two.mat');
10+
load('data/ch_dat_one.mat');
11+
load('data/ch_dat_two.mat');
612

713
% Combine into a multi-channel data matrix
814
chs_dat = [ch_dat_one; ch_dat_two]';
915

1016
% Calculate power spectra with Welch's method
1117
[psds, freqs] = pwelch(chs_dat, 500, [], [], s_rate);
1218

13-
% Transpose, to make FOOOF inputs row vectors
19+
% Transpose, to make inputs row vectors
1420
freqs = freqs';
1521

1622
% FOOOF settings
1723
settings = struct();
18-
f_range = [1, 50];
24+
f_range = [1, 30];
1925

2026
% Run FOOOF across a group of power spectra
2127
fooof_results = fooof_group(freqs, psds, f_range, settings);

examples/example_wrapper_one_psd.m renamed to examples/fooof_example_one_spectrum.m

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,24 @@
11
%% FOOOF Matlab Wrapper Example - Single PSD
2+
%
3+
% This example computes an example power spectrum model for a single
4+
% power spectrum, and prints out the results.
5+
%
6+
7+
%% Run Example
28

39
% Load data
4-
load('dat/ch_dat_one.mat');
10+
load('data/ch_dat_one.mat');
511

612
% Calculate a power spectrum with Welch's method
713
[psd, freqs] = pwelch(ch_dat_one, 500, [], [], s_rate);
814

9-
% Transpose, to make FOOOF inputs row vectors
15+
% Transpose, to make inputs row vectors
1016
freqs = freqs';
1117
psd = psd';
1218

1319
% FOOOF settings
1420
settings = struct(); % Use defaults
15-
f_range = [1, 50];
21+
f_range = [1, 30];
1622

1723
% Run FOOOF
1824
fooof_results = fooof(freqs, psd, f_range, settings);

examples/fooof_example_plot_model.m

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
%% FOOOF Matlab Wrapper Example - Plot a FOOOF model
2+
%
3+
% This example computes an example power spectrum model fit,
4+
% and then plots the result.
5+
%
6+
7+
%% Run Example
8+
9+
% Load data
10+
load('data/ch_dat_one.mat');
11+
12+
% Calculate a power spectrum with Welch's method
13+
[psd, freqs] = pwelch(ch_dat_one, 500, [], [], s_rate);
14+
15+
% Transpose, to make inputs row vectors
16+
freqs = freqs';
17+
psd = psd';
18+
19+
% FOOOF settings
20+
settings = struct(); % Use defaults
21+
f_range = [1, 30];
22+
23+
% Run FOOOF, also returning the model
24+
fooof_results = fooof(freqs, psd, f_range, settings, true);
25+
26+
% Plot the resulting model
27+
fooof_plot(fooof_results)

fooof_mat/fooof.m

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,15 @@
1010
% settings = fooof model settings, in a struct, including:
1111
% settings.peak_width_limts
1212
% settings.max_n_peaks
13-
% settings.min_peak_amplitude
13+
% settings.min_peak_height
1414
% settings.peak_threshold
15-
% settings.background_mode
15+
% settings.aperiodic_mode
1616
% settings.verbose
1717
% return_model = boolean of whether to return the FOOOF model fit, optional
1818
%
1919
% Outputs:
2020
% fooof_results = fooof model ouputs, in a struct, including:
21-
% fooof_results.background_params
21+
% fooof_results.aperiodic_params
2222
% fooof_results.peak_params
2323
% fooof_results.gaussian_params
2424
% fooof_results.error
@@ -27,7 +27,7 @@
2727
% fooof_results.freqs
2828
% fooof_results.power_spectrum
2929
% fooof_results.fooofed_spectrum
30-
% fooof_results.bg_fit
30+
% fooof_results.ap_fit
3131
%
3232
% Notes
3333
% Not all settings need to be defined by the user.
@@ -47,9 +47,9 @@
4747
% Initialize FOOOF object
4848
fm = py.fooof.FOOOF(settings.peak_width_limits, ...
4949
settings.max_n_peaks, ...
50-
settings.min_peak_amplitude, ...
50+
settings.min_peak_height, ...
5151
settings.peak_threshold, ...
52-
settings.background_mode, ...
52+
settings.aperiodic_mode, ...
5353
settings.verbose);
5454

5555
% Run FOOOF fit
@@ -58,6 +58,16 @@
5858
% Extract outputs
5959
fooof_results = fm.get_results();
6060
fooof_results = fooof_unpack_results(fooof_results);
61+
62+
% Re-calculating r-squared
63+
% r_squared doesn't seem to get computed properly (in NaN).
64+
% It is unclear why this happens, other than the error can be traced
65+
% back to the internal call to `np.cov`, and fails when this function
66+
% gets two arrays as input.
67+
% Therefore, we can simply recalculate r-squared
68+
coefs = corrcoef(double(py.array.array('d', fm.power_spectrum)), ...
69+
double(py.array.array('d', fm.fooofed_spectrum_)));
70+
fooof_results.r_squared = coefs(2);
6171

6272
% Also return the actual model fit, if requested
6373
% This will default to not return model, if variable not set

fooof_mat/fooof_check_settings.m

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,18 +7,18 @@
77
% settings = struct, can optionally include:
88
% settings.peak_width_limts
99
% settings.max_n_peaks
10-
% settings.min_peak_amplitude
10+
% settings.min_peak_height
1111
% settings.peak_threshold
12-
% settings.background_mode
12+
% settings.aperiodic_mode
1313
% settings.verbose
1414
%
1515
% Outputs:
1616
% settings = struct, with all settings defined:
1717
% settings.peak_width_limts
1818
% settings.max_n_peaks
19-
% settings.min_peak_amplitude
19+
% settings.min_peak_height
2020
% settings.peak_threshold
21-
% settings.background_mode
21+
% settings.aperiodic_mode
2222
% settings.verbose
2323
%
2424
% Notes:
@@ -31,9 +31,9 @@
3131
defaults = struct(...
3232
'peak_width_limits', [0.5, 12], ...
3333
'max_n_peaks', Inf, ...
34-
'min_peak_amplitude', 0.0, ...
34+
'min_peak_height', 0.0, ...
3535
'peak_threshold', 2.0, ...
36-
'background_mode', 'fixed', ...
36+
'aperiodic_mode', 'fixed', ...
3737
'verbose', true);
3838

3939
% Overwrite any non-existent or nan settings with defaults

fooof_mat/fooof_get_model.m

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
% model_fit.freqs
1212
% model_fit.power_spectrum
1313
% model_fit.fooofed_spectrum
14-
% model_fit.bg_fit
14+
% model_fit.ap_fit
1515
%
1616
% Notes
1717
% This function is mostly an internal function.
@@ -24,4 +24,4 @@
2424
model_fit.freqs = double(py.array.array('d',fm.freqs));
2525
model_fit.power_spectrum = double(py.array.array('d', fm.power_spectrum));
2626
model_fit.fooofed_spectrum = double(py.array.array('d', fm.fooofed_spectrum_));
27-
model_fit.bg_fit = double(py.array.array('d', py.getattr(fm, '_bg_fit')));
27+
model_fit.ap_fit = double(py.array.array('d', py.getattr(fm, '_ap_fit')));

fooof_mat/fooof_group.m

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
% fooof_group() run the fooof model on a group of neural power spectra
1+
% fooof_group() - Run the fooof model on a group of neural power spectra.
22
%
33
% Usage:
44
% fooof_results = fooof_group(freqs, psds, f_range, settings);
@@ -10,14 +10,14 @@
1010
% settings = fooof model settings, in a struct, including:
1111
% settings.peak_width_limts
1212
% settings.max_n_peaks
13-
% settings.min_peak_amplitude
13+
% settings.min_peak_height
1414
% settings.peak_threshold
15-
% settings.background_mode
15+
% settings.aperiodic_mode
1616
% settings.verbose
1717
%
1818
% Outputs:
1919
% fooof_results = fooof model ouputs, in a struct, including:
20-
% fooof_results.background_params
20+
% fooof_results.aperiodic_params
2121
% fooof_results.peak_params
2222
% fooof_results.gaussian_params
2323
% fooof_results.error

fooof_mat/fooof_plot.m

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
% fooof_plot() - plot a FOOOF model output
1+
% fooof_plot() - Plot a FOOOF model.
22
%
33
% Usage:
44
% >> fooof_plot(fooof_results)
@@ -40,13 +40,13 @@ function fooof_plot(fooof_results, log_freqs)
4040
% Plot the full model fit
4141
model = plot(plt_freqs, fooof_results.fooofed_spectrum, 'red');
4242

43-
% Plot the background fit
44-
bg_fit = plot(plt_freqs, fooof_results.bg_fit, 'b--');
43+
% Plot the aperiodic fit
44+
ap_fit = plot(plt_freqs, fooof_results.ap_fit, 'b--');
4545

46-
%% Plot settings
46+
%% Plot Settings
4747

4848
% Apply general plot settings
49-
for plt = [data, model, bg_fit]
49+
for plt = [data, model, ap_fit]
5050
set(plt, 'LineWidth', lw);
5151

5252
% Set alpha value for model - in a wonky way, because Matlab

0 commit comments

Comments
 (0)