Something wrong with EEG headset

MNE version: e.g. 1.13.0

Operating system: Ubuntu 24.04.3 LTS

I am working with the cognionics CGX system HD-72 and there seems to be some issue in the PSD after I changed the sensors from flew to non-flex and back to flex again. Not able to pin-point the issue or why it might be happening but here is how the PSD looks now:

and previously it looked like:

​​code:

```
​import mne

import os

raw = mne.io.read_raw_brainvision(
“folder/data.vhdr”,
preload=True
)

raw.set_channel_types({
“ACC30”: “misc”, “ACC31”: “misc”, “ACC32”: “misc”,
“Packet Counter”: “misc”, “TRIGGER”: “stim”
})

raw.rename_channels({
“AFp3h”:“AF3”, “AFpz”:“AFz”, “AFp4h”:“AF4”,
“AFF3”:“F3”, “AFF4”:“F4”,
“FFC5h”:“FC5”, “FFC3h”:“FC3”, “FFCz”:“FCz”,
“FFC4h”:“FC4”, “FFC6h”:“FC6”,
“FCC5h”:“C5”, “FCC3”:“C3”, “FCC1h”:“C1”,
“FCCz”:“Cz”, “FCC2h”:“C2”, “FCC4”:“C4”, “FCC6h”:“C6”,
“CCP5h”:“CP5”, “CCPz”:“CPz”, “CCP6h”:“CP6”,
“CPP3h”:“P3”, “CPPz”:“Pz”, “CPP4h”:“P4”,
“PO5”:“PO5”, “PO1”:“PO1”, “PO2”:“PO2”, “PO6”:“PO6”,
“O1h”:“O1”, “Oz”:“Oz”, “O2h”:“O2”
})

raw.set_montage(
mne.channels.make_standard_montage(“standard_1020”),
on_missing=“ignore”
)

fig = raw.compute_psd(
fmin=0.1,
fmax=100,
picks=“eeg”
).plot(
average=False,
spatial_colors=True,
show=False
)

fig.savefig(“psd_per_channel.png”, dpi=150, bbox_inches=“tight”)
```

This is not just for a single case but multiple recordings show a weird PSD. I use the flex sensors in both the cases right now. What are some possible things I could look into to resolve this?

This looks much more like an acquisition/contact problem than an MNE PSD problem

In the old plot, most channels have the expected roughly 1/f EEG spectrum, apart from one obvious noisy channel and the 60 Hz peak. In the new plot, many channels have a much higher, nearly flat broadband floor, while a few traces sit at quite different levels. There is also a regular ripple across frequency. That is not a plausible physiological change across participants. It suggests that some channels are mostly recording amplifier/environmental noise or a periodic artifact

So sensor change is therefore a pretty strong clue. Switching back to flex sensors would not necessarily restore the previous state if, for example, a sensor is not fully seated, its conductive coating or contact was dmaged/contaminated, or the reference/ground connection was disturbed

I would troubleshoot it in this order:

  1. Check reference and ground first.A bad individual electrode usually damages one channel; a poor reference or active-ground connection can make many or all channels go bad together. Check their contact indication in the CGX acquisition software, their physical connection, and the raw traces while gently pressing each contact. The HD-72 uses active dry electrodes and active shielding, so the reference/ground path is especially important to common-mode noise rejection (Mullen et al., 2015)

  2. Inspect the live contact/impedance map before recording. Save a screenshot so that you can compare good and bad sessions. For flex sensors, make sure the prongs actually reach the scalp through the hair; looking correctly installed from above is not enough. Also inspect every removed/reinstalled sensor for incomplete seating, bent prongs, residue, moisture, or worn conductive surfaces. Use CGXs acceptable-contact criteria rather than a generic wet-electrode impedance cutoff, because this is a high-input-impedance dry-electrode system

  3. Do a swap test. Pick one clearly bad location and one relatively good location, then exchange only their sensors:

    • if the problem follows the sensor, that sensor is suspect;
    • if it stays at the same location, suspect scalp contact, the socket, wiring, or that amplifier channel;
    • if nearly everything changes when touching reference/ground, investigate that path first.
  4. Look at the unfiltered time-domain signal. The periodic spectral ripple suggests that a repeating waveform, clipping, or dropouts may be present.PSD hides which of these is happening. For example:

raw.plot(
    duration=20,
    n_channels=len(raw.copy().pick("eeg").ch_names),
    scalings={"eeg": 200e-6},  # 200 µV display scale
    remove_dc=False,
)

Look for rail-like flat sections, steps, sawtooth/square-wave patterns, synchronous deflections across most channels, or packet-loss discontinuities. Also check whether the CGX viewer already shows the artifact. If it does, MNE is downstream of the problem

  1. quantify which channels are affected and rule out a units/scaling issue
import numpy as np
import pandas as pd
import mne

picks = mne.pick_types(raw.info, eeg=True, exclude=[])
x_uv = raw.get_data(picks=picks) * 1e6  # MNE stores EEG in volts

qc = pd.DataFrame({
    "channel": [raw.ch_names[p] for p in picks],
    "robust_range_uV": np.percentile(x_uv, 99.5, axis=1)
                       - np.percentile(x_uv, 0.5, axis=1),
    "std_uV": x_uv.std(axis=1),
    "max_abs_uV": np.max(np.abs(x_uv), axis=1),
}).sort_values("robust_range_uV", ascending=False)

print(raw.info["sfreq"])
print(qc.to_string(index=False))

If the affected channels are in the millivolt range, clipped, or orders of magnitude above the earlier recordings, that supports an acquisition fault. compare these values with one known-good file using the same script. It is also worth opening the .vhdr files as text and comparing the [Binary Infos] and [Channel Infos] sections, especially the units and resolution fields

  1. make a short controlled recording: subject still, same sensor layout, headset running from its normal battery, and temporarily laptop charger, nearby power supplies, displays, and unnecessary USB equipment removed. Then add items back one at a time. The 60 Hz peak exists in both plots, so line interference alone does not explain the new broadband elevation, but poor electrode/reference contact can greatly increase its pickup

Your MNE operations are unlikely to create this difference: renaming channels and assigning a montage do not alter the voltage samples, and the montage only supplies sensor positions here. compute_psd() estimates the spectrum of the samples already present. I would therefore not notchfilter or interpolate this away yet. that could hide the symptom without fixing the recording. MNE’s guidance is to inspect and mark genuinely malfunctioning channels rather than treating them as ordinary artifacts (bad-channel tutorial; Raw.compute_psd documentation)

If the broad noise remains after verifying contact/reference/ground, and especially if it stays with fixed sockets during the swap test, I would send CGX support:

  • screenshots of the live contact map and raw traces
  • one short known-good and one bad unfiltered recording
  • the two .vhdr files
  • headset/amplifier serial number and firmware/software versions
  • a table showing whether each fault followed the sensor or stayed with the socket

That should let them distinguish failed sensors from a socket, active-shield/reference, or amplifier problem pretty quickly :))