FOOOF Process Options and Comparison to Python Implementation

Greetings BST Community,

I am interested in using the FOOOF algorithm as implemented in Brainstorm (with the Matlab option). I initially used the Brainstorm default values. After inspecting the results, it appears the algorithm with the default parameters may be under-fitting for my dataset. Accordingly, I was hoping to use the guidelines for this scenario as described in the FOOOF python page.

There, it states the following:

  • First check and perhaps loosen any restrictions from 'max_n_peaks' and 'min_peak_height'
  • Try updating 'peak_threshold' to a lower value

Within the Brainstorm implementation, 'max_n_peaks' and 'min_peak_height' are clearly there. However, I am having trouble figuring out which parameter in Brainstorm is equivalent to 'peak_threshold'.

On the python page, 'peak_threshold' is defined as:

The threshold, in terms of standard deviation of the aperiodic-removed power spectrum, above which a data point must pass to be considered a candidate peak. Once a candidate peak drops below this threshold, the peak search is halted (without including the most recent candidate).

I think I may be confusing the 'peak_threshold' and 'min_peak_height' parameters, and that one may be used (rather than both being options for different procedures). On the python page it also states:

peak_threshold (in units of standard deviation)** default: 2.0

The threshold, in terms of standard deviation of the aperiodic-removed power spectrum, above which a data point must pass to be considered a candidate peak. Once a candidate peak drops below this threshold, the peak search is halted (without including the most recent candidate).

min_peak_height (units of power - same as the input spectrum)** default: 0

The minimum height, above the aperiodic fit, that a peak must have to be extracted in the initial fit stage. Once a candidate peak drops below this threshold, the peak search is halted (without including the most recent candidate). Note that because this constraint is enforced during peak search, and prior to final peak fit, returned peaks are not guaranteed to surpass this value in height.

There are two different height-related halting conditions for the peak searching. By default, the relative (standard-deviation based) threshold is defined, whereas the absolute threshold is set to zero (this default is because there is no general way to set this value without knowing the scale of the data). If both are defined, both are used and the peak search will halt when a candidate peak fails to pass either the absolute, or relative threshold.

My question is: based on the last paragraph above, in Brainstorm, is 'peak_threshold' simply not included due to assuming the input to FOOOF will be a PSD with known units (meaning 'min_peak_height' could be used)?

Thank you,
Paul

@Luc @Sylvain?

Hi Paul,

Thank you for reaching out, your investigations have been very careful! Indeed, the peak_threshold option is not visible in the options pane.

As I remember, the MATLAB version of FOOOF was developed at a time where users were unable to change the peak_threshold hyperparameter in Python. As I can now see, the Python developers have now enabled users to change this settings using a keyword argument. It is still possible to retune this hyperparameter in Brainstorm, but for now 1) it can only be done by changing its value in your process_fooof.m file and 2) it will not reset to 2.0 between sessions and will only be automatically reset following Brainstorm updates. If you are able to access your process_fooof.m file in MATLAB ("edit process_fooof" after starting Brainstorm) then you will see the hard-coded value for peak_threshold at line 136 (which you can modify to whatever value you wish).

Just a friendly warning, but I generally advocate for keeping this value at 2 std whenever possible. Lowering this value greatly increases the odds of fitting noise in the spectrum, as the only reason for the algorithm to miss a would-be peak (assuming you have set the min_peak_height to a very small number or 0) is because it is essentially indistinguishable from noise in the spectrum. If you are at liberty to do so, adding more windows to your PSD can smooth out the data (reducing noise) and make hard-to-detect peaks a little more clear.

I hope you have found this information helpful, and I wish you the best of luck in fitting your PSDs! If you have any other questions or concerns, feel free to reach out.

Luc

Hi Luc,

Thank you for the very helpful reply!

I did have some more FOOOF rather than strictly BST-related questions if you don't mind me asking:

  • From your experience, is there a typical range for 'min_peak_height' you find using with your own data (or does the default of 3 dB work for you in most cases)?

  • Using the peak values (for example, when extracting them from a FOOOF model within BST as described in the tutorial), I'm curious if you have ever seen someone look at not the peak/height value exactly, but perhaps the mean of the Gaussian-defined peak (for example, the mean peak values over the width of the peak, or even area under the curve). From my understanding, the peak values over frequency that are returned and the actual peak amplitude value (that you get FOOOF.data in the BST implementation) do not perfectly correspond. I'm sure there's much I'm missing that would imply one shouldn't be looking at for example mean or area under the curve, but was curious regardless.

Thank you,
Paul

Hi Paul,

Certainly, happy to be of help!

  • I should preface my response by saying that I tend to choose hyperparameters that lean on the side of caution (reducing type 1 error), which can sometimes lead to missing genuine spectral peaks. That being said: for PSDs (>10 seconds of data, 1-2s windows with 50% overlap), 3 dB is generally a safe bet. When you have high spectral SNR (i.e., low spectral noise) I often find it appropriate to lower this threshold down to as low as 1 dB. Some set it to 0 dB (same as disabling), which sometimes works since the relative threshold is always in effect. When spectral noise is higher (e.g., time-resolved analyses/SPRiNT), I advise a higher threshold such as 5 dB.

  • I have never heard of someone doing this exactly, but it is an interesting question to raise about the data! One could think of AUC as evaluating an interaction effect between the amplitude and bandwidth, since the AUC of a gaussian is the product of both divided by a constant. It is true that the max peak power across sampled frequencies may be lower than peak amplitude: this happens because the model (peak amplitude) is inferred from the data (which contains some noise that the model has to fit through). As for looking at mean power across the gaussian, it would only be differ meaningfully from AUC/amplitude if it were constrained to a frequency range, which goes back to band-limited analyses, which FOOOF is designed in part to avoid. Still, as long as there is some justification for a particular analytical approach I think the sky is the limit.

N = 1, but I hope this is helpful! Happy to answer any other questions.

Luc