|
10 | 10 | import numpy as np |
11 | 11 | from defusedxml import ElementTree as ET |
12 | 12 |
|
| 13 | +from ..._fiff.constants import FIFF |
13 | 14 | from ..._fiff.meas_info import create_info |
14 | 15 | from ...utils import _check_fname, fill_doc, logger, verbose, warn |
15 | 16 | from ..base import BaseRaw |
@@ -53,7 +54,7 @@ def _parse_otb_plus_metadata(metadata, extras_metadata): |
53 | 54 | n_chan = int(metadata.attrib["DeviceTotalChannels"]) |
54 | 55 | bit_depth = int(metadata.attrib["ad_bits"]) |
55 | 56 | device_name = metadata.attrib["Name"] |
56 | | - adc_range = 3.3 # TODO is this V or mV ?? |
| 57 | + adc_range = 0.0033 # 3.3 mV (TODO VERIFY) |
57 | 58 | # containers |
58 | 59 | gains = np.full(n_chan, np.nan) |
59 | 60 | ch_names = list() |
@@ -93,11 +94,19 @@ def _parse_otb_plus_metadata(metadata, extras_metadata): |
93 | 94 | gain_ix = ix + ch_offset |
94 | 95 | gains[gain_ix] = float(ch.get("Gain")) * adapter_gain |
95 | 96 | # TODO verify ch_type for quats, buffer channel, and ramp channel |
96 | | - ch_types.append( |
97 | | - "misc" |
98 | | - if ch_id in _NON_DATA_CHS or ch_id.lower().startswith("aux") |
99 | | - else "emg" |
100 | | - ) |
| 97 | + # ramp and controls channels definitely "MISC" |
| 98 | + # quats should maybe be FIFF.FIFFV_QUAT_{N} (N from 0-6), but need to verify |
| 99 | + # what quats should be, as there are only 4 quat channels. The FIFF quats: |
| 100 | + # 0: obsolete |
| 101 | + # 1-3: rotations |
| 102 | + # 4-6: translations |
| 103 | + if ch_id == "Quaternions": |
| 104 | + ch_type = FIFF.FIFFV_QUAT_0 # TODO verify |
| 105 | + elif ch_id in _NON_DATA_CHS or ch_id.lower().startswith("aux"): |
| 106 | + ch_type = "misc" |
| 107 | + else: |
| 108 | + ch_type = "emg" |
| 109 | + ch_types.append(ch_type) |
101 | 110 | # parse subject info |
102 | 111 | subject_info = _parse_patient_xml(extras_metadata) |
103 | 112 |
|
@@ -248,7 +257,13 @@ def __init__(self, fname, *, verbose=None): |
248 | 257 | info["lowpass"] = lowpass |
249 | 258 | for ix, _ch in enumerate(info["chs"]): |
250 | 259 | cal = 1 / 2**bit_depth / gains[ix] |
251 | | - _ch.update(cal=cal, range=adc_range) |
| 260 | + # TODO need different range for Quaternions? |
| 261 | + _range = ( |
| 262 | + adc_range |
| 263 | + if _ch["kind"] in (FIFF.FIFFV_EMG_CH, FIFF.FIFFV_EEG_CH) |
| 264 | + else 1.0 |
| 265 | + ) |
| 266 | + _ch.update(cal=cal, range=_range) |
252 | 267 | if meas_date is not None: |
253 | 268 | info["meas_date"] = datetime.fromisoformat(meas_date.text).astimezone( |
254 | 269 | timezone.utc |
@@ -308,13 +323,7 @@ def _preload_data(self, preload): |
308 | 323 | else: |
309 | 324 | _data = np.concatenate(_data, axis=0) |
310 | 325 |
|
311 | | - # TODO without this fudge factor, the scale of the signals seems way too high |
312 | | - # (sample data channels show a dynamic range of 0.2 - 3.3 V) |
313 | | - # the puzzling thing is that in the MATLAB code the fudge is 1e3 (not 1e-3) ?!? |
314 | | - fudge_factor = 1e-3 |
315 | | - cals = np.array( |
316 | | - [_ch["cal"] * _ch["range"] * fudge_factor for _ch in self.info["chs"]] |
317 | | - ) |
| 326 | + cals = np.array([_ch["cal"] * _ch["range"] for _ch in self.info["chs"]]) |
318 | 327 | self._data = _data * cals[:, np.newaxis] |
319 | 328 |
|
320 | 329 |
|
|
0 commit comments