Time Frequency Response Comparison with Brainstorm

Hello MNE users,

I am trying to compare the time frequency response (morlet wavelets) obtained from MNE to that with the one obtained from brainstorm. For comparison, I would ideally want the resolution and the methods of baseline normalization for both MNE and Brainstorm to be the same. On brainstorm, I performed the normalization using Event-related pertubation (ERS/ERD), however, I could not find that method in MNE (baseline_mode). Is there any way to perform ERS/ESD normalization on MNE?

Also, a silly question but how do we set the display axis( frequency in my case) to be a linear step of 10 (10,20,30,40,50,…etc) on MNE?


Yes there is, you can pass mode='percent' to get ERD/ERS (see also the ERD/ERS maps example).

And how do we get finer resolution with Time frequency analysis ? Instead of big blocks , is there a way to see the time frequency response as that shown by brainstorm ( the first figure above)

You can pass a range of frequencies as the freqs argument to tfr_multitaper() (or whatever t/f function you are using), e.g. freqs=np.arange(1, 101) for 1Hz steps.

Hi @Subrat_Bastola,
in addition to what Clemens already said, bear in mind that to have the same result in mne as in Brainstorm you would have to use the same parameters as the ones Brainstorm uses. So in the case of wavelets you’d have to set the same n_cycles in tfr_morlet (because this is what ultimately influences your frequency resolution). You will also notice that mne, unlike FieldTrip for example, does not trim the edges of the TFR space where your time-frequency window extends beyond the range of the data. In your figure you see that as the artifacts on the left and right edges of the time extent. This is worth remembering when setting the time range used for baseline.

Thank you for the reply. I have one more question. How do I perform the TFR for magnitude instead of power in MNE? Brainstorm has two options: magnitude and power. Does MNE has a way to calculate Magnitude in TFR and not power?

@Subrat_Bastola I don’t think you have that option in mne, but power is magnitude ** 2, so you can get magnitude from power with np.sqrt(power).

Hi Mikolaj,

I am sharing an example of the two TFRs for the same sensor that I obtained using brainstorm and MNE respectively.

The evoked response obtained from brainstorm and MNE were quite similar, however with TFR (morlet wavelets), I see considerable difference between those produced by brainstorm and MNE?

On brainstom , I did Morlet wavelets followed by ERS/D baseline normalization, for MNE, I set my baseline mode= ‘percent’. The baseline period for both brainstorm and MNE were (-200ms, -10 ms)


freqs = np.arange(1,71)
n_cycles = freqs / 3 

power, itc = tfr_morlet(epochs, freqs=freqs, n_cycles=n_cycles, use_fft=True,
                        return_itc=True, decim=3, n_jobs=1)


why are these plots so different? is there something that I did wrong?

My advice is to have a look at the settings of the plot in Brainstorm, what are its vmin and vmax?
Then try to set the same value in MNE.

In addition to what @BarryLiu97 mentions it seems that the TFR is done differently in Brainstorm - you don’t see the edge artifacts there and as a result baseline correction gives different results (in mne your baseline period contains these edge artifacts which results for example in overestimating the changes in low frequencies).
What are the limits of your epochs? If you only have 200 ms prestimulus then I would not set n_cycles to an equivalent of around 0.333 seconds because in such case no wavelet is fully contained in the prestimulus period.
@larsoner @agramfort - situations like this make me think we should consider NaNing out the timepoints where the time-frequency window extends beyond data limits, like FieldTrip does.

In addition what has been said, it also looks like Brainstorm subtracts the evoked component before TFR computation.

@cbrnr @mmagnuski @agramfort

Above is the Time frequency plot obtained for the same sensor in brainstorm(left) and on MNE(right). For brainstorm I computed the Morlet wavelets for the average file of my evoked response and then normalized it using zscore.

For MNE, I used the following:

freqs = np.arange(1,71)
n_cycles = freqs / 5.  # different number of cycle per frequency
power, itc = mne.time_frequency.tfr_morlet(epochs['D5'], freqs=freqs, n_cycles=n_cycles, use_fft=True,  return_itc=True, decim=3, n_jobs=1)

baseline_mode = 'zscore'
baseline = (None, -0.01)

power.plot(picks='MEG0112', baseline=baseline, mode=baseline_mode,cmap='jet')

Why such drastic difference in the TFR?

Welcome back @Subrat_Bastola,
I don’t think we finished discussing this topic in this thread. I think it might be better if you moved this message to that thread.
But to respond to your question (“Why such drastic difference?”) shortly: it is hard to tell exactly. But it is likely due to a few factors: different n_cycles settings across frequencies in brainstorm than what you set in mne, different baseline (which can be due to many things - we’ve started discussing this in the previous thread) or maybe different treatment of the signal before the computing the TFR.

do I understand you correctly that in brainstorm you perform the TFR computation on an evoked response (average across epochs)? If so this is a very likely candidate for the difference in the output between brainstorm and mne. In the mne code you provide you perform the TFR on the epochs (so first TFR on every epoch, then average), not on the evoked (first average, then TFR).

Thanks @mmagnuski for your answer. I really appreciate you taking time out to respond. Is there a way we can perform TFR directly on evoked response in MNE?
Because when I put my evoked object as an argument to the method ( also putting return itc= False) it gives me an iteration error.

Passing evoked should work (according to the docs), if it doesn’t then it may be a bug. Could you paste the whole error message that you are getting?

FYI, I merged the two threads.

1 Like

Great, thanks @cbrnr, I looked for that option but coldn’t find it.