EegPowerBands

Band power per channel: delta to gamma, absolute or as a share of the whole spectrum.

EegPowerBands py
psd
power
Type name
signal:EegPowerBands
Plane
signal
Tags
analysiseeg
Language
python
Tier
in-process
Bundle
eeg
Source
node-bundles/eeg/eeg_power_bands.py
Availability
available

Slots

SlotDirectionType
psdinputARRAY
poweroutputARRAY

Parameters

bands

NameTypeDefaultRangeDoc
deltastring1-4Hz, as `lo-hi`; empty drops the band.
thetastring4-8
alphastring8-13
betastring13-30
gammastring30-50
relativeboolfalseDivide each band by the power of the whole spectrum.

common

NameTypeDefaultRangeDoc
autotriggerboolfalseRun on the node's own schedule, instead of waiting for an input frame. Turn this on for sources; leave it off for transforms driven by their input.
max_frequencyfloat00 … 100Rate cap for this node, read through `frequency_mode`. 0 means uncapped — the node runs as often as the scheduler and its inputs allow.
frequency_modestringupdates_per_secondupdates_per_second | seconds_per_updateHow to read `max_frequency`: as a rate in Hz (updates per second), or as a period in seconds between updates — convenient for very slow nodes.

Source

The current source of this node, as it stands in the goofi repository at node-bundles/eeg/eeg_power_bands.py.

node-bundles/eeg/eeg_power_bands.py
"""EegPowerBands — the power in each EEG band, from a spectrum.

Takes a `Psd` frame: `[.., F]` with the frequencies on its last axis, and answers `[.., bands]`
with the band names on that axis. Power is the density integrated over the band, so it does not
move with the spectrum's resolution. A band is `lo-hi` in Hz; leave one empty to drop it.
"""

import numpy as np
import goofi

BANDS = ["delta", "theta", "alpha", "beta", "gamma"]


class EegPowerBands(goofi.Node):
    """Band power per channel: delta to gamma, absolute or as a share of the whole spectrum."""

    TAGS = ["analysis", "eeg"]
    INPUTS = {"psd": goofi.InputSlot(goofi.DataType.ARRAY, required=True)}
    OUTPUTS = {"power": goofi.DataType.ARRAY}
    PARAMS = {
        "bands": {
            "delta": goofi.StringParam("1-4", doc="Hz, as `lo-hi`; empty drops the band."),
            "theta": goofi.StringParam("4-8"),
            "alpha": goofi.StringParam("8-13"),
            "beta": goofi.StringParam("13-30"),
            "gamma": goofi.StringParam("30-50"),
            "relative": goofi.BoolParam(False, doc="Divide each band by the power of the whole spectrum."),
        }
    }

    def process(self, psd):
        p = self.params.bands
        x = np.asarray(psd.data, dtype=np.float64)
        last = f"dim{x.ndim - 1}"
        freqs = np.asarray(psd.meta["channels"][last], dtype=np.float64)

        names, power = [], []
        for name in BANDS:
            spec = getattr(p, name).strip()
            if not spec:
                continue
            lo, hi = (float(v) for v in spec.split("-"))
            band = (freqs >= lo) & (freqs <= hi)
            names.append(name)
            power.append(np.trapezoid(x[..., band], freqs[band], axis=-1))
        power = np.stack(power, axis=-1)
        if p.relative:
            power = power / np.trapezoid(x, freqs, axis=-1)[..., None]

        axes = {k: v for k, v in psd.meta.get("channels", {}).items() if k != last}
        return power.astype(np.float32), {"channels": {**axes, last: names}}

← All nodes

This reference describes goofi 3.1.0(537cd394), generated from a running instance on 2026-09-06.