Skip to content

Commit a41ca39

Browse files
agramfortlarsoner
authored andcommitted
WIP: issue with dates on write not on read (mne-tools#7135)
* issue with dates on write not on read * add test + fixes * fix? * typo
1 parent 1325c1a commit a41ca39

File tree

3 files changed

+48
-25
lines changed

3 files changed

+48
-25
lines changed

mne/io/meas_info.py

+40-24
Original file line numberDiff line numberDiff line change
@@ -582,28 +582,6 @@ def _check_consistency(self, prepend_error=''):
582582
raise RuntimeError('%sinfo["meas_date"] must be a datetime '
583583
'object in UTC or None, got "%r"'
584584
% (prepend_error, repr(self['meas_date']),))
585-
meas_date_stamp = _dt_to_stamp(meas_date)
586-
if (meas_date_stamp[0] < np.iinfo('>i4').min or
587-
meas_date_stamp[0] > np.iinfo('>i4').max):
588-
raise RuntimeError(
589-
'%sinfo["meas_date"] seconds must be between "%r" '
590-
'and "%r", got "%r"'
591-
% (prepend_error, (np.iinfo('>i4').min, 0),
592-
(np.iinfo('>i4').max, 0), meas_date_stamp[0],))
593-
594-
for key in ('file_id', 'meas_id'):
595-
value = self.get(key)
596-
if value is not None:
597-
assert 'msecs' not in value
598-
for key_2 in ('secs', 'usecs'):
599-
if (value[key_2] < np.iinfo('>i4').min or
600-
value[key_2] > np.iinfo('>i4').max):
601-
raise RuntimeError('%sinfo[%s][%s] must be between '
602-
'"%r" and "%r", got "%r"'
603-
% (prepend_error, key, key_2,
604-
np.iinfo('>i4').min,
605-
np.iinfo('>i4').max,
606-
value[key_2]),)
607585

608586
chs = [ch['ch_name'] for ch in self['chs']]
609587
if len(self['ch_names']) != len(chs) or any(
@@ -1290,6 +1268,40 @@ def read_meas_info(fid, tree, clean_bads=False, verbose=None):
12901268
return info, meas
12911269

12921270

1271+
def _check_dates(info, prepend_error=''):
1272+
"""Check dates before writing as fif files.
1273+
1274+
It's needed because of the limited integer precision
1275+
of the fix standard.
1276+
"""
1277+
for key in ('file_id', 'meas_id'):
1278+
value = info.get(key)
1279+
if value is not None:
1280+
assert 'msecs' not in value
1281+
for key_2 in ('secs', 'usecs'):
1282+
if (value[key_2] < np.iinfo('>i4').min or
1283+
value[key_2] > np.iinfo('>i4').max):
1284+
raise RuntimeError('%sinfo[%s][%s] must be between '
1285+
'"%r" and "%r", got "%r"'
1286+
% (prepend_error, key, key_2,
1287+
np.iinfo('>i4').min,
1288+
np.iinfo('>i4').max,
1289+
value[key_2]),)
1290+
1291+
meas_date = info.get('meas_date')
1292+
if meas_date is None:
1293+
return
1294+
1295+
meas_date_stamp = _dt_to_stamp(meas_date)
1296+
if (meas_date_stamp[0] < np.iinfo('>i4').min or
1297+
meas_date_stamp[0] > np.iinfo('>i4').max):
1298+
raise RuntimeError(
1299+
'%sinfo["meas_date"] seconds must be between "%r" '
1300+
'and "%r", got "%r"'
1301+
% (prepend_error, (np.iinfo('>i4').min, 0),
1302+
(np.iinfo('>i4').max, 0), meas_date_stamp[0],))
1303+
1304+
12931305
def write_meas_info(fid, info, data_type=None, reset_range=True):
12941306
"""Write measurement info into a file id (from a fif file).
12951307
@@ -1311,6 +1323,7 @@ def write_meas_info(fid, info, data_type=None, reset_range=True):
13111323
Tags are written in a particular order for compatibility with maxfilter.
13121324
"""
13131325
info._check_consistency()
1326+
_check_dates(info)
13141327

13151328
# Measurement info
13161329
start_block(fid, FIFF.FIFFB_MEAS_INFO)
@@ -2082,10 +2095,13 @@ def anonymize_info(info, daysback=None, keep_his=False, verbose=None):
20822095
if di.get(k) is not None:
20832096
di[k] = default_str
20842097

2085-
err_mesg = ('anonymize_info generated an inconsistent info object. Most '
2086-
'often this is because daysback parameter was too large. '
2098+
err_mesg = ('anonymize_info generated an inconsistent info object. '
20872099
'Underlying Error:\n')
20882100
info._check_consistency(prepend_error=err_mesg)
2101+
err_mesg = ('anonymize_info generated an inconsistent info object. '
2102+
'daysback parameter was too large.'
2103+
'Underlying Error:\n')
2104+
_check_dates(info, prepend_error=err_mesg)
20892105

20902106
return info
20912107

mne/io/tests/test_meas_info.py

+7
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,13 @@ def test_read_write_info(tmpdir):
255255
info2 = read_info(tmp_fname_3)
256256
assert info2['meas_date'] is None
257257

258+
# Check that having a very old date in fine until you try to save it to fif
259+
info['meas_date'] = datetime(1800, 1, 1, 0, 0, 0, tzinfo=timezone.utc)
260+
info._check_consistency()
261+
fname = tmpdir.join('test.fif')
262+
with pytest.raises(RuntimeError, match='must be between '):
263+
write_info(fname, info)
264+
258265

259266
def test_io_dig_points(tmpdir):
260267
"""Test Writing for dig files."""

setup.cfg

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ doc-files = doc
1616

1717
[flake8]
1818
exclude = __init__.py,*externals*,constants.py,fixes.py
19-
ignore = W504
19+
ignore = W504,I100,I101,I201,N806
2020

2121
[tool:pytest]
2222
addopts =

0 commit comments

Comments
 (0)