Skip to content

Commit d533a5f

Browse files
committed
remove local curryreader module + impedance reader + minor fixes
1 parent e640023 commit d533a5f

File tree

2 files changed

+72
-659
lines changed

2 files changed

+72
-659
lines changed

mne/io/curry/curry.py

Lines changed: 72 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,14 @@
66
import re
77
from pathlib import Path
88

9+
import curryreader
910
import numpy as np
1011

1112
from ..._fiff.meas_info import create_info
1213
from ...annotations import annotations_from_events
1314
from ...channels import make_dig_montage
1415
from ...utils import verbose
1516
from ..base import BaseRaw
16-
from .curryreader import read
17-
18-
_RE_COMBINE_WHITESPACE = re.compile(r"\s+")
1917

2018

2119
@verbose
@@ -61,12 +59,12 @@ class RawCurry(BaseRaw):
6159
"""
6260

6361
@verbose
64-
def __init__(self, fname, preload=False, verbose=None):
62+
def __init__(self, fname, preload=True, verbose=None):
6563
fname = Path(fname)
6664

6765
# use curry-python-reader
6866
try:
69-
currydata = read(str(fname), plotdata=0, verbosity=1)
67+
currydata = curryreader.read(str(fname), plotdata=0, verbosity=1)
7068
except Exception as e:
7169
raise ValueError(f"file could not be read - {e}")
7270

@@ -80,44 +78,39 @@ def __init__(self, fname, preload=False, verbose=None):
8078
landmarkslabels = currydata["landmarkslabels"]
8179

8280
# extract data
83-
orig_format = (
84-
"single"
85-
if isinstance(currydata["data"].dtype, type(np.dtype("float32")))
86-
else None
87-
)
81+
orig_format = "single" # curryreader.py always reads float32. is this correct?
82+
8883
preload = currydata["data"].T.astype(
8984
"float64"
9085
) # curryreader returns float32, but mne seems to need float64
9186
events = currydata["events"]
9287
# annotations = currydata[
9388
# "annotations"
9489
# ] # dont always seem to correspond to events?!
90+
# impedances = currydata["impedances"] # see read_impedances_curry
9591
# epochinfo = currydata["epochinfo"] # TODO
9692
# epochlabels = currydata["epochlabels"] # TODO
97-
# impedances = currydata["impedances"] # TODO
9893
# hpimatrix = currydata["hpimatrix"] # TODO
9994

100-
# extract some more essential info not provided by reader
95+
# extract other essential info not provided by curryreader
10196
fname_hdr = None
10297
for hdr_suff in [".cdt.dpa", ".cdt.dpo", ".dap"]:
10398
if fname.with_suffix(hdr_suff).exists():
10499
fname_hdr = fname.with_suffix(hdr_suff)
105100

106101
ch_types, units = [], []
107102
if fname_hdr:
108-
changroups = fname_hdr.read_text().split("DEVICE_PARAMETERS")[1::2]
109-
for changroup_info in changroups:
110-
changroup_info = _RE_COMBINE_WHITESPACE.sub(" ", changroup_info).strip()
111-
groupid = changroup_info.split()[0]
112-
unit = changroup_info.split("DataUnit = ")[1].split()[0]
113-
n_ch_group = int(
114-
changroup_info.split("NumChanThisGroup = ")[1].split()[0]
115-
)
103+
ch_groups = fname_hdr.read_text().split("DEVICE_PARAMETERS")[1::2]
104+
for ch_group in ch_groups:
105+
ch_group = re.compile(r"\s+").sub(" ", ch_group).strip()
106+
groupid = ch_group.split()[0]
107+
unit = ch_group.split("DataUnit = ")[1].split()[0]
108+
n_ch_group = int(ch_group.split("NumChanThisGroup = ")[1].split()[0])
116109
ch_type = (
117110
"mag"
118111
if ("MAG" in groupid)
119112
else "misc"
120-
if ("OTHER") in groupid
113+
if ("OTHER" in groupid)
121114
else "eeg"
122115
)
123116
# combine info
@@ -127,11 +120,10 @@ def __init__(self, fname, preload=False, verbose=None):
127120
assert len(ch_types) == len(units) == len(ch_names) == n_ch
128121

129122
else:
130-
# not implemented
131123
raise NotImplementedError
132124

133125
# finetune channel types (e.g. stim, eog etc might be identified by name)
134-
# TODO
126+
# TODO?
135127

136128
# scale data to SI units
137129
orig_units = dict(zip(ch_names, units))
@@ -172,6 +164,9 @@ def __init__(self, fname, preload=False, verbose=None):
172164
mont = _make_curry_montage(ch_names, ch_pos, landmarks, landmarkslabels)
173165
self.set_montage(mont, on_missing="ignore")
174166

167+
# add HPI data (if present)
168+
# TODO
169+
175170

176171
def _make_curry_montage(ch_names, ch_pos, landmarks, landmarkslabels):
177172
ch_pos_dict = dict(zip(ch_names, ch_pos))
@@ -180,10 +175,17 @@ def _make_curry_montage(ch_names, ch_pos, landmarks, landmarkslabels):
180175
if k not in landmark_dict.keys():
181176
landmark_dict[k] = None
182177
if len(landmarkslabels) > 0:
183-
hpi_pos = landmarks[[i for i, n in enumerate(landmarkslabels) if "HPI" in n], :]
178+
hpi_pos = landmarks[
179+
[i for i, n in enumerate(landmarkslabels) if re.match("HPI[1-99]", n)], :
180+
]
184181
else:
185182
hpi_pos = None
186-
# TODO headshape (H1,2,3..)
183+
if len(landmarkslabels) > 0:
184+
hsp_pos = landmarks[
185+
[i for i, n in enumerate(landmarkslabels) if re.match("H[1-99]", n)], :
186+
]
187+
else:
188+
hsp_pos = None
187189

188190
mont = None
189191
if ch_pos.shape[1] == 3: # eeg xyz space
@@ -192,7 +194,7 @@ def _make_curry_montage(ch_names, ch_pos, landmarks, landmarkslabels):
192194
nasion=landmark_dict["Nas"],
193195
lpa=landmark_dict["LPA"],
194196
rpa=landmark_dict["RPA"],
195-
hsp=None,
197+
hsp=hsp_pos,
196198
hpi=hpi_pos,
197199
coord_frame="unknown",
198200
)
@@ -203,3 +205,47 @@ def _make_curry_montage(ch_names, ch_pos, landmarks, landmarkslabels):
203205
pass
204206

205207
return mont
208+
209+
210+
def read_impedances_curry(fname):
211+
"""Read impedance measurements from Curry files.
212+
213+
Parameters
214+
----------
215+
fname : path-like
216+
Path to a curry file with extensions ``.dat``, ``.dap``, ``.rs3``,
217+
``.cdt``, ``.cdt.dpa``, ``.cdt.cef`` or ``.cef``.
218+
219+
Returns
220+
-------
221+
ch_names : list
222+
A list object containing channel names
223+
impedances : np.ndarray
224+
An array containing up to 10 impedance measurements for all recorded channels.
225+
226+
"""
227+
# use curry-python-reader to load data
228+
try:
229+
currydata = curryreader.read(str(fname), plotdata=0, verbosity=1)
230+
except Exception as e:
231+
raise ValueError(f"file could not be read - {e}")
232+
233+
impedances = currydata["impedances"]
234+
ch_names = currydata["labels"]
235+
236+
# try get measurement times
237+
# TODO possible?
238+
annotations = currydata[
239+
"annotations"
240+
] # dont really seem to correspond to events!?!
241+
for anno in set(annotations):
242+
if "impedance" in anno.lower():
243+
print("FOUND IMPEDANCE ANNOTATION!")
244+
print(f"'{anno}' - N={len([a for a in annotations if a == anno])}")
245+
246+
# print impedances
247+
print("impedance measurements:")
248+
for iimp in range(impedances.shape[0]):
249+
print({ch: float(imp) for ch, imp in zip(ch_names, impedances[iimp])})
250+
251+
return ch_names, impedances

0 commit comments

Comments
 (0)