custom frequency bands for calculating power band features

Dear community members,

I’m extracting band power features from single channel eeg data with mne_features and I need to know if it is possible to create custom frequency bands for calculating power. For example, I’d like to have normalised and relative power over these ranges:

“delta”: [0.5, 3.5], “theta”: [3.5, 7.5], “alpha1”: [7.5, 9.5],“alpha2”: [9.5,12.5], “beta1”: [12.5, 17.5], “beta1”: [17.5, 25], “gamma”: [25,40]

I tried this code, and it returned 6 final results for each epoch, whereas I expected 7 data points based on the frequency band definition. .

bands = {“delta”: [0.5, 3.5], “theta”: [3.5, 7.5], “alpha1”: [7.5, 9.5],“alpha2”: [9.5,12.5], “beta1”: [12.5, 17.5], “beta1”: [17.5, 25], “gamma”: [25,40]}
X_psd_2 = extract_features(X = epochs.get_data([‘F7’]),
sfreq = epochs.info[‘sfreq’],
selected_funcs = [‘pow_freq_bands’],
funcs_params = {‘pow_freq_bands__freq_bands’: bands,
‘pow_freq_bands__normalize’ : True})

Hello,

beta1 occurs twice, I suppose the second one needs to be beta2 instead.

Best wishes,
Richard

2 Likes

Thanks for your response @richard ,
I fixed that and it worked but now I am faced with this error while using the same code:
_check_input() missing 1 required keyword-only argument: 'reset’
I have no idea what had happened.

Can you give the full traceback of the error? It suggests the private method _check_input() is used with an argument provided as a positional argument instead of a keyword argument somewhere. i.e. it should be _check_input(positional_arguments, reset=..., other_keword_argument)

@mscheltienne, Thanks for your response,
Of course, I’ll share the entire error trace back, which consists of 21 frames:
Specifically, I’d like to extract spectral and temporal properties from “F7” eeg channel data.

bands = {“delta”: [0.5, 3.5], “theta”: [3.5, 7.5],“alpha1”: [7.5, 9.5],“alpha2”: [9.5,12.5], “beta1”: [12.5, 17.5], “beta2”: [17.5, 25], “gamma”: [25,40], ‘total’:[0.5,40]}

X_psd_2 = extract_features(X = epochs.get_data([‘F7’]),
sfreq = epochs.info[‘sfreq’],
selected_funcs = [‘pow_freq_bands’] ,
funcs_params = {‘pow_freq_bands__freq_bands’: bands,
‘pow_freq_bands__normalize’ : True})


TypeError Traceback (most recent call last)
in ()
4 selected_funcs = [‘pow_freq_bands’] ,
5 funcs_params = {‘pow_freq_bands__freq_bands’: bands,
----> 6 ‘pow_freq_bands__normalize’ : True})

21 frames
/usr/local/lib/python3.7/dist-packages/mne_features/feature_extraction.py in extract_features(X, sfreq, selected_funcs, funcs_params, n_jobs, return_as_df)
433 extractor.set_params(**funcs_params)
434 res = joblib.Parallel(n_jobs=n_jobs)(joblib.delayed(_apply_extractor)(
→ 435 extractor, X[j, :, :], return_as_df) for j in range(n_epochs))
436 feature_names = res[0][1]
437 res = list(zip(*res))[0]

/usr/local/lib/python3.7/dist-packages/joblib/parallel.py in call(self, iterable)
1041 # remaining jobs.
1042 self._iterating = False
→ 1043 if self.dispatch_one_batch(iterator):
1044 self._iterating = self._original_iterator is not None
1045

/usr/local/lib/python3.7/dist-packages/joblib/parallel.py in dispatch_one_batch(self, iterator)
859 return False
860 else:
→ 861 self._dispatch(tasks)
862 return True
863

/usr/local/lib/python3.7/dist-packages/joblib/parallel.py in _dispatch(self, batch)
777 with self._lock:
778 job_idx = len(self._jobs)
→ 779 job = self._backend.apply_async(batch, callback=cb)
780 # A job can complete so quickly than its callback is
781 # called before we get here, causing self._jobs to

/usr/local/lib/python3.7/dist-packages/joblib/_parallel_backends.py in apply_async(self, func, callback)
206 def apply_async(self, func, callback=None):
207 “”“Schedule a func to be run”""
→ 208 result = ImmediateResult(func)
209 if callback:
210 callback(result)

/usr/local/lib/python3.7/dist-packages/joblib/_parallel_backends.py in init(self, batch)
570 # Don’t delay the application, to avoid keeping the input
571 # arguments in memory
→ 572 self.results = batch()
573
574 def get(self):

/usr/local/lib/python3.7/dist-packages/joblib/parallel.py in call(self)
261 with parallel_backend(self._backend, n_jobs=self._n_jobs):
262 return [func(*args, **kwargs)
→ 263 for func, args, kwargs in self.items]
264
265 def reduce(self):

