Skip to content

Commit

Permalink
load xdf files: insert nan for missing data instead of interpolation
Browse files Browse the repository at this point in the history
  • Loading branch information
bkloeckl committed Dec 26, 2024
1 parent 820bda7 commit 902bff0
Showing 1 changed file with 31 additions and 3 deletions.
34 changes: 31 additions & 3 deletions src/mnelab/io/xdf.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ class RawXDF(BaseRaw):
"""Raw data from .xdf file."""

def __init__(
self, fname, stream_ids, marker_ids=None, prefix_markers=False, fs_new=None
self, fname, stream_ids, marker_ids=None, prefix_markers=False, fs_new=None, gap_threshold=1.0
):
"""Read raw data from .xdf file.
Expand Down Expand Up @@ -42,6 +42,9 @@ def __init__(
streams, _ = load_xdf(fname)
streams = {stream["info"]["stream_id"]: stream for stream in streams}

# Use these functions after loading the data


if all(_is_markerstream(streams[stream_id]) for stream_id in stream_ids):
raise RuntimeError(
"Loading only marker streams is not supported, at least one stream must"
Expand Down Expand Up @@ -79,9 +82,12 @@ def __init__(
data, first_time = _resample_streams(streams, stream_ids, fs_new)
fs = fs_new
else: # only possible if a single stream was selected
data = streams[stream_ids[0]]["time_series"]
first_time = streams[stream_ids[0]]["time_stamps"][0]
fs = float(np.array(stream["info"]["effective_srate"]).item())
data = streams[stream_ids[0]]["time_series"]

# insert nan for missing data instead of interpolation
gap_indices = _detect_gaps(streams[stream_ids[0]]["time_stamps"], gap_threshold)
data, first_time = _insert_nans(data, streams[stream_ids[0]]["time_stamps"], gap_indices, fs)

info = mne.create_info(ch_names=labels_all, sfreq=fs, ch_types=types_all)

Expand All @@ -105,6 +111,28 @@ def __init__(
self.annotations.append(onsets, [0] * len(onsets), descriptions)


def _detect_gaps(timestamps, gap_threshold):
gaps = np.diff(timestamps) > gap_threshold
return np.where(gaps)[0]


def _insert_nans(data, timestamps, gap_indices, fs):
for index in gap_indices:
gap_size = int((timestamps[index + 1] - timestamps[index]) * fs)
data = np.insert(data, index + 1, np.full((gap_size, data.shape[1]), np.nan), axis=0)
timestamps = np.insert(
timestamps,
index + 1,
np.linspace(
timestamps[index] + 1/fs,
timestamps[index + 1],
gap_size,
endpoint=False
)
)
return data, timestamps


def _resample_streams(streams, stream_ids, fs_new):
"""
Resample multiple XDF streams to a given frequency.
Expand Down

0 comments on commit 902bff0

Please sign in to comment.