90 lines
2.8 KiB
Python
90 lines
2.8 KiB
Python
# 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,
|
|
)
|