/usr/local/lib/python3.7/dist-packages/joblib/parallel.py in (.0)
261 with parallel_backend(self._backend, n_jobs=self._n_jobs):
262 return [func(*args, **kwargs)
→ 263 for func, args, kwargs in self.items]
264
265 def reduce(self):

/usr/local/lib/python3.7/dist-packages/mne_features/feature_extraction.py in _apply_extractor(extractor, X, return_as_df)
199 Not None, only if return_as_df is True.
200 “”"
→ 201 X = extractor.fit_transform(X)
202 feature_names = None
203 if return_as_df:

/usr/local/lib/python3.7/dist-packages/sklearn/pipeline.py in fit_transform(self, X, y, **fit_params)
1170 sum of n_components (output dimension) over transformers.
1171 “”"
→ 1172 results = self._parallel_func(X, y, fit_params, _fit_transform_one)
1173 if not results:
1174 # All transformers are None

/usr/local/lib/python3.7/dist-packages/sklearn/pipeline.py in _parallel_func(self, X, y, fit_params, func)
1202 **fit_params,
1203 )
→ 1204 for idx, (name, transformer, weight) in enumerate(transformers, 1)
1205 )
1206

/usr/local/lib/python3.7/dist-packages/joblib/parallel.py in call(self, iterable)
1041 # remaining jobs.
1042 self._iterating = False
→ 1043 if self.dispatch_one_batch(iterator):
1044 self._iterating = self._original_iterator is not None
1045

/usr/local/lib/python3.7/dist-packages/joblib/parallel.py in dispatch_one_batch(self, iterator)
859 return False
860 else:
→ 861 self._dispatch(tasks)
862 return True
863

/usr/local/lib/python3.7/dist-packages/joblib/parallel.py in _dispatch(self, batch)
777 with self._lock:
778 job_idx = len(self._jobs)
→ 779 job = self._backend.apply_async(batch, callback=cb)
780 # A job can complete so quickly than its callback is
781 # called before we get here, causing self._jobs to

/usr/local/lib/python3.7/dist-packages/joblib/_parallel_backends.py in apply_async(self, func, callback)
206 def apply_async(self, func, callback=None):
207 “”“Schedule a func to be run”""
→ 208 result = ImmediateResult(func)
209 if callback:
210 callback(result)

/usr/local/lib/python3.7/dist-packages/joblib/_parallel_backends.py in init(self, batch)
570 # Don’t delay the application, to avoid keeping the input
571 # arguments in memory
→ 572 self.results = batch()
573
574 def get(self):

/usr/local/lib/python3.7/dist-packages/joblib/parallel.py in call(self)
261 with parallel_backend(self._backend, n_jobs=self._n_jobs):
262 return [func(*args, **kwargs)
→ 263 for func, args, kwargs in self.items]
264
265 def reduce(self):

/usr/local/lib/python3.7/dist-packages/joblib/parallel.py in (.0)
261 with parallel_backend(self._backend, n_jobs=self._n_jobs):
262 return [func(*args, **kwargs)
→ 263 for func, args, kwargs in self.items]
264
265 def reduce(self):

/usr/local/lib/python3.7/dist-packages/sklearn/utils/fixes.py in call(self, *args, **kwargs)
209 def call(self, *args, **kwargs):
210 with config_context(**self.config):
→ 211 return self.function(*args, **kwargs)
212
213

/usr/local/lib/python3.7/dist-packages/sklearn/pipeline.py in _fit_transform_one(transformer, X, y, weight, message_clsname, message, **fit_params)
891 with _print_elapsed_time(message_clsname, message):
892 if hasattr(transformer, “fit_transform”):
→ 893 res = transformer.fit_transform(X, y, **fit_params)
894 else:
895 res = transformer.fit(X, y, **fit_params).transform(X)

/usr/local/lib/python3.7/dist-packages/sklearn/base.py in fit_transform(self, X, y, **fit_params)
845 if y is None:
846 # fit method of arity 1 (unsupervised transformation)
→ 847 return self.fit(X, **fit_params).transform(X)
848 else:
849 # fit method of arity 2 (supervised transformation)

/usr/local/lib/python3.7/dist-packages/mne_features/feature_extraction.py in fit(self, X, y)
85 self
86 “”"
—> 87 self._check_input(X)
88 _feature_func = _get_python_func(self.func)
89 if hasattr(_feature_func, ‘get_feature_names’):

TypeError: _check_input() missing 1 required keyword-only argument: ‘reset’

This bug has been fix on the github repository:

in this commit: passing reset=True in _check_input() · mne-tools/mne-features@629f5d4 · GitHub

To get rid of it, you could update to the development version, either by cloning the repository and then doing:

python setup.py install

Or by using the pip command:

pip install git+https://github.com/mne-tools/mne-features.git#egg=mne_features

@mscheltienne Many thanks for your help.