Open kingjr opened 8 years ago
Hey! Yep, the function I wrote for this is here:
https://github.com/choldgraf/ecogtools/blob/master/tfr.py#L244
It lets you specify a few sub-bands if you want. It'll do a bandpass for each, and will average them together (scaling them first, optionally).
Thanks Chris. I wrote this to make it memory/CPU efficient; it works with multitapers and morlet, I can add the hilbert too; it's probably going to be fast too.
The main design change is that
split_size
) so that if you have a powerful workstation, you can minimize the channel loop, but if you work with a laptop, you can use the same function.Also, in my Matlab code I transformed the power in log base before normalizing. But I didn't write why, nor a ref... So I'm not sure it was a good idea in the first place
def extract_amplitude(inst, freqs, normalize=True, method='morlet',
picks=None, log=False, copy=False, split_size=1):
from tqdm import tqdm # progress bar
from mne.io.pick import _pick_data_channels
from mne.time_frequency import cwt_morlet
from mne.time_frequency.tfr import _induced_power_mtm
from jr.stats import median_abs_deviation
if picks is None:
picks = _pick_data_channels(inst.info, with_ref_meg=False)
if copy:
inst = inst.copy()
data = inst._data[picks, :]
sfreq = inst.info['sfreq']
# Loop across chunks of channels to optimize memory/CPU
chans_splits = np.array_split(np.arange(len(picks)),
np.ceil(float(len(picks)) / split_size))
for chans in tqdm(chans_splits):
if method == 'morlet':
x = cwt_morlet(data[chans, :], sfreq, freqs,
use_fft=True, n_cycles=7.0, zero_mean=False)
power = (x * x.conj()).real
del x
elif method == 'mtm':
power, itc = _induced_power_mtm(data[None, chans, :], sfreq=sfreq,
frequencies=freqs, n_jobs=-1,
zero_mean=True, verbose='INFO')
del itc
else:
raise NotImplementedError('Unknown method %s' % method)
if log:
np.log(1 + power, out=power) # in place
if normalize:
mean = np.median(power, axis=2)[:, :, np.newaxis]
std = median_abs_deviation(power, axis=2)[:, :, np.newaxis]
std[std == 0] = 1.
power -= mean
power /= std
mean_power = np.mean(power, axis=1)
inst._data[picks[chans], :] = mean_power
del power, mean_power
return inst
e.g.
freqs = np.logspace(np.log10(60), np.log10(150), 10)
raw = extract_amplitude(raw, freqs, method='morlet', split_size=10)
for from jr.stats import median_abs_deviation
see https://github.com/kingjr/jr-tools/blob/master/jr/stats/base.py#L484
Nice! Thanks for the updated function. I've seen papers do log-transforming and others that don't, I don't think there's a rule one way or another. In my case, I usually z-score data at some point anyway (within frequency bands) so I haven't worried too much about it.
Do you have any interest in a co-maintained set of ecog tools? We could create a new repo for it and I could port over the relevant code from this repository into that one. I'd be happy to come up with functions that are crowdsourced for usefulness and correctness (well, even if the crowd is an N of 2). I'm imagining functions that are useful, but maybe too specific to contribute to MNE. Or maybe it'd be too specific? I just imagine that there are lots of ecog pythonistas out there implementing their own functions, no reason we should all be reinventing the wheel.
Absolutely. I'm happy to contribute here directly, no need to port it elsewhere (except if you want to keep a dirty repo for yourself.). Eventually, I can transfer ecoggui for the elec location here too. (I'm waiting to get my next patient before looking at it again, hence the waiting)
I think the good move would be to use this as a buffer before MNE. Once we have a bit of experience with the functions we wrote we can propose to make them available to MNE with an example for each. WDYT?
I think that's a good idea - it's pretty much how I've tried to structure code here already (using MNE docstring style as much as possible and structuring objects similarly etc). Want me to just give you admin rights? If there are functions in here that are too specific to my stuff then I can put that in another repository.
Sure. Shall we set up Travis ?
On Friday, 11 March 2016, Chris Holdgraf notifications@github.com wrote:
I think that's a good idea - it's pretty much how I've tried to structure code here already (using MNE docstring style as much as possible and structuring objects similarly etc). Want me to just give you admin rights? If there are functions in here that are too specific to my stuff then I can put that in another repository.
— Reply to this email directly or view it on GitHub https://github.com/choldgraf/ecogtools/issues/1#issuecomment-195631624.
Sounds like a good idea - I don't have much experience setting Travis up but it's something I've been wanting to figure out for a while now. I assume it is basically just setting up a random number generator that has a 99% probability of telling you that your code is wrong on each query, is that correct? ;)
On Fri, Mar 11, 2016 at 8:41 PM, Jean-Rémi KING notifications@github.com wrote:
Sure. Shall we set up Travis ?
On Friday, 11 March 2016, Chris Holdgraf notifications@github.com wrote:
I think that's a good idea - it's pretty much how I've tried to structure code here already (using MNE docstring style as much as possible and structuring objects similarly etc). Want me to just give you admin rights? If there are functions in here that are too specific to my stuff then I can put that in another repository.
— Reply to this email directly or view it on GitHub <https://github.com/choldgraf/ecogtools/issues/1#issuecomment-195631624 .
— Reply to this email directly or view it on GitHub https://github.com/choldgraf/ecogtools/issues/1#issuecomment-195659534.
I actually don't know either. Good place to learn.
In case you haven't seen, they just created an mne-sandbox rep. I'm not sure whether this wouldn't be a good place too. On the plus side we'd have their feedbacks right away. On the minus one, it'll be heavier (more testing, more integration with all types of MEG specificies, e.g. projections etc. WDYT?
Hey - jumping back on this now that graduation craziness has ended. I am a bit torn between having an ecog-specific repository and pushing things to MNE-sandbox. I guess the question is where there is enough ecog-specific stuff to warrant its own repository. If we think that's the case, then we can create an MNE-ecog repo or something like this. However, IMO if there's significant overlap with EEG/MEG then I'm happy to just contribute this to MNE-sandbox/python. It'd be cool if we could improve functionality in general for eeg / ieeg now that both types are supported natively.
So I guess my intuition is that we should make an mne_sandbox.ecog submodule and then build things in there.
We should also figure out a good ECoG dataset to use for testing. Maybe we can take an existing dataset, anonymize it, remove metadata about the task except for when "events" happen, and choose a bunch of semi-random points on the MNI brain that roughly reflect the grid coverage.
Hey :)
Do you have a pipeline for extract gamma activity from the raw data, instead of doing it at the epoch level?