From 757d0969d285a88c68a9e9ebb7a55f61000ce9cd Mon Sep 17 00:00:00 2001 From: Aimer Date: Thu, 11 Jul 2019 00:08:01 +0800 Subject: [PATCH 1/3] fix iss6550 --- mne/io/cnt/_utils.py | 32 ++++++++++++++++++++++---------- 1 file changed, 22 insertions(+), 10 deletions(-) diff --git a/mne/io/cnt/_utils.py b/mne/io/cnt/_utils.py index 74984a403c2..6d66b755e7c 100644 --- a/mne/io/cnt/_utils.py +++ b/mne/io/cnt/_utils.py @@ -113,22 +113,33 @@ def _compute_robust_event_table_position(fid): Xxx xxxxxxxxxxx. """ + def _obtain_num_suffix(num, length=32): + """Return the last `length` bits of the number.""" + return bin(num).lstrip('0b')[-length:] + def _infer_n_bytes_event_table_pos(readed_event_table_pos): - readed_event_table_pos_feature = np.binary_repr( - readed_event_table_pos).lstrip('-') + """Infer the data format of CNT file and the event table position. + + Use `n_samples`, `n_channels` to infer the correct event table position + and the data format of the cnt file, even if the event_table_pos in + the SETUP section overflows. + + Returns: + ------- + n_bytes: the number of bytes for each samples + event_table_pos: the position of the event table in the cnt file + """ + readed_event_table_pos_feature = _obtain_num_suffix(np.uint32(readed_event_table_pos)) for n_bytes in [2, 4]: computed_event_table_pos = ( - 900 + 75 * int(n_channels) + - n_bytes * int(n_channels) * int(n_samples)) - - if ( - np.binary_repr(computed_event_table_pos) - .endswith(readed_event_table_pos_feature) - ): + 900 + 75 * int(n_channels) + + n_bytes * int(n_channels) * int(n_samples)) + computed_event_table_pos_feature = _obtain_num_suffix(computed_event_table_pos) + if computed_event_table_pos_feature == readed_event_table_pos_feature: return n_bytes, computed_event_table_pos - raise Exception("event_table_dismatch") + raise Exception("Event table position cannot be configured correctly.") SETUP_NCHANNELS_OFFSET = 370 SETUP_NSAMPLES_OFFSET = 864 @@ -144,6 +155,7 @@ def _infer_n_bytes_event_table_pos(readed_event_table_pos): fid.seek(SETUP_EVENTTABLEPOS_OFFSET) (event_table_pos,) = np.frombuffer(fid.read(4), dtype=' Date: Thu, 11 Jul 2019 00:23:04 +0800 Subject: [PATCH 2/3] delete one useless line --- mne/io/cnt/_utils.py | 1 - 1 file changed, 1 deletion(-) diff --git a/mne/io/cnt/_utils.py b/mne/io/cnt/_utils.py index 6d66b755e7c..c965a493a86 100644 --- a/mne/io/cnt/_utils.py +++ b/mne/io/cnt/_utils.py @@ -155,7 +155,6 @@ def _infer_n_bytes_event_table_pos(readed_event_table_pos): fid.seek(SETUP_EVENTTABLEPOS_OFFSET) (event_table_pos,) = np.frombuffer(fid.read(4), dtype=' Date: Thu, 11 Jul 2019 10:50:43 +0800 Subject: [PATCH 3/3] a better way to solve the read problem --- mne/io/cnt/_utils.py | 86 +++++++++++++++++++++++++------------------- mne/io/cnt/cnt.py | 5 ++- 2 files changed, 52 insertions(+), 39 deletions(-) diff --git a/mne/io/cnt/_utils.py b/mne/io/cnt/_utils.py index c965a493a86..83e18b12162 100644 --- a/mne/io/cnt/_utils.py +++ b/mne/io/cnt/_utils.py @@ -7,6 +7,7 @@ from math import modf from datetime import datetime import numpy as np +from os import SEEK_END from ...utils import warn @@ -96,7 +97,7 @@ def _session_date_2_meas_date(session_date, date_format): return (int_part, frac_part) -def _compute_robust_event_table_position(fid): +def _compute_robust_event_table_position(fid, data_format): """Compute `event_table_position`. When recording event_table_position is computed (as accomulation). If the @@ -112,51 +113,64 @@ def _compute_robust_event_table_position(fid): x_xxxxxxxx : xxxxxxxx xx Xxxxxxxxxxx Xxx xxxxxxxxxxx. """ + SETUP_NCHANNELS_OFFSET = 370 + SETUP_NSAMPLES_OFFSET = 864 + SETUP_EVENTTABLEPOS_OFFSET = 886 - def _obtain_num_suffix(num, length=32): - """Return the last `length` bits of the number.""" - return bin(num).lstrip('0b')[-length:] - - def _infer_n_bytes_event_table_pos(readed_event_table_pos): - """Infer the data format of CNT file and the event table position. + def get_most_possible_sol(fid, possible_n_bytes, n_samples, n_channels): + """Find the most possible solution - Use `n_samples`, `n_channels` to infer the correct event table position - and the data format of the cnt file, even if the event_table_pos in - the SETUP section overflows. + Since both event table position and n_bytes has many possible values, + and n_samples might be not so accurate, distance between the possible + event table position and calculated event table position is used to + find the most possible combination of the event table position and + n_bytes. - Returns: - ------- - n_bytes: the number of bytes for each samples - event_table_pos: the position of the event table in the cnt file + When the distance of the solution find is not equals to 0, there is + a mismatch between the n_samples and the event_table_pos. """ - readed_event_table_pos_feature = _obtain_num_suffix(np.uint32(readed_event_table_pos)) - - for n_bytes in [2, 4]: - computed_event_table_pos = ( - 900 + 75 * int(n_channels) + - n_bytes * int(n_channels) * int(n_samples)) - computed_event_table_pos_feature = _obtain_num_suffix(computed_event_table_pos) - if computed_event_table_pos_feature == readed_event_table_pos_feature: - return n_bytes, computed_event_table_pos - - raise Exception("Event table position cannot be configured correctly.") - - SETUP_NCHANNELS_OFFSET = 370 - SETUP_NSAMPLES_OFFSET = 864 - SETUP_EVENTTABLEPOS_OFFSET = 886 + sol_table = [] + for event_table_pos in possible_event_table_pos(fid): + for n_bytes in possible_n_bytes: + calc_event_table_pos = 900 + 75 * n_channels + \ + n_bytes * n_channels * n_samples + distance = abs(calc_event_table_pos - event_table_pos) + + if distance == 0: + return event_table_pos, n_bytes, distance + sol_table.append((event_table_pos, n_bytes, distance)) + return sorted(sol_table, key=lambda x: x[2])[0] + + def possible_event_table_pos(fid): + """Yield all the possible event table position""" + fid.seek(SETUP_EVENTTABLEPOS_OFFSET) + event_table_pos = int(np.frombuffer(fid.read(4), dtype='