Source code for pycartool.sef.sef

# -*- coding: utf-8 -*-
# Authors: Tanguy Vivier <tanguy.viv@gmail.com>
#          Victor Férat <victor.ferat@live.fr>
#
# License: BSD (3-clause)
import datetime as dt
import struct
import time

import mne
import numpy as np
from mne import create_info
from mne.io import RawArray

from ..utils._docs import fill_doc
from ..utils._logs import logger, verbose


[docs]@fill_doc @verbose def read_sef(filename, verbose=None): """Read file with format ``.sef``, and returns a `~mne.io.RawArray`. Parameters ---------- filename : str or file-like The Simple EEG (``.sef``) file to read. %(verbose)s Returns ------- raw : `~mne.io.RawArray` RawArray containing the EEG signals. %(verbose)s """ f = open(filename, "rb") # Read fixed part of the headerà version = f.read(4).decode("utf-8") if version != "SE01": print(f"Version : {version} not supported") raise ValueError() (n_channels,) = struct.unpack("I", f.read(4)) (num_aux_electrodes,) = struct.unpack("I", f.read(4)) # noqa F841 (num_time_frames,) = struct.unpack("I", f.read(4)) (sfreq,) = struct.unpack("f", f.read(4)) (year,) = struct.unpack("H", f.read(2)) (month,) = struct.unpack("H", f.read(2)) (day,) = struct.unpack("H", f.read(2)) (hour,) = struct.unpack("H", f.read(2)) (minute,) = struct.unpack("H", f.read(2)) (second,) = struct.unpack("H", f.read(2)) (millisecond,) = struct.unpack("H", f.read(2)) # Read variable part of the header ch_names = [] for _ in range(n_channels): name = [char for char in f.read(8).split(b"\x00") if char != b""][0] ch_names.append(name.decode("utf-8").strip()) # Read data buffer = np.frombuffer( f.read(n_channels * num_time_frames * 8), dtype=np.float32, count=n_channels * num_time_frames, ) data = np.reshape(buffer, (num_time_frames, n_channels)) # Create infos description = "Imported with Pycartool" try: record_time = dt.datetime( year, month, day, hour, minute, second ).timetuple() meas_date = (time.mktime(record_time), millisecond) except Exception as e: logger.info(f"Cannot read recording date from file: {e}") meas_date = None ch_types = ["eeg" for i in range(n_channels)] infos = create_info(ch_names=ch_names, sfreq=sfreq, ch_types=ch_types) infos["description"] = description raw = RawArray(np.transpose(data), infos) raw.set_meas_date(meas_date) return raw
[docs]def write_sef(filename, raw): """Export a raw mne file to a ``.sef`` file. Parameters ---------- filename : str or file-like Filename of the exported dataset. raw : `~mne.io.RawArray` The raw data to export. """ n_channels = len(raw.info["ch_names"]) num_freq_frames = raw.n_times info = raw.info sfreq = info["sfreq"] num_aux_electrodes = n_channels - len( mne.pick_types(info, meg=False, eeg=True, exclude=[""]) ) f = open(filename, "wb") f.write("SE01".encode("utf-8")) f.write(struct.pack("I", n_channels)) f.write(struct.pack("I", num_aux_electrodes)) f.write(struct.pack("I", num_freq_frames)) f.write(struct.pack("f", sfreq)) f.write(struct.pack("H", 0)) f.write(struct.pack("H", 0)) f.write(struct.pack("H", 0)) f.write(struct.pack("H", 0)) f.write(struct.pack("H", 0)) f.write(struct.pack("H", 0)) f.write(struct.pack("H", 0)) ch_names = info["ch_names"] for k in range(n_channels): ch_name = ch_names[k] ch_name = ch_name.ljust(8) f.write(ch_name.encode("utf-8")) data = raw.get_data().astype(np.float32) data = np.reshape(data, n_channels * num_freq_frames, order="F") data.tofile(f) f.close()