Skip to content

Commit 03276c7

Browse files
authored
MAINT: Backports (#7890)
* FIX: Fix reading of old TFRs (#7851) * MRG, FIX: Ensure Info H5-writeable (#7887) * FIX: Ensure H5-writeable * FIX: Test * FIX: Protect
1 parent 68ac9c5 commit 03276c7

File tree

8 files changed

+65
-16
lines changed

8 files changed

+65
-16
lines changed

mne/io/ctf/info.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -296,7 +296,7 @@ def _conv_comp(comp, first, last, chs):
296296
col_names = comp[first]['sensors'][:n_col]
297297
row_names = [comp[p]['sensor_name'] for p in range(first, last + 1)]
298298
mask = np.in1d(col_names, ch_names) # missing channels excluded
299-
col_names = np.array(col_names)[mask]
299+
col_names = np.array(col_names)[mask].tolist()
300300
n_col = len(col_names)
301301
n_row = len(row_names)
302302
ccomp = dict(ctfkind=np.array([comp[first]['coeff_type']]),

mne/io/egi/egi.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,6 @@ def my_fread(*x, **y):
6363
for event in range(info['n_events']):
6464
event_codes = ''.join(np.fromfile(fid, 'S1', 4).astype('U1'))
6565
info['event_codes'].append(event_codes)
66-
info['event_codes'] = np.array(info['event_codes'])
6766
else:
6867
raise NotImplementedError('Only continuous files are supported')
6968
info['unsegmented'] = unsegmented

mne/io/egi/events.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ def _read_events(input_fname, info):
2525
mff_events, event_codes = _read_mff_events(input_fname, info['sfreq'],
2626
info['n_samples'])
2727
info['n_events'] = len(event_codes)
28-
info['event_codes'] = np.asarray(event_codes).astype('<U4')
28+
info['event_codes'] = event_codes
2929
events = np.zeros([info['n_events'],
3030
info['n_segments'] * info['n_samples']])
3131
for n, event in enumerate(event_codes):

mne/io/meas_info.py

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@
2121
from .open import fiff_open
2222
from .tree import dir_tree_find
2323
from .tag import read_tag, find_tag, _coord_dict
24-
from .proj import _read_proj, _write_proj, _uniquify_projs, _normalize_proj
24+
from .proj import (_read_proj, _write_proj, _uniquify_projs, _normalize_proj,
25+
Projection)
2526
from .ctf_comp import read_ctf_comp, write_ctf_comp
2627
from .write import (start_file, end_file, start_block, end_block,
2728
write_string, write_dig_points, write_float, write_int,
@@ -31,7 +32,7 @@
3132
from ..transforms import invert_transform, Transform, _coord_frame_name
3233
from ..utils import (logger, verbose, warn, object_diff, _validate_type,
3334
_stamp_to_dt, _dt_to_stamp, _pl, _is_numeric)
34-
from ._digitization import (_format_dig_points, _dig_kind_proper,
35+
from ._digitization import (_format_dig_points, _dig_kind_proper, DigPoint,
3536
_dig_kind_rev, _dig_kind_ints, _read_dig_fif)
3637
from ._digitization import write_dig as _dig_write_dig
3738
from .compensator import get_current_comp
@@ -190,6 +191,16 @@ def set_montage(self, montage, raise_if_subset=DEPRECATED_PARAM,
190191
return self
191192

192193

194+
def _format_trans(obj, key):
195+
try:
196+
t = obj[key]
197+
except KeyError:
198+
pass
199+
else:
200+
if t is not None:
201+
obj[key] = Transform(t['from'], t['to'], t['trans'])
202+
203+
193204
# XXX Eventually this should be de-duplicated with the MNE-MATLAB stuff...
194205
class Info(dict, MontageMixin):
195206
"""Measurement information.
@@ -528,9 +539,24 @@ class Info(dict, MontageMixin):
528539

529540
def __init__(self, *args, **kwargs):
530541
super(Info, self).__init__(*args, **kwargs)
531-
t = self.get('dev_head_t', None)
532-
if t is not None and not isinstance(t, Transform):
533-
self['dev_head_t'] = Transform(t['from'], t['to'], t['trans'])
542+
# Deal with h5io writing things as dict
543+
for key in ('dev_head_t', 'ctf_head_t', 'dev_ctf_t'):
544+
_format_trans(self, key)
545+
for res in self.get('hpi_results', []):
546+
_format_trans(res, 'coord_trans')
547+
if self.get('dig', None) is not None and len(self['dig']) and \
548+
not isinstance(self['dig'][0], DigPoint):
549+
self['dig'] = _format_dig_points(self['dig'])
550+
for pi, proj in enumerate(self.get('projs', [])):
551+
if not isinstance(proj, Projection):
552+
self['projs'][pi] = Projection(proj)
553+
# Old files could have meas_date as tuple instead of datetime
554+
try:
555+
meas_date = self['meas_date']
556+
except KeyError:
557+
pass
558+
else:
559+
self['meas_date'] = _ensure_meas_date_none_or_dt(meas_date)
534560

535561
def copy(self):
536562
"""Copy the instance.
@@ -1362,11 +1388,7 @@ def read_meas_info(fid, tree, clean_bads=False, verbose=None):
13621388
info['proj_name'] = proj_name
13631389
if meas_date is None:
13641390
meas_date = (info['meas_id']['secs'], info['meas_id']['usecs'])
1365-
if np.array_equal(meas_date, DATE_NONE):
1366-
meas_date = None
1367-
else:
1368-
meas_date = _stamp_to_dt(meas_date)
1369-
info['meas_date'] = meas_date
1391+
info['meas_date'] = _ensure_meas_date_none_or_dt(meas_date)
13701392
info['utc_offset'] = utc_offset
13711393

13721394
info['sfreq'] = sfreq
@@ -1408,6 +1430,14 @@ def read_meas_info(fid, tree, clean_bads=False, verbose=None):
14081430
return info, meas
14091431

14101432

1433+
def _ensure_meas_date_none_or_dt(meas_date):
1434+
if meas_date is None or np.array_equal(meas_date, DATE_NONE):
1435+
meas_date = None
1436+
elif not isinstance(meas_date, datetime.datetime):
1437+
meas_date = _stamp_to_dt(meas_date)
1438+
return meas_date
1439+
1440+
14111441
def _check_dates(info, prepend_error=''):
14121442
"""Check dates before writing as fif files.
14131443

mne/io/tests/test_raw.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@
1616

1717
from mne import concatenate_raws, create_info, Annotations
1818
from mne.datasets import testing
19-
from mne.io import read_raw_fif, RawArray, BaseRaw
20-
from mne.utils import _TempDir, catch_logging, _raw_annot, _stamp_to_dt
19+
from mne.externals.h5io import read_hdf5, write_hdf5
20+
from mne.io import read_raw_fif, RawArray, BaseRaw, Info
21+
from mne.utils import (_TempDir, catch_logging, _raw_annot, _stamp_to_dt,
22+
object_diff, check_version)
2123
from mne.io.meas_info import _get_valid_units
2224
from mne.io._digitization import DigPoint
2325

@@ -169,6 +171,13 @@ def _test_raw_reader(reader, test_preloading=True, test_kwargs=True,
169171
for ch_name, unit in raw._orig_units.items():
170172
assert unit.lower() in valid_units_lower, ch_name
171173

174+
# Make sure that writing info to h5 format
175+
# (all fields should be compatible)
176+
if check_version('h5py'):
177+
fname_h5 = op.join(tempdir, 'info.h5')
178+
write_hdf5(fname_h5, raw.info)
179+
new_info = Info(read_hdf5(fname_h5))
180+
assert object_diff(new_info, raw.info) == ''
172181
return raw
173182

174183

mne/tests/test_bem.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,28 +247,34 @@ def test_fit_sphere_to_headshape():
247247
# Top of the head (extra point)
248248
{'coord_frame': FIFF.FIFFV_COORD_HEAD,
249249
'kind': FIFF.FIFFV_POINT_EXTRA,
250+
'ident': 0,
250251
'r': np.array([0.0, 0.0, 1.0])},
251252

252253
# EEG points
253254
# Fz
254255
{'coord_frame': FIFF.FIFFV_COORD_HEAD,
255256
'kind': FIFF.FIFFV_POINT_EEG,
257+
'ident': 0,
256258
'r': np.array([0, .72, .69])},
257259
# F3
258260
{'coord_frame': FIFF.FIFFV_COORD_HEAD,
259261
'kind': FIFF.FIFFV_POINT_EEG,
262+
'ident': 1,
260263
'r': np.array([-.55, .67, .50])},
261264
# F4
262265
{'coord_frame': FIFF.FIFFV_COORD_HEAD,
263266
'kind': FIFF.FIFFV_POINT_EEG,
267+
'ident': 2,
264268
'r': np.array([.55, .67, .50])},
265269
# Cz
266270
{'coord_frame': FIFF.FIFFV_COORD_HEAD,
267271
'kind': FIFF.FIFFV_POINT_EEG,
272+
'ident': 3,
268273
'r': np.array([0.0, 0.0, 1.0])},
269274
# Pz
270275
{'coord_frame': FIFF.FIFFV_COORD_HEAD,
271276
'kind': FIFF.FIFFV_POINT_EEG,
277+
'ident': 4,
272278
'r': np.array([0, -.72, .69])},
273279
]
274280
for d in dig:

mne/time_frequency/tests/test_tfr.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -409,7 +409,9 @@ def test_io():
409409

410410
info = mne.create_info(['MEG 001', 'MEG 002', 'MEG 003'], 1000.,
411411
['mag', 'mag', 'mag'])
412-
info['meas_date'] = datetime.datetime(year=2020, month=2, day=5)
412+
info['meas_date'] = datetime.datetime(year=2020, month=2, day=5,
413+
tzinfo=datetime.timezone.utc)
414+
info._check_consistency()
413415
tfr = AverageTFR(info, data=data, times=times, freqs=freqs,
414416
nave=20, comment='test', method='crazy-tfr')
415417
tfr.save(fname)
@@ -426,6 +428,8 @@ def test_io():
426428
pytest.raises(IOError, tfr.save, fname)
427429

428430
tfr.comment = None
431+
# test old meas_date
432+
info['meas_date'] = (1, 2)
429433
tfr.save(fname, overwrite=True)
430434
assert_equal(read_tfrs(fname, condition=0).comment, tfr.comment)
431435
tfr.comment = 'test-A'

mne/time_frequency/tfr.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2294,6 +2294,7 @@ def read_tfrs(fname, condition=None):
22942294
tfr_data = read_hdf5(fname, title='mnepython', slash='replace')
22952295
for k, tfr in tfr_data:
22962296
tfr['info'] = Info(tfr['info'])
2297+
tfr['info']._check_consistency()
22972298
if 'metadata' in tfr:
22982299
tfr['metadata'] = _prepare_read_metadata(tfr['metadata'])
22992300
is_average = 'nave' in tfr

0 commit comments

Comments
 (0)