针对pulse-transit的工具
This commit is contained in:
8
dist/client/mne/io/kit/__init__.py
vendored
Normal file
8
dist/client/mne/io/kit/__init__.py
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
"""KIT module for reading raw data."""
|
||||
|
||||
# Authors: The MNE-Python contributors.
|
||||
# License: BSD-3-Clause
|
||||
# Copyright the MNE-Python contributors.
|
||||
|
||||
from .kit import read_raw_kit, read_epochs_kit
|
||||
from .coreg import read_mrk
|
||||
BIN
dist/client/mne/io/kit/__pycache__/__init__.cpython-310.pyc
vendored
Normal file
BIN
dist/client/mne/io/kit/__pycache__/__init__.cpython-310.pyc
vendored
Normal file
Binary file not shown.
BIN
dist/client/mne/io/kit/__pycache__/constants.cpython-310.pyc
vendored
Normal file
BIN
dist/client/mne/io/kit/__pycache__/constants.cpython-310.pyc
vendored
Normal file
Binary file not shown.
BIN
dist/client/mne/io/kit/__pycache__/coreg.cpython-310.pyc
vendored
Normal file
BIN
dist/client/mne/io/kit/__pycache__/coreg.cpython-310.pyc
vendored
Normal file
Binary file not shown.
BIN
dist/client/mne/io/kit/__pycache__/kit.cpython-310.pyc
vendored
Normal file
BIN
dist/client/mne/io/kit/__pycache__/kit.cpython-310.pyc
vendored
Normal file
Binary file not shown.
259
dist/client/mne/io/kit/constants.py
vendored
Normal file
259
dist/client/mne/io/kit/constants.py
vendored
Normal file
@@ -0,0 +1,259 @@
|
||||
"""KIT constants."""
|
||||
|
||||
# Authors: The MNE-Python contributors.
|
||||
# License: BSD-3-Clause
|
||||
# Copyright the MNE-Python contributors.
|
||||
|
||||
from ..._fiff.constants import FIFF
|
||||
from ...utils import BunchConst
|
||||
|
||||
|
||||
KIT = BunchConst()
|
||||
|
||||
# byte values
|
||||
KIT.SHORT = 2
|
||||
KIT.INT = 4
|
||||
KIT.DOUBLE = 8
|
||||
|
||||
# channel parameters
|
||||
KIT.CALIB_FACTOR = 1.0 # mne_manual p.272
|
||||
KIT.RANGE = 1.0 # mne_manual p.272
|
||||
KIT.UNIT_MUL = FIFF.FIFF_UNITM_NONE # default is 0 mne_manual p.273
|
||||
KIT.GAINS = [1, 2, 5, 10, 20, 50, 100, 200]
|
||||
|
||||
KIT.HPFS = {
|
||||
1: (0, 1, 3, 3),
|
||||
2: (0, 0.03, 0.1, 0.3, 1, 3, 10, 30),
|
||||
3: (0, 0.03, 0.1, 0.3, 1, 3, 10, 30),
|
||||
4: (0, 1, 3, 10, 30, 100, 200, 500),
|
||||
}
|
||||
KIT.LPFS = {
|
||||
1: (10, 20, 50, 100, 200, 500, 1000, 2000),
|
||||
2: (10, 20, 50, 100, 200, 500, 1000, 2000),
|
||||
3: (10, 20, 50, 100, 200, 500, 1000, 10000),
|
||||
4: (10, 30, 100, 300, 1000, 2000, 5000, 10000),
|
||||
}
|
||||
KIT.BEFS = {
|
||||
1: (0, 50, 60, 60),
|
||||
2: (0, 0, 0),
|
||||
3: (0, 60, 50, 50),
|
||||
}
|
||||
|
||||
# Map FLL-Type to filter options (high, low, band)
|
||||
KIT.FLL_SETTINGS = {
|
||||
0: (1, 1, 1), # Hanger Type #1
|
||||
10: (1, 1, 1), # Hanger Type #2
|
||||
20: (1, 1, 1), # Hanger Type #2
|
||||
50: (2, 1, 1), # Hanger Type #3
|
||||
60: (2, 1, 1), # Hanger Type #3
|
||||
100: (3, 3, 3), # Low Band Kapper Type
|
||||
101: (1, 3, 2), # Berlin (DC, 200 Hz, Through)
|
||||
120: (3, 3, 3), # Low Band Kapper Type
|
||||
200: (4, 4, 3), # High Band Kapper Type
|
||||
300: (2, 2, 2), # Kapper Type
|
||||
}
|
||||
|
||||
# channel types
|
||||
KIT.CHANNEL_MAGNETOMETER = 1
|
||||
KIT.CHANNEL_MAGNETOMETER_REFERENCE = 0x101
|
||||
KIT.CHANNEL_AXIAL_GRADIOMETER = 2
|
||||
KIT.CHANNEL_AXIAL_GRADIOMETER_REFERENCE = 0x102
|
||||
KIT.CHANNEL_PLANAR_GRADIOMETER = 3
|
||||
KIT.CHANNEL_PLANAR_GRADIOMETER_REFERENCE = 0x103
|
||||
KIT.CHANNEL_2ND_ORDER_AXIAL_GRADIOMETER = 4
|
||||
KIT.CHANNEL_2ND_ORDER_AXIAL_GRADIOMETER_REFERENCE = 0x104
|
||||
KIT.CHANNEL_TRIGGER = -1
|
||||
KIT.CHANNEL_EEG = -2
|
||||
KIT.CHANNEL_ECG = -3
|
||||
KIT.CHANNEL_ETC = -4
|
||||
KIT.CHANNEL_NULL = 0
|
||||
KIT.CHANNELS_MEG = (
|
||||
KIT.CHANNEL_MAGNETOMETER,
|
||||
KIT.CHANNEL_MAGNETOMETER_REFERENCE,
|
||||
KIT.CHANNEL_AXIAL_GRADIOMETER,
|
||||
KIT.CHANNEL_AXIAL_GRADIOMETER_REFERENCE,
|
||||
KIT.CHANNEL_PLANAR_GRADIOMETER,
|
||||
KIT.CHANNEL_PLANAR_GRADIOMETER_REFERENCE,
|
||||
KIT.CHANNEL_2ND_ORDER_AXIAL_GRADIOMETER,
|
||||
KIT.CHANNEL_2ND_ORDER_AXIAL_GRADIOMETER_REFERENCE,
|
||||
)
|
||||
KIT.CHANNELS_REFERENCE = (
|
||||
KIT.CHANNEL_MAGNETOMETER_REFERENCE,
|
||||
KIT.CHANNEL_AXIAL_GRADIOMETER_REFERENCE,
|
||||
KIT.CHANNEL_PLANAR_GRADIOMETER_REFERENCE,
|
||||
KIT.CHANNEL_2ND_ORDER_AXIAL_GRADIOMETER_REFERENCE,
|
||||
)
|
||||
KIT.CHANNELS_MISC = (
|
||||
KIT.CHANNEL_TRIGGER,
|
||||
KIT.CHANNEL_EEG,
|
||||
KIT.CHANNEL_ECG,
|
||||
KIT.CHANNEL_ETC,
|
||||
)
|
||||
KIT.CHANNEL_NAME_NCHAR = {
|
||||
KIT.CHANNEL_MAGNETOMETER: 6,
|
||||
KIT.CHANNEL_AXIAL_GRADIOMETER: 6,
|
||||
KIT.CHANNEL_TRIGGER: 32,
|
||||
KIT.CHANNEL_EEG: 8,
|
||||
KIT.CHANNEL_ECG: 32,
|
||||
KIT.CHANNEL_ETC: 32,
|
||||
}
|
||||
KIT.CH_TO_FIFF_COIL = {
|
||||
# KIT.CHANNEL_MAGNETOMETER: FIFF.???,
|
||||
KIT.CHANNEL_MAGNETOMETER_REFERENCE: FIFF.FIFFV_COIL_KIT_REF_MAG,
|
||||
KIT.CHANNEL_AXIAL_GRADIOMETER: FIFF.FIFFV_COIL_KIT_GRAD,
|
||||
# KIT.CHANNEL_AXIAL_GRADIOMETER_REFERENCE: FIFF.???,
|
||||
# KIT.CHANNEL_PLANAR_GRADIOMETER: FIFF.???,
|
||||
# KIT.CHANNEL_PLANAR_GRADIOMETER_REFERENCE: FIFF.???,
|
||||
# KIT.CHANNEL_2ND_ORDER_AXIAL_GRADIOMETER: FIFF.???,
|
||||
# KIT.CHANNEL_2ND_ORDER_AXIAL_GRADIOMETER_REFERENCE: FIFF.???,
|
||||
KIT.CHANNEL_TRIGGER: FIFF.FIFFV_COIL_NONE,
|
||||
KIT.CHANNEL_EEG: FIFF.FIFFV_COIL_EEG,
|
||||
KIT.CHANNEL_ECG: FIFF.FIFFV_COIL_NONE,
|
||||
KIT.CHANNEL_ETC: FIFF.FIFFV_COIL_NONE,
|
||||
KIT.CHANNEL_NULL: FIFF.FIFFV_COIL_NONE,
|
||||
}
|
||||
KIT.CH_TO_FIFF_KIND = {
|
||||
KIT.CHANNEL_MAGNETOMETER: FIFF.FIFFV_MEG_CH,
|
||||
KIT.CHANNEL_MAGNETOMETER_REFERENCE: FIFF.FIFFV_REF_MEG_CH,
|
||||
KIT.CHANNEL_AXIAL_GRADIOMETER: FIFF.FIFFV_MEG_CH,
|
||||
KIT.CHANNEL_AXIAL_GRADIOMETER_REFERENCE: FIFF.FIFFV_REF_MEG_CH,
|
||||
KIT.CHANNEL_PLANAR_GRADIOMETER: FIFF.FIFFV_MEG_CH,
|
||||
KIT.CHANNEL_PLANAR_GRADIOMETER_REFERENCE: FIFF.FIFFV_REF_MEG_CH,
|
||||
KIT.CHANNEL_2ND_ORDER_AXIAL_GRADIOMETER: FIFF.FIFFV_MEG_CH,
|
||||
KIT.CHANNEL_2ND_ORDER_AXIAL_GRADIOMETER_REFERENCE: FIFF.FIFFV_REF_MEG_CH,
|
||||
KIT.CHANNEL_TRIGGER: FIFF.FIFFV_MISC_CH,
|
||||
KIT.CHANNEL_EEG: FIFF.FIFFV_EEG_CH,
|
||||
KIT.CHANNEL_ECG: FIFF.FIFFV_ECG_CH,
|
||||
KIT.CHANNEL_ETC: FIFF.FIFFV_MISC_CH,
|
||||
KIT.CHANNEL_NULL: FIFF.FIFFV_MISC_CH,
|
||||
}
|
||||
KIT.CH_LABEL = {
|
||||
KIT.CHANNEL_TRIGGER: "TRIGGER",
|
||||
KIT.CHANNEL_EEG: "EEG",
|
||||
KIT.CHANNEL_ECG: "ECG",
|
||||
KIT.CHANNEL_ETC: "MISC",
|
||||
KIT.CHANNEL_NULL: "MISC",
|
||||
}
|
||||
|
||||
# Acquisition modes
|
||||
KIT.CONTINUOUS = 1
|
||||
KIT.EVOKED = 2
|
||||
KIT.EPOCHS = 3
|
||||
|
||||
# coreg constants
|
||||
KIT.DIG_POINTS = 10000
|
||||
|
||||
# Known KIT systems
|
||||
# -----------------
|
||||
# KIT recording system is encoded in the SQD file as integer:
|
||||
KIT.SYSTEM_MQ_ADULT = 345 # Macquarie Dept of Cognitive Science, 2006 -
|
||||
KIT.SYSTEM_MQ_CHILD = 403 # Macquarie Dept of Cognitive Science, 2006 -
|
||||
KIT.SYSTEM_AS = 260 # Academia Sinica at Taiwan
|
||||
KIT.SYSTEM_AS_2008 = 261 # Academia Sinica, 2008 or 2009 -
|
||||
KIT.SYSTEM_NYU_2008 = 32 # NYU-NY, July 7, 2008 -
|
||||
KIT.SYSTEM_NYU_2009 = 33 # NYU-NY, January 24, 2009 -
|
||||
KIT.SYSTEM_NYU_2010 = 34 # NYU-NY, January 22, 2010 -
|
||||
KIT.SYSTEM_NYU_2019 = 35 # NYU-NY, September 18, 2019 -
|
||||
KIT.SYSTEM_NYUAD_2011 = 440 # NYU-AD initial launch May 20, 2011 -
|
||||
KIT.SYSTEM_NYUAD_2012 = 441 # NYU-AD more channels July 11, 2012 -
|
||||
KIT.SYSTEM_NYUAD_2014 = 442 # NYU-AD move to NYUAD campus Nov 20, 2014 -
|
||||
KIT.SYSTEM_UMD_2004 = 51 # UMD Marie Mount Hall, October 1, 2004 -
|
||||
KIT.SYSTEM_UMD_2014_07 = 52 # UMD update to 16 bit ADC, July 4, 2014 -
|
||||
KIT.SYSTEM_UMD_2014_12 = 53 # UMD December 4, 2014 -
|
||||
KIT.SYSTEM_UMD_2019_09 = 54 # UMD September 3, 2019 -
|
||||
KIT.SYSTEM_YOKOGAWA_2017_01 = 1001 # Kanazawa (until 2017)
|
||||
KIT.SYSTEM_YOKOGAWA_2018_01 = 10020 # Kanazawa (since 2018)
|
||||
KIT.SYSTEM_YOKOGAWA_2020_08 = 10021 # Kanazawa (since August 2020)
|
||||
KIT.SYSTEM_EAGLE_TECHNOLOGY_PTB_2008 = 124
|
||||
|
||||
# Sensor layouts for plotting
|
||||
KIT_LAYOUT = {
|
||||
KIT.SYSTEM_AS: None,
|
||||
KIT.SYSTEM_AS_2008: "KIT-AS-2008",
|
||||
KIT.SYSTEM_MQ_ADULT: "KIT-160",
|
||||
KIT.SYSTEM_MQ_CHILD: "KIT-125",
|
||||
KIT.SYSTEM_NYU_2008: "KIT-157",
|
||||
KIT.SYSTEM_NYU_2009: "KIT-157",
|
||||
KIT.SYSTEM_NYU_2010: "KIT-157",
|
||||
KIT.SYSTEM_NYU_2019: None,
|
||||
KIT.SYSTEM_NYUAD_2011: "KIT-AD",
|
||||
KIT.SYSTEM_NYUAD_2012: "KIT-AD",
|
||||
KIT.SYSTEM_NYUAD_2014: "KIT-AD",
|
||||
KIT.SYSTEM_UMD_2004: None,
|
||||
KIT.SYSTEM_UMD_2014_07: None,
|
||||
KIT.SYSTEM_UMD_2014_12: "KIT-UMD-3",
|
||||
KIT.SYSTEM_UMD_2019_09: None,
|
||||
KIT.SYSTEM_YOKOGAWA_2017_01: None,
|
||||
KIT.SYSTEM_YOKOGAWA_2018_01: None,
|
||||
KIT.SYSTEM_YOKOGAWA_2020_08: None,
|
||||
KIT.SYSTEM_EAGLE_TECHNOLOGY_PTB_2008: None,
|
||||
}
|
||||
# Sensor neighbor definitions
|
||||
KIT_NEIGHBORS = {
|
||||
KIT.SYSTEM_AS: None,
|
||||
KIT.SYSTEM_AS_2008: None,
|
||||
KIT.SYSTEM_MQ_ADULT: None,
|
||||
KIT.SYSTEM_MQ_CHILD: None,
|
||||
KIT.SYSTEM_NYU_2008: "KIT-157",
|
||||
KIT.SYSTEM_NYU_2009: "KIT-157",
|
||||
KIT.SYSTEM_NYU_2010: "KIT-157",
|
||||
KIT.SYSTEM_NYU_2019: "KIT-NYU-2019",
|
||||
KIT.SYSTEM_NYUAD_2011: "KIT-208",
|
||||
KIT.SYSTEM_NYUAD_2012: "KIT-208",
|
||||
KIT.SYSTEM_NYUAD_2014: "KIT-208",
|
||||
KIT.SYSTEM_UMD_2004: "KIT-UMD-1",
|
||||
KIT.SYSTEM_UMD_2014_07: "KIT-UMD-2",
|
||||
KIT.SYSTEM_UMD_2014_12: "KIT-UMD-3",
|
||||
KIT.SYSTEM_UMD_2019_09: "KIT-UMD-4",
|
||||
KIT.SYSTEM_YOKOGAWA_2017_01: None,
|
||||
KIT.SYSTEM_YOKOGAWA_2018_01: None,
|
||||
KIT.SYSTEM_YOKOGAWA_2020_08: None,
|
||||
KIT.SYSTEM_EAGLE_TECHNOLOGY_PTB_2008: None,
|
||||
}
|
||||
# Names displayed in the info dict description
|
||||
KIT_SYSNAMES = {
|
||||
KIT.SYSTEM_MQ_ADULT: "Macquarie Dept of Cognitive Science (Adult), 2006-",
|
||||
KIT.SYSTEM_MQ_CHILD: "Macquarie Dept of Cognitive Science (Child), 2006-",
|
||||
KIT.SYSTEM_AS: "Academia Sinica, -2008",
|
||||
KIT.SYSTEM_AS_2008: "Academia Sinica, 2008-",
|
||||
KIT.SYSTEM_NYU_2008: "NYU New York, 2008-9",
|
||||
KIT.SYSTEM_NYU_2009: "NYU New York, 2009-10",
|
||||
KIT.SYSTEM_NYU_2010: "NYU New York, 2010-",
|
||||
KIT.SYSTEM_NYUAD_2011: "New York University Abu Dhabi, 2011-12",
|
||||
KIT.SYSTEM_NYUAD_2012: "New York University Abu Dhabi, 2012-14",
|
||||
KIT.SYSTEM_NYUAD_2014: "New York University Abu Dhabi, 2014-",
|
||||
KIT.SYSTEM_UMD_2004: "University of Maryland, 2004-14",
|
||||
KIT.SYSTEM_UMD_2014_07: "University of Maryland, 2014",
|
||||
KIT.SYSTEM_UMD_2014_12: "University of Maryland, 2014-",
|
||||
KIT.SYSTEM_UMD_2019_09: "University of Maryland, 2019-",
|
||||
KIT.SYSTEM_YOKOGAWA_2017_01: "Yokogawa of Kanazawa (until 2017)",
|
||||
KIT.SYSTEM_YOKOGAWA_2018_01: "Yokogawa of Kanazawa (since 2018)",
|
||||
KIT.SYSTEM_YOKOGAWA_2020_08: "Yokogawa of Kanazawa (since August 2020)",
|
||||
KIT.SYSTEM_EAGLE_TECHNOLOGY_PTB_2008: "Eagle Technology MEG (KIT/Yokogawa style) at PTB (since 2008, software upgrade in 2018)", # noqa: E501
|
||||
}
|
||||
|
||||
LEGACY_AMP_PARAMS = {
|
||||
KIT.SYSTEM_NYU_2008: (5.0, 11.0),
|
||||
KIT.SYSTEM_NYU_2009: (5.0, 11.0),
|
||||
KIT.SYSTEM_NYU_2010: (5.0, 11.0),
|
||||
KIT.SYSTEM_UMD_2004: (5.0, 11.0),
|
||||
}
|
||||
|
||||
# Ones that we don't use are commented out
|
||||
KIT.DIR_INDEX_DIR = 0
|
||||
KIT.DIR_INDEX_SYSTEM = 1
|
||||
KIT.DIR_INDEX_CHANNELS = 4
|
||||
KIT.DIR_INDEX_CALIBRATION = 5
|
||||
# FLL = 6
|
||||
KIT.DIR_INDEX_AMP_FILTER = 7
|
||||
KIT.DIR_INDEX_ACQ_COND = 8
|
||||
KIT.DIR_INDEX_RAW_DATA = 9
|
||||
# AVERAGED_DATA = 10
|
||||
# MRI = 11
|
||||
KIT.DIR_INDEX_COREG = 12
|
||||
# MAGNETIC_SOURCE = 13
|
||||
# TRIGGER = 14
|
||||
# BOOKMARKS = 15
|
||||
# DIGITIZER = 25
|
||||
KIT.DIR_INDEX_DIG_POINTS = 26
|
||||
KIT.DIR_INDEX_CHPI_DATA = 29
|
||||
233
dist/client/mne/io/kit/coreg.py
vendored
Normal file
233
dist/client/mne/io/kit/coreg.py
vendored
Normal file
@@ -0,0 +1,233 @@
|
||||
"""Coordinate Point Extractor for KIT system."""
|
||||
|
||||
# Authors: The MNE-Python contributors.
|
||||
# License: BSD-3-Clause
|
||||
# Copyright the MNE-Python contributors.
|
||||
|
||||
import re
|
||||
from collections import OrderedDict
|
||||
from os import SEEK_CUR, PathLike
|
||||
from pathlib import Path
|
||||
|
||||
import numpy as np
|
||||
|
||||
from ..._fiff._digitization import _make_dig_points
|
||||
from ...channels.montage import (
|
||||
_check_dig_shape,
|
||||
read_custom_montage,
|
||||
read_dig_polhemus_isotrak,
|
||||
read_polhemus_fastscan,
|
||||
)
|
||||
from ...transforms import (
|
||||
Transform,
|
||||
als_ras_trans,
|
||||
apply_trans,
|
||||
get_ras_to_neuromag_trans,
|
||||
)
|
||||
from ...utils import _check_fname, _check_option, warn
|
||||
from .constants import FIFF, KIT
|
||||
|
||||
INT32 = "<i4"
|
||||
FLOAT64 = "<f8"
|
||||
|
||||
|
||||
def read_mrk(fname):
|
||||
r"""Marker Point Extraction in MEG space directly from sqd.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
fname : path-like
|
||||
Absolute path to Marker file.
|
||||
File formats allowed: \*.sqd, \*.mrk, \*.txt.
|
||||
|
||||
Returns
|
||||
-------
|
||||
mrk_points : ndarray, shape (n_points, 3)
|
||||
Marker points in MEG space [m].
|
||||
"""
|
||||
from .kit import _read_dirs
|
||||
|
||||
fname = Path(_check_fname(fname, "read", must_exist=True, name="mrk file"))
|
||||
_check_option("file extension", fname.suffix, (".sqd", ".mrk", ".txt"))
|
||||
if fname.suffix in (".sqd", ".mrk"):
|
||||
with open(fname, "rb", buffering=0) as fid:
|
||||
dirs = _read_dirs(fid)
|
||||
fid.seek(dirs[KIT.DIR_INDEX_COREG]["offset"])
|
||||
# skips match_done, meg_to_mri and mri_to_meg
|
||||
fid.seek(KIT.INT + (2 * KIT.DOUBLE * 16), SEEK_CUR)
|
||||
mrk_count = np.fromfile(fid, INT32, 1)[0]
|
||||
pts = []
|
||||
for _ in range(mrk_count):
|
||||
# mri_type, meg_type, mri_done, meg_done
|
||||
_, _, _, meg_done = np.fromfile(fid, INT32, 4)
|
||||
_, meg_pts = np.fromfile(fid, FLOAT64, 6).reshape(2, 3)
|
||||
if meg_done:
|
||||
pts.append(meg_pts)
|
||||
mrk_points = np.array(pts)
|
||||
else:
|
||||
assert fname.suffix == ".txt"
|
||||
mrk_points = _read_dig_kit(fname, unit="m")
|
||||
|
||||
# check output
|
||||
mrk_points = np.asarray(mrk_points)
|
||||
if mrk_points.shape != (5, 3):
|
||||
err = f"{repr(fname)} is no marker file, shape is {mrk_points.shape}"
|
||||
raise ValueError(err)
|
||||
return mrk_points
|
||||
|
||||
|
||||
def read_sns(fname):
|
||||
"""Sensor coordinate extraction in MEG space.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
fname : path-like
|
||||
Absolute path to sensor definition file.
|
||||
|
||||
Returns
|
||||
-------
|
||||
locs : numpy.array, shape = (n_points, 3)
|
||||
Sensor coil location.
|
||||
"""
|
||||
p = re.compile(
|
||||
r"\d,[A-Za-z]*,([\.\-0-9]+),"
|
||||
+ r"([\.\-0-9]+),([\.\-0-9]+),"
|
||||
+ r"([\.\-0-9]+),([\.\-0-9]+)"
|
||||
)
|
||||
with open(fname) as fid:
|
||||
locs = np.array(p.findall(fid.read()), dtype=float)
|
||||
return locs
|
||||
|
||||
|
||||
def _set_dig_kit(mrk, elp, hsp, eeg, *, bad_coils=()):
|
||||
"""Add landmark points and head shape data to the KIT instance.
|
||||
|
||||
Digitizer data (elp and hsp) are represented in [mm] in the Polhemus
|
||||
ALS coordinate system. This is converted to [m].
|
||||
|
||||
Parameters
|
||||
----------
|
||||
mrk : path-like | array_like, shape (5, 3) | None
|
||||
Marker points representing the location of the marker coils with
|
||||
respect to the MEG Sensors, or path to a marker file.
|
||||
elp : path-like | array_like, shape (8, 3) | None
|
||||
Digitizer points representing the location of the fiducials and the
|
||||
marker coils with respect to the digitized head shape, or path to a
|
||||
file containing these points.
|
||||
hsp : path-like | array, shape (n_points, 3) | None
|
||||
Digitizer head shape points, or path to head shape file. If more
|
||||
than 10`000 points are in the head shape, they are automatically
|
||||
decimated.
|
||||
bad_coils : list
|
||||
Indices of bad marker coils (up to two). Bad coils will be excluded
|
||||
when computing the device-head transformation.
|
||||
eeg : dict
|
||||
Ordered dict of EEG dig points.
|
||||
|
||||
Returns
|
||||
-------
|
||||
dig_points : list
|
||||
List of digitizer points for info['dig'].
|
||||
dev_head_t : Transform
|
||||
A dictionary describing the device-head transformation.
|
||||
hpi_results : list
|
||||
The hpi results.
|
||||
"""
|
||||
from ...coreg import _decimate_points, fit_matched_points
|
||||
|
||||
if isinstance(hsp, (str, Path, PathLike)):
|
||||
hsp = _read_dig_kit(hsp)
|
||||
n_pts = len(hsp)
|
||||
if n_pts > KIT.DIG_POINTS:
|
||||
hsp = _decimate_points(hsp, res=0.005)
|
||||
n_new = len(hsp)
|
||||
warn(
|
||||
f"The selected head shape contained {n_pts} points, which is more than "
|
||||
f"recommended ({KIT.DIG_POINTS}), and was automatically downsampled to "
|
||||
f"{n_new} points. The preferred way to downsample is using FastScan."
|
||||
)
|
||||
|
||||
if isinstance(elp, (str, Path, PathLike)):
|
||||
elp_points = _read_dig_kit(elp)
|
||||
if len(elp_points) != 8:
|
||||
raise ValueError(
|
||||
f"File {repr(elp)} should contain 8 points; got shape "
|
||||
f"{elp_points.shape}."
|
||||
)
|
||||
elp = elp_points
|
||||
if len(bad_coils) > 0:
|
||||
elp = np.delete(elp, np.array(bad_coils) + 3, 0)
|
||||
# check we have at least 3 marker coils (whether read from file or
|
||||
# passed in directly)
|
||||
if len(elp) not in (6, 7, 8):
|
||||
raise ValueError(f"ELP should contain 6 ~ 8 points; got shape {elp.shape}.")
|
||||
if isinstance(mrk, (str, Path, PathLike)):
|
||||
mrk = read_mrk(mrk)
|
||||
if len(bad_coils) > 0:
|
||||
mrk = np.delete(mrk, bad_coils, 0)
|
||||
if len(mrk) not in (3, 4, 5):
|
||||
raise ValueError(f"MRK should contain 3 ~ 5 points; got shape {mrk.shape}.")
|
||||
|
||||
mrk = apply_trans(als_ras_trans, mrk)
|
||||
|
||||
nasion, lpa, rpa = elp[:3]
|
||||
nmtrans = get_ras_to_neuromag_trans(nasion, lpa, rpa)
|
||||
elp = apply_trans(nmtrans, elp)
|
||||
hsp = apply_trans(nmtrans, hsp)
|
||||
eeg = OrderedDict((k, apply_trans(nmtrans, p)) for k, p in eeg.items())
|
||||
|
||||
# device head transform
|
||||
trans = fit_matched_points(tgt_pts=elp[3:], src_pts=mrk, out="trans")
|
||||
|
||||
nasion, lpa, rpa = elp[:3]
|
||||
elp = elp[3:]
|
||||
|
||||
dig_points = _make_dig_points(nasion, lpa, rpa, elp, hsp, dig_ch_pos=eeg)
|
||||
dev_head_t = Transform("meg", "head", trans)
|
||||
|
||||
hpi_results = [
|
||||
dict(
|
||||
dig_points=[
|
||||
dict(
|
||||
ident=ci,
|
||||
r=r,
|
||||
kind=FIFF.FIFFV_POINT_HPI,
|
||||
coord_frame=FIFF.FIFFV_COORD_UNKNOWN,
|
||||
)
|
||||
for ci, r in enumerate(mrk)
|
||||
],
|
||||
coord_trans=dev_head_t,
|
||||
)
|
||||
]
|
||||
|
||||
return dig_points, dev_head_t, hpi_results
|
||||
|
||||
|
||||
def _read_dig_kit(fname, unit="auto"):
|
||||
# Read dig points from a file and return ndarray, using FastSCAN for .txt
|
||||
fname = _check_fname(fname, "read", must_exist=True, name="hsp or elp file")
|
||||
assert unit in ("auto", "m", "mm")
|
||||
_check_option("file extension", fname.suffix, (".hsp", ".elp", ".mat", ".txt"))
|
||||
if fname.suffix == ".txt":
|
||||
unit = "mm" if unit == "auto" else unit
|
||||
out = read_polhemus_fastscan(fname, unit=unit, on_header_missing="ignore")
|
||||
elif fname.suffix in (".hsp", ".elp"):
|
||||
unit = "m" if unit == "auto" else unit
|
||||
mon = read_dig_polhemus_isotrak(fname, unit=unit)
|
||||
if fname.suffix == ".hsp":
|
||||
dig = [d["r"] for d in mon.dig if d["kind"] != FIFF.FIFFV_POINT_CARDINAL]
|
||||
else:
|
||||
dig = [d["r"] for d in mon.dig]
|
||||
if (
|
||||
dig
|
||||
and mon.dig[0]["kind"] == FIFF.FIFFV_POINT_CARDINAL
|
||||
and mon.dig[0]["ident"] == FIFF.FIFFV_POINT_LPA
|
||||
):
|
||||
# LPA, Nasion, RPA -> NLR
|
||||
dig[:3] = [dig[1], dig[0], dig[2]]
|
||||
out = np.array(dig, float)
|
||||
else:
|
||||
assert fname.suffix == ".mat"
|
||||
out = np.array([d["r"] for d in read_custom_montage(fname).dig])
|
||||
_check_dig_shape(out)
|
||||
return out
|
||||
1045
dist/client/mne/io/kit/kit.py
vendored
Normal file
1045
dist/client/mne/io/kit/kit.py
vendored
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user