コード例 #1
0
ファイル: smartmove.py プロジェクト: neuromti/tool-offspect
def cut_traces(cntfile: FileName, annotation: Annotations) -> List[TraceData]:
    """cut the tracedate from a matfile given Annotations
    args
    ----
    cntfile: FileName
        the cntfile for cutting the data. must correspond in name to the one specified in the annotation
    annotation: Annotations
        the annotations specifying e.g. onsets as well as pre and post durations

    returns
    -------
    traces: List[TraceData]
    """
    cnt = cnt_file(cntfile)
    pre = decode(annotation["attrs"]["samples_pre_event"])
    post = decode(annotation["attrs"]["samples_post_event"])
    cix = [cnt.get_channel_info(c)[0] for c in range(cnt.get_channel_count())
           ].index(decode(annotation["attrs"]["channel_of_interest"])[0])
    traces = []
    for attrs in annotation["traces"]:
        onset = decode(attrs["event_sample"])
        trace = cnt.get_samples(fro=onset - pre, to=onset + post)
        trace = np.asanyarray(trace)[:, cix]
        traces.append(trace)
    return traces
コード例 #2
0
ファイル: smartmove.py プロジェクト: neuromti/tool-offspect
def load_triggers(fname: FileName) -> List[Tuple[str, int]]:
    c = cnt_file(fname)
    triggers = [c.get_trigger(i) for i in range(c.get_trigger_count())]
    events = []
    for t in triggers:
        m = t[0]
        idx = t[1]
        events.append((m, idx))
    return events
コード例 #3
0
ファイル: test_libeep.py プロジェクト: neuromti/tool-libeep
def test_add_trigger(tmp_cnt):
    fname, rate, channel_count = tmp_cnt
    c = libeep.cnt_file(fname)
    assert c.get_trigger_count() == 1
    for i in range(c.get_trigger_count()):
        m, s, *_ = c.get_trigger(i)
        print(m, s)
        assert m == "hello"
        assert s == 5
コード例 #4
0
ファイル: test_libeep.py プロジェクト: neuromti/tool-libeep
def test_channels(tmp_cnt):
    fname, rate, channel_count = tmp_cnt
    c = libeep.cnt_file(fname)
    assert c.get_channel_count() == channel_count
    for i in range(c.get_channel_count()):
        l, r, u = c.get_channel_info(i)
        assert l == f"Ch{i+1}"
        assert r == "None"
        assert u == "uV"
コード例 #5
0
ファイル: smartmove.py プロジェクト: neuromti/tool-offspect
def load_ephys_file(
    eeg_fname: FileName,
    emg_fname: FileName,
    pre_in_ms: float = 100,
    post_in_ms: float = 100,
    select_events: List[str] = ["0001"],
    select_channel: str = "Ch1",
) -> Dict[str, Any]:
    """load the electophysiological data for a specific channel for a smartmove file-pair

    args
    ----
    eeg_fname: FileName
        the path to the EEG file. The file is expected to have the following format: VvNn_VvNn_YYYY-MM-DD_HH-MM-SS.cnt
    emg_fname: FileName
        the path to the EMG file. The  file is expected to have the following format: VvNn<qualifier> YYYY-MM-DD_HH-MM-SS.cnt
    pre_in_ms: float = 100
        how much time before the TMS
    post_in_ms: float = 100
        how much time after the TMS
    select_events: List[str] = ["0001"]
        which events indicate the occurence of a TMS-pulse
    select_channel: str = "Ch1"
        the channel to use. Note that EMG channel labes only offer a selection of :code:`'Ch1', 'Ch2', 'Ch3', 'Ch4', 'Ch5', 'Ch6', 'Ch7', 'Ch8'`, while EEG channels are recording from a standard wavecap and should offer ['Fp1', 'Fpz', 'Fp2', 'F7', 'F3', 'Fz', 'F4', 'F8', 'FC5', 'FC1', 'FC2', 'FC6', 'M1', 'T7', 'C3', 'Cz', 'C4', 'T8', 'M2', 'CP5', 'CP1', 'CP2', 'CP6', 'P7', 'P3', 'Pz', 'P4', 'P8', 'POz', 'O1', 'O2', 'EOG', 'AF7', 'AF3', 'AF4', 'AF8', 'F5', 'F1', 'F2', 'F6', 'FC3', 'FCz', 'FC4', 'C5', 'C1', 'C2', 'C6', 'CP3', 'CP4', 'P5', 'P1', 'P2', 'P6', 'PO5', 'PO3', 'PO4', 'PO6', 'FT7', 'FT8', 'TP7', 'TP8', 'PO7', 'PO8', 'Oz'] all in reference to Cpz.


    returns
    -------
    Traces: List[TraceData]
        the TraceData for each event fitting to select_events in the file
    pre_in_samples:int
        how many samples before the trigger
    post_in_samples:int
        how many samples after the trigger
    sampling_rate: float
        the sampling rate of the trace
    """

    if not is_eegfile_valid(eeg_fname):
        raise ValueError(
            f"{eeg_fname} has not the correct file signature for a smartmove eeg file"
        )

    assert_equal_recording_day(eeg_fname, emg_fname)
    filedate = str(parse_recording_date(eeg_fname))

    eeg = cnt_file(eeg_fname)
    eeg_labels = [
        eeg.get_channel_info(i)[0] for i in range(eeg.get_channel_count())
    ]

    emg = cnt_file(emg_fname)
    emg_labels = [
        emg.get_channel_info(i)[0] for i in range(emg.get_channel_count())
    ]

    # the triggers are always recorded with EEG, so we need this Fs
    triggers = load_triggers(eeg_fname)
    eeg_fs = eeg.get_sample_frequency()

    if select_channel in eeg_labels:
        cnt = eeg
    elif select_channel in emg_labels:
        cnt = emg
    else:
        raise IndexError(f"Selected channel {select_channel} not found")

    origin = Path(cnt._fname).name
    subject = Path(eeg_fname).stem.split("_")[0]
    fs = cnt.get_sample_frequency()
    pre = int(pre_in_ms * fs / 1000)
    post = int(post_in_ms * fs / 1000)
    scale = fs / eeg_fs
    enames = []
    onsets = []
    tstamps = []

    for event, sample in triggers:
        if event in select_events:
            onset = int(sample * scale)
            onsets.append(onset)
            tstamps.append(sample / eeg_fs)
            enames.append(event)
    print("Selected", len(onsets), "of", len(triggers), "trigger events")

    time_since_last_pulse = [inf] + [
        a - b for a, b in zip(tstamps[1:], tstamps[0:-1])
    ]
    info = {
        "origin": origin,
        "event_samples": onsets,
        "event_times": tstamps,
        "event_names": enames,
        "samples_pre_event": pre,
        "samples_post_event": post,
        "samplingrate": fs,
        "subject": subject,
        "channel_labels": [select_channel],
        "time_since_last_pulse": time_since_last_pulse,
        "filedate": filedate,
    }
    return info
