Repository: mne-tools/mne-python

Issue:
Merging Infos fails for numpy scalars
Merging ``Info``s fails when encountering numpy scalars (e.g., in ``'dig'``). This happens for example when adding a bipolar reference (see example below) or also when adding channels to a Raw after a montage has been set

#### Code to reproduce

```Python
import mne
import numpy as np

sfreq = 1000
n_samples = 1000
ch_data = np.random.randn(1, n_samples)

info1 = mne.create_info(['F9', 'F10'], sfreq, ['eeg'] * 2)
raw1 = mne.io.RawArray(np.concatenate([ch_data] * 2), info1)
raw1.set_montage(mne.channels.read_montage(kind='standard_1020'))

print(np.unique([str(type(raw1.info['dig'][i]['ident']))
                 for i in range(len(raw1.info['dig']))]))
# ["<class 'int'>" "<class 'numpy.int64'>"]

raw_new = mne.set_bipolar_reference(raw1, "F9", "F10", ch_name="HEOG", ch_info=None,
                          drop_refs=False, copy=True)
# File "path/to/mne-python/mne/utils/numerics.py", line 712, in object_diff
# RuntimeError: [3]['ident']: unsupported type <class 'numpy.int64'> (1)
```
This is due to the fact that the ``ident`` values are ``np.int64`` scalars (see https://github.com/mne-tools/mne-python/blob/master/mne/io/meas_info.py#L879) and the "switch-like"-construct in ``object_diff`` does not handle numpy scalars (https://github.com/mne-tools/mne-python/blob/master/mne/utils/numerics.py#L712)

#### Workaround and expected results
It works if we manually convert types.
```Python
 for i in range(len(raw1.info['dig'])):
        if isinstance(raw1.info['dig'][i]['ident'], np.generic):
            raw1.info['dig'][i]['ident'] = raw1.info['dig'][i][
                'ident'].tolist()
raw_new = mne.set_bipolar_reference(raw1, "F9", "F10", ch_name="HEOG", ch_info=None,
                          drop_refs=False, copy=True)
# does not fail
```

#### Suggested fix
``object_diff`` should also check for ``np.generic`` in addition to/instead of ``np.ndarray`` and simply check for equality. I can submit a PR if you agree with this fix.



Merging Infos fails for numpy scalars
Merging ``Info``s fails when encountering numpy scalars (e.g., in ``'dig'``). This happens for example when adding a bipolar reference (see example below) or also when adding channels to a Raw after a montage has been set

#### Code to reproduce

```Python
import mne
import numpy as np

sfreq = 1000
n_samples = 1000
ch_data = np.random.randn(1, n_samples)

info1 = mne.create_info(['F9', 'F10'], sfreq, ['eeg'] * 2)
raw1 = mne.io.RawArray(np.concatenate([ch_data] * 2), info1)
raw1.set_montage(mne.channels.read_montage(kind='standard_1020'))

print(np.unique([str(type(raw1.info['dig'][i]['ident']))
                 for i in range(len(raw1.info['dig']))]))
# ["<class 'int'>" "<class 'numpy.int64'>"]

raw_new = mne.set_bipolar_reference(raw1, "F9", "F10", ch_name="HEOG", ch_info=None,
                          drop_refs=False, copy=True)
# File "path/to/mne-python/mne/utils/numerics.py", line 712, in object_diff
# RuntimeError: [3]['ident']: unsupported type <class 'numpy.int64'> (1)
```
This is due to the fact that the ``ident`` values are ``np.int64`` scalars (see https://github.com/mne-tools/mne-python/blob/master/mne/io/meas_info.py#L879) and the "switch-like"-construct in ``object_diff`` does not handle numpy scalars (https://github.com/mne-tools/mne-python/blob/master/mne/utils/numerics.py#L712)

#### Workaround and expected results
It works if we manually convert types.
```Python
 for i in range(len(raw1.info['dig'])):
        if isinstance(raw1.info['dig'][i]['ident'], np.generic):
            raw1.info['dig'][i]['ident'] = raw1.info['dig'][i][
                'ident'].tolist()
raw_new = mne.set_bipolar_reference(raw1, "F9", "F10", ch_name="HEOG", ch_info=None,
                          drop_refs=False, copy=True)
# does not fail
```

#### Suggested fix
``object_diff`` should also check for ``np.generic`` in addition to/instead of ``np.ndarray`` and simply check for equality. I can submit a PR if you agree with this fix.





Discussion:
Yes making `object_diff` better at its job is a good fix
Yes making `object_diff` better at its job is a good fix

Resolving patch:
diff --git a/mne/utils/numerics.py b/mne/utils/numerics.py
--- a/mne/utils/numerics.py
+++ b/mne/utils/numerics.py
@@ -683,7 +683,7 @@ def object_diff(a, b, pre=''):
         else:
             for ii, (xx1, xx2) in enumerate(zip(a, b)):
                 out += object_diff(xx1, xx2, pre + '[%s]' % ii)
-    elif isinstance(a, (str, int, float, bytes)):
+    elif isinstance(a, (str, int, float, bytes, np.generic)):
         if a != b:
             out += pre + ' value mismatch (%s, %s)\n' % (a, b)
     elif a is None:


Test patch: