Channel information in psd functions


What would be the best way to get channel names info from psd results (e.g. with psd_welch function)?
With the picks option you can select the specific channels to include. If there you have a list, then you have the information already there, but if you select things like “all” or “meg” where could we recover the channel info for each line of the array output?


Also where could I find the units of the results?

Units of psd_welch are (amplitude ** 2) / Hz, where amplitude will be the SI unit for the channel type (V for EEG, T for magnetometers, etc).

For keeping track of channel names, one approach is to store raw.ch_names (or epochs.ch_names or evoked.ch_names) in a list, then use mne.pick_info to get your pick indices. You can then use the pick indices for both the PSD function and for indexing the channel name list.


Thanks a lot @drammock !

For the units (or related) then I have a question:

– When I compute the PSD using mne.time_frequency.psd_welch function I get very different values than when I plot with raw.plot_psd with the very same inputs.

Even if I do log of Welch psd the magnitudes are very different.
Is this related just to the units or to some other additional processing step that I’m not taking into account. How are the plot_psd values computed? And what’s different from Welch? Can I have them as an output of the raw.plot_psd function?

Thanks for your help!

Look at the y-axis labels of the plots, and read the docstring for plot_psd parameters “estimate” and “dB”. These parameters affect exactly what gets computed before it is shown on the plot. Note also that internally, the values in MNE-Python are always in SI units, so the conversion from (say) V/√Hz to μV/√Hz is done by the plotting function so that the numbers labelling the y-axis don’t need to have 20 decimal places (this makes the plot easier to read).

Thanks @drammock !

I tried to plot both mne.time_frequency.psd_welch with some unit transformations and raw.plot_psd side by side in this notebook:

Would you mind having a look and guide me to get equal scales on the Welch psd plot?

I looked at your notebook. One problem is that in this cell
your conversion from \mathrm{T}^2/\mathrm{Hz} to \mathrm{fT}^2/\mathrm{Hz} is wrong. You’re multiplying by (10**2*15) which is 1500. You should be multiplying by 10**(2*15) which is 1000000000000000000000000000000. I didn’t look further than that.


Thanks for catching this @drammock !! I have reviewed it many times!!
Now it matches for psd_welch and plot_psd : ) Yet, when I epoch the data with equal length segments and do a plot_psd_topomap per frequency bands, the range is still different from the plot_psd one (see last figures).
I marked dB=True and Normalize=False. Any other thing that should be taking into account?

1 Like

please create a new thread for this new question. It makes it hard for others to discover your questions (and my answers) when several questions are clustered in one thread, because the thread title only relates to your first question here.

As an aside: your previous error (10**2*15) can be avoided in future if you use scientific notation in your code to represent powers of 10: 1e30 is a valid numeric representation of 10**(2*15) and averts any parentheses-in-the-wrong-place errors.

1 Like

Related to the original question of the post. I copy here too my message on GitHub:

Ok. I think I finally understood. I’ll explain here in case it can be helpful for others (not sure I’m correct so please go ahead if I say something wrong). I’m new to the tool so I appreciate your patience:

  • There’s your raw data. With info about the channels with: raw.ch_names (or equivalents)
  • There’s your epoched data. With info about the channels with: epochs.ch_names (or equivalents)
  • However, there’s no channel information on the outputs of the psd functions, so one can assume it is the same as the raw or epochs passed as inputs. But this is not always true.

CASE 1: if you have specified the picks parameter inside the psd functions

  • In this case an equivalent selection have to be done in the raw/epochs.ch_names list.
  • Since this selection may not be straight forward having just the list of names, something useful could be to create a copy of the epoch just containing the channels you want, e.g. epochs_grad = epochs.copy().pick('grad')
  • Then you apply the psd function just to the epochs_grad and can ensure that the channels in epochs_grad.ch_names are the ones matching.
  • An equivalent thing can be done for the raw.

CASE 2: picks parameter is not specified or set to None

  • By default the psd is not computed in all the channels passed e.g. meg_ref channels are excluded, even when the picks parameter is not specified or set to None, as stated in the documentation. So the channels obtained by raw/epochs.ch_names will not match the ones obtained with the psd functions.
  • The solution proposed before additionally solves this issue that was making my code crash all the time.


  • Pre-selecting your channels before hand creating a copy with .pick (e.g. epochs_grad = epochs.copy().pick('grad')) may help to solve this issue, given that the psd functions don’t provide channel information on the output.