Skip to content

Channel Metrics

This demo demonstrates how to calculate and visualize channel quality metrics for identifying bad channels and detecting artifacts.

What are Channel Metrics?

Channel quality metrics quantify various characteristics of the EEG signal at each electrode. These metrics help identify problematic channels that may need repair or rejection before analysis.

Variance:

  • Measures overall signal power/amplitude variability at each channel

  • High variance may indicate artifacts (muscle, movement)

  • Very low variance suggests poor contact or disconnected electrode

Kurtosis:

  • Measures the distribution shape (tailedness) of the signal

  • High kurtosis indicates spiky signals with extreme values (artifacts)

Correlation:

  • Average correlation between a channel and its spatial neighbors

  • Low correlation suggests the channel is behaving differently from nearby electrodes

  • Detects bad contacts, bridging, or electrode-specific noise

Joint Probability:

  • Statistical outlier detection across channels simultaneously

  • Identifies channels that deviate from the typical multi-channel pattern

  • Combines information from variance and correlation metrics

Use Cases

Quality control:

  • Identify bad channels before epoching or averaging

  • Screen data quality during or after acquisition

  • Track bad channels across participants - if a specific electrode is consistently bad across multiple participants, this may indicate a broken electrode or faulty electrode set that needs replacement

Workflow Summary

This demo shows channel quality assessment workflows:

Basic Channel Metrics

  • Load and preprocess raw data (average reference, high-pass filter)

  • Calculate channel joint probability metrics

  • Identify channels with extreme values

EOG Correlation Analysis

  • Compute vertical and horizontal EOG channels

  • Detect EOG onsets automatically

  • Calculate correlation between EEG channels and EOG

  • Partition bad channels into EOG-related vs. non-EOG artifacts

Metric Interpretation

  • Add z-score columns for standardized thresholds

  • Identify channels that are artifact-related vs. bad contacts

  • Guide decisions on repair (interpolation) vs. rejection

Code Examples

Show Code
julia
# Demo: Channel Metrics
# Shows how to compute and visualize channel-wise metrics (variance, kurtosis, etc.).

using EegFun
# Note: EegFun.example_path() resolves bundled example data paths.
# When using your own data, simply pass the file path directly, e.g.:
# dat = EegFun.read_raw_data("/path/to/your/data.bdf")

# read raw data
dat = EegFun.read_raw_data(EegFun.example_path("data/bdf/example1.bdf"));

# read and prepare layout file
layout = EegFun.read_layout(EegFun.example_path("layouts/biosemi/biosemi72.csv"));
EegFun.polar_to_cartesian_xy!(layout)

dat = EegFun.create_eegfun_data(dat, layout)

# minimal preprocessing
EegFun.rereference!(dat, :avg)
EegFun.highpass_filter!(dat, 0.1)

# extreme value bool column
EegFun.is_extreme_value!(dat, 100)

# channel joint probability
channel_joint_probability = EegFun.channel_joint_probability(dat)
channel_joint_probability = EegFun.channel_joint_probability(dat, sample_selection = EegFun.samples_not(:is_extreme_value_100))

# Calculate EOG signals
EegFun.channel_difference!(
    dat,
    channel_selection1 = EegFun.channels([:Fp1, :Fp2]),
    channel_selection2 = EegFun.channels([:IO1, :IO2]),
    channel_out = :vEOG,
); # vertical EOG = mean(Fp1, Fp2) - mean(IO1, I02)
EegFun.channel_difference!(
    dat,
    channel_selection1 = EegFun.channels([:F9]),
    channel_selection2 = EegFun.channels([:F10]),
    channel_out = :hEOG,
); # horizontal EOG = F9 - F10

EegFun.detect_eog_onsets!(dat, 50, :vEOG, :is_vEOG)
EegFun.detect_eog_onsets!(dat, 30, :hEOG, :is_hEOG)


# Calculate correlations between all channels and EOG channels
cm = EegFun.correlation_matrix_dual_selection(
    dat,
    sample_selection = EegFun.samples(),  # All samples
    channel_selection1 = EegFun.channels(),  # All EEG channels
    channel_selection2 = EegFun.channels([:vEOG, :hEOG]),  # EOG channels
)
EegFun.add_zscore_columns!(cm)

bad_channels = [:Fp1, :AF3]
non_eog_related, eog_related = EegFun.partition_channels_by_eog_correlation(bad_channels, cm)

See Also