# Authors: The MNE-Python contributors. # License: BSD-3-Clause # Copyright the MNE-Python contributors. import os.path as op from io import BytesIO import numpy as np from ...annotations import Annotations from .info import _convert_time from .res4 import _read_res4 def _get_markers(fname): def consume(fid, predicate): # just a consumer to move around conveniently while predicate(fid.readline()): pass def parse_marker(string): # XXX: there should be a nicer way to do that data = np.genfromtxt( BytesIO(string.encode()), dtype=[("trial", int), ("sync", float)] ) return int(data["trial"]), float(data["sync"]) markers = dict() with open(fname) as fid: consume(fid, lambda line: not line.startswith("NUMBER OF MARKERS:")) num_of_markers = int(fid.readline()) for _ in range(num_of_markers): consume(fid, lambda line: not line.startswith("NAME:")) label = fid.readline().strip("\n") consume(fid, lambda line: not line.startswith("NUMBER OF SAMPLES:")) n_markers = int(fid.readline()) consume(fid, lambda line: not line.startswith("LIST OF SAMPLES:")) next(fid) # skip the samples header markers[label] = [parse_marker(next(fid)) for _ in range(n_markers)] return markers def _get_res4_info_needed_by_markers(directory): """Get required information from CTF res4 information file.""" # we only need a few values from res4. Maybe we can read them directly # instead of parsing the entire res4 file. res4 = _read_res4(directory) total_offset_duration = res4["pre_trig_pts"] / res4["sfreq"] trial_duration = res4["nsamp"] / res4["sfreq"] meas_date = (_convert_time(res4["data_date"], res4["data_time"]), 0) return total_offset_duration, trial_duration, meas_date def _read_annotations_ctf(directory): total_offset, trial_duration, meas_date = _get_res4_info_needed_by_markers( directory ) return _read_annotations_ctf_call( directory, total_offset, trial_duration, meas_date ) def _read_annotations_ctf_call(directory, total_offset, trial_duration, meas_date): fname = op.join(directory, "MarkerFile.mrk") if not op.exists(fname): return Annotations(list(), list(), list(), orig_time=meas_date) else: markers = _get_markers(fname) onset = [ synctime + (trialnum * trial_duration) + total_offset for _, m in markers.items() for (trialnum, synctime) in m ] description = np.concatenate( [np.repeat(label, len(m)) for label, m in markers.items()] ) return Annotations( onset=onset, duration=np.zeros_like(onset), description=description, orig_time=meas_date, )