====== EEG Remarking Status Channel ======
"Remarking" is part of the preprocessing pipeline. For more see [[:tools:eeg_7t_preprocessingpipeline|EEG Preprocessing Pipeline for 7T/BrainMechR01]]
===== Why =====
The BioSemi device used in [[:tools:loefeeg]] records in [[https://www.biosemi.com/faq/file_format.htm|24-bits]] on the [[https://www.biosemi.com/faq/trigger_signals.htm|Status Channel (16 available for task)]]. Matlab and python read in 32-bits. Task "trigger"/"TTL" values in the ''Status'' channel are read in offset from what is sent/intended-to-be-recorded. More info about the BDF format on [[https://www.fieldtriptoolbox.org/getting_started/biosemi/#the-bdf-fileformat|fieldtriptoolbox's page]], and for more on bit masking, see mne python's [[https://mne.tools/dev/generated/mne.io.read_raw_bdf.html#:~:text=to%20retrieve%20correct%20event%20values%20(bits%201-16)%2C%20one%20could%20do|read_bdf documentation]]. Also see [[https://wiki.besa.de/index.php?title=Reading_BioSemi_data_with_BESA|BESA's note on "negative logic"]] (maybe why our status channel has negative values).
Additionally, tasks may send more information than desired for analsyis. E.g. we may want to group all prep events into a single type but the task sends different triggers for various types of prep events. Remarking would collapse all of these (say values 100-150) into a single event code (say 100).
===== Code =====
TODO: example matlab code? link to github functions (fix_stim_channel).
def correct_ttl(x):
"""mne expects 8bit channel. biosemi has 24 bit. go down to 16 and adjust
>>> correct_ttl(np.array([16128],dtype='int64')) # first stim ch val
np.array([0],dtype='int16')
"""
return x.astype(np.int32) - 127**2 + 1
v = x - 16128 # np.log2(16128+256)==14
v[v == 65536] = 0 # 65536==2**16
return v
def add_stim_corrected(raw):
"""
>>> raw = mne.io.read_raw_bdf('/Volumes/Hera/Raw/EEG/SPA/12192_20251024/12192_20251024_rest.bdf')
>>> add_stim_corrected(raw)
"""
raw.load_data()
stim_raw = raw.pick_channels(["Status"]).get_data()
info = mne.create_info(["StatusCorrected"], raw.info["sfreq"], ["stim"])
stim_vals = correct_ttl(stim_raw[0]).reshape(stim_raw.shape)
stim = mne.io.RawArray(stim_vals, info)
raw.add_channels([stim], force_update_info=True)
def read_events(bdf):
"read events by making a new channel"
## read in eeg and get separate stim channel info
eeg = mne.io.read_raw_bdf(bdf)
# eeg.describe() # 247808 (484.0 s) == 512Hz
# events = mne.find_events(eeg, shortest_event=2)
util.add_stim_corrected(eeg)
events = mne.find_events(eeg, stim_channel="StatusCorrected", shortest_event=2)
return (events, eeg.info)