Repository: mne-tools/mne-python

Issue:
a problem in loading EEG data, nicolat.py format when trying to load data with 4 Byte integer values.
**Trying to read a file containing data with 4 Byte integer values, produces an error:**

raw = mne.io.read_raw_nicolet(path, ch_type='eeg', preload=True)
or 
raw = mne.io.read_raw_nicolet(path, ch_type='eeg', preload=False
raw.load_data()

see error logs below - these files were correctly opened in Matlab, so I know ist not a file problem

**file examples can be downloaded here:** 
https://www.dropbox.com/sh/gx5mrre4w0izuor/AABeDbycOdQ9G0bv7oMqCRPAa?dl=0
 
Also in some of the files, recording duration is not an integer value so _get_nicolet_info
in nicolat.py needs to be updated to read the duration as a float and not an int, 
for example adding to line 76 the condition: 

elif var == 'conversion_factor' | **var == 'duration_in_sec**':
      value = float(value)



**1st error logging:** 
raw = mne.io.read_raw_nicolet(path, ch_type='eeg', preload=True)

Reading header...
Reading 0 ... 3142559  =      0.000 ...  6137.811 secs...
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
~\anaconda3\envs\pre_ictal_dynamics\lib\site-packages\mne\io\nicolet\nicolet.py in _read_segment_file(self, data, idx, fi, start, stop, cals, mult)

~\anaconda3\envs\pre_ictal_dynamics\lib\site-packages\mne\io\utils.py in _read_segments_file(raw, data, idx, fi, start, stop, cals, mult, dtype, n_channels, offset, trigger_ch)
    222             if block.size != count:
--> 223                 raise RuntimeError('Incorrect number of samples (%s != %s), '
    224                                    'please report this error to MNE-Python '

RuntimeError: Incorrect number of samples (171 != 49999985), please report this error to MNE-Python developers

During handling of the above exception, another exception occurred:

RuntimeError                              Traceback (most recent call last)
<ipython-input-10-7397a9929112> in <module>
----> 1 raw = mne.io.read_raw_nicolet(path, ch_type='eeg', preload=True)

~\anaconda3\envs\pre_ictal_dynamics\lib\site-packages\mne\io\nicolet\nicolet.py in read_raw_nicolet(input_fname, ch_type, eog, ecg, emg, misc, preload, verbose)
     58     mne.io.Raw : Documentation of attribute and methods.
     59     """
---> 60     return RawNicolet(input_fname, ch_type, eog=eog, ecg=ecg,
     61                       emg=emg, misc=misc, preload=preload, verbose=verbose)
     62 

~\anaconda3\envs\pre_ictal_dynamics\lib\site-packages\mne\io\nicolet\nicolet.py in __init__(self, input_fname, ch_type, eog, ecg, emg, misc, preload, verbose)
    157         super(RawNicolet, self).__init__(
    158             info, preload, filenames=[input_fname], raw_extras=[header_info],
--> 159             last_samps=last_samps, orig_format='int',
    160             verbose=verbose)
    161 

<decorator-gen-165> in __init__(self, info, preload, first_samps, last_samps, filenames, raw_extras, orig_format, dtype, buffer_size_sec, orig_units, verbose)

~\anaconda3\envs\pre_ictal_dynamics\lib\site-packages\mne\io\base.py in __init__(self, info, preload, first_samps, last_samps, filenames, raw_extras, orig_format, dtype, buffer_size_sec, orig_units, verbose)
    247         self._update_times()
    248         if load_from_disk:
--> 249             self._preload_data(preload)
    250         self._init_kwargs = _get_argvalues()
    251 

<decorator-gen-169> in _preload_data(self, preload, verbose)

~\anaconda3\envs\pre_ictal_dynamics\lib\site-packages\mne\io\base.py in _preload_data(self, preload, verbose)
    528         logger.info('Reading %d ... %d  =  %9.3f ... %9.3f secs...' %
    529                     (0, len(self.times) - 1, 0., self.times[-1]))
--> 530         self._data = self._read_segment(
    531             data_buffer=data_buffer, projector=self._projector)
    532         assert len(self._data) == self.info['nchan']

<decorator-gen-167> in _read_segment(self, start, stop, sel, data_buffer, projector, verbose)

~\anaconda3\envs\pre_ictal_dynamics\lib\site-packages\mne\io\base.py in _read_segment(***failed resolving arguments***)
    412             # reindex back to original file
    413             orig_idx = _convert_slice(self._read_picks[fi][need_idx])
--> 414             _ReadSegmentFileProtector(self)._read_segment_file(
    415                 data[:, this_sl], orig_idx, fi,
    416                 int(start_file), int(stop_file), cals, mult)

~\anaconda3\envs\pre_ictal_dynamics\lib\site-packages\mne\io\base.py in _read_segment_file(self, data, idx, fi, start, stop, cals, mult)
   1814 
   1815     def _read_segment_file(self, data, idx, fi, start, stop, cals, mult):
-> 1816         return self.__raw.__class__._read_segment_file(
   1817             self, data, idx, fi, start, stop, cals, mult)
   1818 

~\anaconda3\envs\pre_ictal_dynamics\lib\site-packages\mne\io\nicolet\nicolet.py in _read_segment_file(self, data, idx, fi, start, stop, cals, mult)

~\anaconda3\envs\pre_ictal_dynamics\lib\site-packages\mne\io\utils.py in _read_segments_file(raw, data, idx, fi, start, stop, cals, mult, dtype, n_channels, offset, trigger_ch)
    221             block = np.fromfile(fid, dtype, count)
    222             if block.size != count:
--> 223                 raise RuntimeError('Incorrect number of samples (%s != %s), '
    224                                    'please report this error to MNE-Python '
    225                                    'developers' % (block.size, count))

RuntimeError: Incorrect number of samples (85 != 24999975), please report this error to MNE-Python developers

**second error logging:** 

raw = mne.io.read_raw_nicolet(path, ch_type='eeg', preload=False
raw.load_data()

Reading 0 ... 272639  =      0.000 ...   532.498 secs...
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
~\anaconda3\envs\pre_ictal_dynamics\lib\site-packages\mne\io\nicolet\nicolet.py in _read_segment_file(self, data, idx, fi, start, stop, cals, mult)
    166         try:
--> 167             _read_segments_file(
    168                 self, data, idx, fi, start, stop, cals, mult, dtype='<i2')

~\anaconda3\envs\pre_ictal_dynamics\lib\site-packages\mne\io\utils.py in _read_segments_file(raw, data, idx, fi, start, stop, cals, mult, dtype, n_channels, offset, trigger_ch)
    222             if block.size != count:
--> 223                 raise RuntimeError('Incorrect number of samples (%s != %s), '
    224                                    'please report this error to MNE-Python '

RuntimeError: Incorrect number of samples (169 != 9542400), please report this error to MNE-Python developers

During handling of the above exception, another exception occurred:

RuntimeError                              Traceback (most recent call last)
<ipython-input-7-72a37d28be67> in <module>
----> 1 raw.load_data()

<decorator-gen-168> in load_data(self, verbose)

~\anaconda3\envs\pre_ictal_dynamics\lib\site-packages\mne\io\base.py in load_data(self, verbose)
    517         """
    518         if not self.preload:
--> 519             self._preload_data(True)
    520         return self
    521 

<decorator-gen-169> in _preload_data(self, preload, verbose)

~\anaconda3\envs\pre_ictal_dynamics\lib\site-packages\mne\io\base.py in _preload_data(self, preload, verbose)
    528         logger.info('Reading %d ... %d  =  %9.3f ... %9.3f secs...' %
    529                     (0, len(self.times) - 1, 0., self.times[-1]))
--> 530         self._data = self._read_segment(
    531             data_buffer=data_buffer, projector=self._projector)
    532         assert len(self._data) == self.info['nchan']

<decorator-gen-167> in _read_segment(self, start, stop, sel, data_buffer, projector, verbose)

~\anaconda3\envs\pre_ictal_dynamics\lib\site-packages\mne\io\base.py in _read_segment(***failed resolving arguments***)
    412             # reindex back to original file
    413             orig_idx = _convert_slice(self._read_picks[fi][need_idx])
--> 414             _ReadSegmentFileProtector(self)._read_segment_file(
    415                 data[:, this_sl], orig_idx, fi,
    416                 int(start_file), int(stop_file), cals, mult)

~\anaconda3\envs\pre_ictal_dynamics\lib\site-packages\mne\io\base.py in _read_segment_file(self, data, idx, fi, start, stop, cals, mult)
   1814 
   1815     def _read_segment_file(self, data, idx, fi, start, stop, cals, mult):
-> 1816         return self.__raw.__class__._read_segment_file(
   1817             self, data, idx, fi, start, stop, cals, mult)
   1818 

~\anaconda3\envs\pre_ictal_dynamics\lib\site-packages\mne\io\nicolet\nicolet.py in _read_segment_file(self, data, idx, fi, start, stop, cals, mult)
    168                 self, data, idx, fi, start, stop, cals, mult, dtype='<i2')
    169         except RuntimeError:
--> 170             _read_segments_file(
    171                 self, data, idx, fi, start, stop, cals, mult, dtype='<i4')

~\anaconda3\envs\pre_ictal_dynamics\lib\site-packages\mne\io\utils.py in _read_segments_file(raw, data, idx, fi, start, stop, cals, mult, dtype, n_channels, offset, trigger_ch)
    221             block = np.fromfile(fid, dtype, count)
    222             if block.size != count:
--> 223                 raise RuntimeError('Incorrect number of samples (%s != %s), '
    224                                    'please report this error to MNE-Python '
    225                                    'developers' % (block.size, count))

RuntimeError: Incorrect number of samples (84 != 9542400), please report this error to MNE-Python developers




Discussion:
took me a while to figure it out but I think you passed the .head file to the read_raw_nicolet function and not the .data file. If you pass the .data file it works. I agree this is very error prone. I suggest a PR to check that the .data file is passed with some docstrings updates. Ok for you @miriamguen ?
this works, thanks @agramfort !

Resolving patch:
diff --git a/mne/io/nicolet/nicolet.py b/mne/io/nicolet/nicolet.py
--- a/mne/io/nicolet/nicolet.py
+++ b/mne/io/nicolet/nicolet.py
@@ -19,14 +19,15 @@ def read_raw_nicolet(input_fname, ch_type, eog=(),
                      ecg=(), emg=(), misc=(), preload=False, verbose=None):
     """Read Nicolet data as raw object.
 
-    Note: This reader takes data files with the extension ``.data`` as an
-    input. The header file with the same file name stem and an extension
-    ``.head`` is expected to be found in the same directory.
+    ..note:: This reader takes data files with the extension ``.data`` as an
+             input. The header file with the same file name stem and an
+             extension ``.head`` is expected to be found in the same
+             directory.
 
     Parameters
     ----------
     input_fname : str
-        Path to the data file.
+        Path to the data file (ending with ``.data`` not ``.head``).
     ch_type : str
         Channel type to designate to the data channels. Supported data types
         include 'eeg', 'dbs'.
@@ -63,7 +64,13 @@ def read_raw_nicolet(input_fname, ch_type, eog=(),
 
 def _get_nicolet_info(fname, ch_type, eog, ecg, emg, misc):
     """Extract info from Nicolet header files."""
-    fname = path.splitext(fname)[0]
+    fname, extension = path.splitext(fname)
+
+    if extension != '.data':
+        raise ValueError(
+            f'File name should end with .data not "{extension}".'
+        )
+
     header = fname + '.head'
 
     logger.info('Reading header...')


Test patch:
diff --git a/mne/io/nicolet/tests/test_nicolet.py b/mne/io/nicolet/tests/test_nicolet.py
--- a/mne/io/nicolet/tests/test_nicolet.py
+++ b/mne/io/nicolet/tests/test_nicolet.py
@@ -6,19 +6,22 @@
 import os.path as op
 import inspect
 
-from mne.utils import run_tests_if_main
 from mne.io import read_raw_nicolet
 from mne.io.tests.test_raw import _test_raw_reader
 
+import pytest
+
 FILE = inspect.getfile(inspect.currentframe())
 base_dir = op.join(op.dirname(op.abspath(FILE)), 'data')
-fname = op.join(base_dir, 'test_nicolet_raw.data')
+fname_data = op.join(base_dir, 'test_nicolet_raw.data')
+fname_head = op.join(base_dir, 'test_nicolet_raw.head')
 
 
 def test_data():
     """Test reading raw nicolet files."""
-    _test_raw_reader(read_raw_nicolet, input_fname=fname, ch_type='eeg',
+    _test_raw_reader(read_raw_nicolet, input_fname=fname_data, ch_type='eeg',
                      ecg='auto', eog='auto', emg='auto', misc=['PHO'])
 
-
-run_tests_if_main()
+    with pytest.raises(ValueError,
+                       match='File name should end with .data not ".head".'):
+        read_raw_nicolet(fname_head, 'eeg')