.. DO NOT EDIT. .. THIS FILE WAS AUTOMATICALLY GENERATED BY SPHINX-GALLERY. .. TO MAKE CHANGES, EDIT THE SOURCE PYTHON FILE: .. "auto_examples/plot_2_example_add_feature.py" .. LINE NUMBERS ARE GIVEN BELOW. .. only:: html .. note:: :class: sphx-glr-download-link-note :ref:`Go to the end ` to download the full example code. .. rst-class:: sphx-glr-example-title .. _sphx_glr_auto_examples_plot_2_example_add_feature.py: =================== Adding New Features =================== .. GENERATED FROM PYTHON SOURCE LINES 8-12 .. code-block:: Python import py_neuromodulation as nm import numpy as np from typing import Iterable .. GENERATED FROM PYTHON SOURCE LINES 13-16 In this example we will demonstrate how a new feature can be added to the existing feature pipeline. This can be done by creating a new feature class that implements the protocol class :class:`~features.NMFeature` and registering it with the :func:`~features.AddCustomFeature` function. .. GENERATED FROM PYTHON SOURCE LINES 19-24 Let's create a new feature class called `ChannelMean` that calculates the mean signal for each channel. We can optinally make it inherit from :class:`~features.NMFeature` but as long as it has an adequate constructor and a `calc_feature` method with the appropriate signatures it will work. The :func:`__init__` method should take the settings, channel names and sampling frequency as arguments. The `calc_feature` method should take the data and a dictionary of features as arguments and return the updated dictionary. .. GENERATED FROM PYTHON SOURCE LINES 24-59 .. code-block:: Python class ChannelMean: def __init__( self, settings: nm.NMSettings, ch_names: Iterable[str], sfreq: float ) -> None: # If required for feature calculation, store the settings, # channel names and sampling frequency (optional) self.settings = settings self.ch_names = ch_names self.sfreq = sfreq # Here you can add any additional initialization code # For example, you could store parameters for the functions\ # used in the calc_feature method self.feature_name = "channel_mean" def calc_feature(self, data: np.ndarray) -> dict: # First, create an empty dictionary to store the calculated features feature_results = {} # Here you can add any feature calculation code # This example simply calculates the mean signal for each channel ch_means = np.mean(data, axis=1) # Store the calculated features in the feature_results dictionary # Be careful to use a unique keyfor each channel and metric you compute for ch_idx, ch in enumerate(self.ch_names): feature_results[f"{self.feature_name}_{ch}"] = ch_means[ch_idx] # Return the updated feature_results dictionary to the stream return feature_results nm.add_custom_feature("channel_mean", ChannelMean) .. GENERATED FROM PYTHON SOURCE LINES 60-61 Now we can instantiate settings and observe that the new feature has been added to the list of features .. GENERATED FROM PYTHON SOURCE LINES 61-65 .. code-block:: Python settings = nm.NMSettings() # Get default settings settings.features .. rst-class:: sphx-glr-script-out .. code-block:: none {'bandpass_filter': False, 'bispectrum': False, 'bursts': True, 'channel_mean': True, 'coherence': False, 'fft': True, 'fooof': False, 'linelength': True, 'mne_connectivity': False, 'nolds': False, 'raw_hjorth': True, 'return_raw': True, 'sharpwave_analysis': True, 'stft': False, 'welch': True} .. GENERATED FROM PYTHON SOURCE LINES 66-67 Let's create some artificial data to demonstrate the feature calculation. .. GENERATED FROM PYTHON SOURCE LINES 67-85 .. code-block:: Python N_CHANNELS = 5 N_SAMPLES = 10000 # 10 seconds of random data at 1000 Hz sampling frequency data = np.random.random([N_CHANNELS, N_SAMPLES]) stream = nm.Stream( sfreq=1000, data=data, settings = settings, sampling_rate_features_hz=10, verbose=False, ) feature_df = stream.run() columns = [col for col in feature_df.columns if "channel_mean" in col] feature_df[columns] .. raw:: html
channel_mean_ch0_avgref channel_mean_ch1_avgref channel_mean_ch2_avgref channel_mean_ch3_avgref channel_mean_ch4_avgref
0 -0.003151 0.003845 0.009986 -0.008624 -0.002056
1 -1.000000 -1.000000 1.000000 1.000000 -1.000000
2 -1.183055 0.067441 0.127422 -1.388348 1.386479
3 0.971766 0.420605 -1.230613 -0.665998 0.684274
4 1.602812 -1.861613 1.262754 -1.847107 1.170723
... ... ... ... ... ...
86 -0.223974 0.650751 0.052932 -0.559971 0.342396
87 -0.469088 0.560148 -0.411298 0.418785 0.369015
88 -0.284326 0.633788 -0.878672 1.154053 -0.013363
89 -1.228100 0.222809 0.037242 1.437820 -0.544140
90 -0.826018 -0.044380 0.340241 0.805401 -0.586588

91 rows × 5 columns



.. GENERATED FROM PYTHON SOURCE LINES 86-87 Remove feature so that it does not interfere with other examples .. GENERATED FROM PYTHON SOURCE LINES 87-91 .. code-block:: Python nm.remove_custom_feature("channel_mean") .. rst-class:: sphx-glr-timing **Total running time of the script:** (0 minutes 0.849 seconds) .. _sphx_glr_download_auto_examples_plot_2_example_add_feature.py: .. only:: html .. container:: sphx-glr-footer sphx-glr-footer-example .. container:: sphx-glr-download sphx-glr-download-jupyter :download:`Download Jupyter notebook: plot_2_example_add_feature.ipynb ` .. container:: sphx-glr-download sphx-glr-download-python :download:`Download Python source code: plot_2_example_add_feature.py ` .. container:: sphx-glr-download sphx-glr-download-zip :download:`Download zipped: plot_2_example_add_feature.zip ` .. only:: html .. rst-class:: sphx-glr-signature `Gallery generated by Sphinx-Gallery `_