コード例 #6
0
ファイル: cnt.py プロジェクト: neuromti/tool-offspect
def prepare_annotations(
    fname,
    docname,
    pre_in_ms=100,
    post_in_ms=100,
    select_events=["4"],
    select_channel="Ch1",
    mso=100,
    didt="",
):

    if not Path(fname).with_suffix(".evt").exists():
        raise FileNotFoundError("No matching event file found for", fname)

    coords, subject = load_documentation_txt(docname)
    recstart = get_recording_start(fname)

    cnt = cnt_file(fname)
    fs = cnt.get_sample_frequency()
    pre_in_samples = int(pre_in_ms * fs / 1000)
    post_in_samples = int(post_in_ms * fs / 1000)

    event_samples = []
    event_times = []
    event_names = []
    stimulation_intensity_mso = []
    stimulation_intensity_didt = []
    print(f"Reading events constrained to {select_events}")
    for tix in range(cnt.get_trigger_count()):
        event_name, event_sample, *suppl = cnt.get_trigger(tix)
        if event_name in select_events:
            event_names.append(event_name)
            event_samples.append(event_sample)
            event_time = event_sample / fs
            event_times.append(event_time)
            stimulation_intensity_mso.append(mso)
            stimulation_intensity_didt.append(didt)

    print(f"Assigning coordinates from {docname}")
    xyz_coords = []
    for event_time in event_times:
        event_datetime = recstart + timedelta(seconds=event_time)
        xyz = [nan, nan, nan]
        for idx, (key, _xyz) in enumerate(coords.items()):
            delta = (key - event_datetime).total_seconds()
            if delta > 0:
                xyz = _xyz
                break
        xyz_coords.append(xyz)

    time_since_last_pulse = [
        a - b for a, b in zip(event_times, [-inf] + event_times)
    ]

    anno = AnnotationFactory(readin="tms",
                             readout="cmep",
                             origin=Path(fname).name)
    anno.set("filedate", str(recstart))
    anno.set("subject", subject)
    anno.set("samplingrate", fs)
    anno.set("samples_pre_event", pre_in_samples)
    anno.set("samples_post_event", post_in_samples)
    anno.set("channel_of_interest", [select_channel])
    anno.set("channel_labels", [select_channel])

    # trace fields
    for idx, t in enumerate(event_samples):
        tattr = {
            "id": idx,
            "event_name": event_names[idx],
            "event_sample": event_samples[idx],
            "event_time": event_times[idx],
            "xyz_coords": xyz_coords[idx],
            "time_since_last_pulse_in_s": time_since_last_pulse[idx],
            "stimulation_intensity_mso": stimulation_intensity_mso[idx],
            "stimulation_intensity_didt": stimulation_intensity_didt[idx],
            "reject": False,
            "onset_shift": 0,
        }
        anno.append_trace_attr(tattr)

    return anno.anno
コード例 #7
0
ファイル: test_libeep.py プロジェクト: neuromti/tool-libeep
def test_add_samples(tmp_cnt):
    fname, rate, channel_count = tmp_cnt
    c = libeep.cnt_file(fname)
    data = c.get_samples(0, c.get_sample_count())
    assert all([x == 0.0 for x in data[0]])
    assert all([x == 99.0 for x in data[-1]])
コード例 #8
0
ファイル: test_libeep.py プロジェクト: neuromti/tool-libeep
def test_sampling_rate(tmp_cnt):
    fname, rate, channel_count = tmp_cnt
    c = libeep.cnt_file(fname)

    assert c.get_sample_frequency() == rate