File: markers.py

package info (click to toggle)
python-mne 1.3.0%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 100,172 kB
  • sloc: python: 166,349; pascal: 3,602; javascript: 1,472; sh: 334; makefile: 236
file content (83 lines) | stat: -rw-r--r-- 2,924 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# Author: Joan Massich <mailsik@gmail.com>
#
# License: BSD-3-Clause

import numpy as np
import os.path as op
from io import BytesIO

from ...annotations import Annotations
from .res4 import _read_res4
from .info import _convert_time


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)