How to get the peak value of each channel in mne

I would like to ask if there is a way to get the peak value of each channel in mne.
I am using mne’s evoke get_peak function to get the peak, but this seems to return only the largest one among all channels, is there any way to get the peak of each channel in a certain time period?

N100 = evoked_roi.get_peak(tmin = 0.1,tmax = 0.2,
time_as_index = True,
return_amplitude=True)

I’m looking forward to your reply. Thank you very much for your help!

  • MNE-Python version: MNE 0.22.0
  • operating system: mac 10.14.6, jupyter lab 3.0.5

If you use

foobar = evoked_roi.get_data(picks=[:], start=1, stop=3)

you’ll get a matrix consisting of (channels x samples) in range start to stop.

next step would be to use either scipy (scipy.signal.find_peaks) if you want to find multiple peaks or numpy if you want to find only one peak, so for instance :

numpy.argmax(foobar, axis=1)

this should return a vector consisting of the indices of the samples containing the maximum values per channel.

This is how I would approach this, maybe somebody knows a more elegant solution or there is something that comes out of the box with mne?

Hope that helps.

1 Like

Thank you very much for your reply!

It seems that the evoke object has no get_data parameter, I used evoke_roi.data[:,100:150] to get the data. (The Evoked data structure: evoked/averaged data — MNE 0.23.dev0 documentation)
But the two methods you mentioned: scipy.signal.find_peaks and numpy.argmax seem to extract peaks from one-dimensional data.
The webpage of scipy.signal.find_peaks says that This function takes a 1-D array and finds all local maxima by simple comparison of neighboring values.
(scipy.signal.find_peaks — SciPy v1.6.0 Reference Guide)

You are right that scipy.signal.find_peaks operates on 1D data. But numpy.argmax can take arrays of any shape, and has an axis parameter, so @RuKrei’s second suggestion should work as long as you’re only interested in the (index of the) single highest value per channel.

(Aside: the .get_data() method is for Raw and Epochs objects, Evokeds are usually much smaller (in terms of memory) so Evoked data is always automatically preloaded into RAM. That is why it has a .data attribute instead of a .get_data() method.)

Thank you very much for your reply!
I have two questions about the function of numpy.argmax and would like to ask you.
The first is that it seems impossible to get the peak value of each channel.
I use code
peak = np.argmax(evoke2_roi[150:200]) (50 time points and 11 channels)
But it returns only one value, not the peak value of all channels. I also tried adding axis=0, or axis=1, but they all reported errors.
The error is as follows
peak = np.argmax(evoke2_roi[150:200], axis=0)
Shape of passed values is (11, 1), indices imply (50, 11)
peak = np.argmax(evoke2_roi[150:200], axis=1)
Shape of passed values is (50, 1), indices imply (50, 11)
I find it strange, it seems that the code in the official interface can run normally.numpy.argmin — NumPy v1.20 Manual
Another problem is that the np.argmax function seems to only return the time point corresponding to the peak, but it does not return the peak.

I don’t think that can really be the code you’re using, since the part evoke2_roi[150:200] should already fail (Evoked object is not subscriptable). Unless evoke2_roi is already a NumPy array? In which case probably it should say evoke2_roi[:, 150:200] (note the extra : saying to keep all channels, and apply the slice across the time axis). So assuming your evoke2_roi is a NumPy array:

time_of_interest = evoke2_roi[:, 150:200]
indices = np.argmax(time_of_interest, axis=1)
peak_values = time_of_interest[:, indices]

Thank you very much for your help, this is indeed working and very effective!