Repository: mne-tools/mne-python

Issue:
missing template for topoplot
Hello, 
Trying to use evoked.plot_topomap on MEG data with .sqd format and receive this message error:

"The layout for the KIT system with ID 35 is missing. Please contact the developers about adding it."

Thanks for your help!
Claire



Discussion:
Can you share the file ? Where is the file coming from ?

The file come from NYU MEG system.

File can be downloaded here:

https://we.tl/t-Ezmn5SI0lQ


Thanks,
Claire

> Le 2 oct. 2019 à 19:18, Alexandre Gramfort <notifications@github.com> a écrit :
> 
> Can you share the file ? Where is the file coming from ?
> —
> You are receiving this because you authored the thread.
> Reply to this email directly, view it on GitHub <https://github.com/mne-tools/mne-python/issues/6891?email_source=notifications&email_token=ALO6B6EXU673T7FFIKMSDBTQMUT6BA5CNFSM4I44LLKKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEAGPQ7Q#issuecomment-537720958>, or mute the thread <https://github.com/notifications/unsubscribe-auth/ALO6B6H4FKBUHLI6ITV3MGDQMUT6BANCNFSM4I44LLKA>.
> 


it looks like christian updated the kit module to support that ID in `0.19` right before release. @cpelofi, which version of mne are you currently running? it might just need a quick update
I just ran 

pip install mne --upgrade

Received that:

Found existing installation: mne 0.18.1
    Uninstalling mne-0.18.1:
      Successfully uninstalled mne-0.18.1
Successfully installed mne-0.19.0


Then ran again

evoked = epochs['tone'].average()
evoked.plot()
evoked.plot(spatial_colors = True, gfp = True)

times = np.arange(0., 0.4, 0.04)
evoked.plot_topomap(times=times)

And received the same message..




> Le 2 oct. 2019 à 19:35, Teon L Brooks <notifications@github.com> a écrit :
> 
> it looks like christian updated the kit module to support that ID in 0.19 right before release. @cpelofi <https://github.com/cpelofi>, which version of mne are you currently running? it might just need a quick update
> 
> —
> You are receiving this because you were mentioned.
> Reply to this email directly, view it on GitHub <https://github.com/mne-tools/mne-python/issues/6891?email_source=notifications&email_token=ALO6B6D7BJD3UUHAE4TP7SDQMUV33A5CNFSM4I44LLKKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEAGQMSY#issuecomment-537724491>, or mute the thread <https://github.com/notifications/unsubscribe-auth/ALO6B6BNXMMJSR5FDRIZTRLQMUV33ANCNFSM4I44LLKA>.
> 



I just upgraded to the 0.19 version but still get the same error message when I run the topomap.





> Le 2 oct. 2019 à 19:35, Teon L Brooks <notifications@github.com> a écrit :
> 
> it looks like christian updated the kit module to support that ID in 0.19 right before release. @cpelofi <https://github.com/cpelofi>, which version of mne are you currently running? it might just need a quick update
> 
> —
> You are receiving this because you were mentioned.
> Reply to this email directly, view it on GitHub <https://github.com/mne-tools/mne-python/issues/6891?email_source=notifications&email_token=ALO6B6D7BJD3UUHAE4TP7SDQMUV33A5CNFSM4I44LLKKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEAGQMSY#issuecomment-537724491>, or mute the thread <https://github.com/notifications/unsubscribe-auth/ALO6B6BNXMMJSR5FDRIZTRLQMUV33ANCNFSM4I44LLKA>.
> 


@christianbrodbeck can you have a look?
Yeah I added sensor connectivity but not a layout. Is there a layout or a standard way for generating such a layout manually? Otherwise I would suggest to fall back on the automatic code in `find_layout` for missing KIT IDs. I can make PR if that seems like a good option. 
whatever works. for MEG systems we tend to have predefined layout files.
Maybe fieldtrip has made one we can reuse?

>

I doubt it since this system has only just been updated (including a layout change)

Resolving patch:
diff --git a/mne/channels/layout.py b/mne/channels/layout.py
--- a/mne/channels/layout.py
+++ b/mne/channels/layout.py
@@ -397,6 +397,7 @@ def find_layout(info, ch_type=None, exclude='bads'):
     if ch_type == "eeg" and not has_eeg_coils:
         raise RuntimeError('No EEG channels present. Cannot find EEG layout.')
 
+    layout_name = None
     if ((has_vv_meg and ch_type is None) or
             (any([has_vv_mag, has_vv_grad]) and ch_type == 'meg')):
         layout_name = 'Vectorview-all'
@@ -421,7 +422,9 @@ def find_layout(info, ch_type=None, exclude='bads'):
         layout_name = 'CTF-275'
     elif n_kit_grads > 0:
         layout_name = _find_kit_layout(info, n_kit_grads)
-    else:
+
+    # If no known layout is found, fall back on automatic layout
+    if layout_name is None:
         xy = _auto_topomap_coords(info, picks=range(info['nchan']),
                                   ignore_overlap=True, to_sphere=False)
         return generate_2d_layout(xy, ch_names=info['ch_names'], name='custom',
@@ -456,26 +459,17 @@ def _find_kit_layout(info, n_grads):
 
     Returns
     -------
-    kit_layout : str
-        One of 'KIT-AD', 'KIT-157', 'KIT-160', or 'KIT-UMD'.
+    kit_layout : str | None
+        String naming the detected KIT layout or ``None`` if layout is missing.
     """
     if info['kit_system_id'] is not None:
         # avoid circular import
         from ..io.kit.constants import KIT_LAYOUT
-
-        if info['kit_system_id'] in KIT_LAYOUT:
-            kit_layout = KIT_LAYOUT[info['kit_system_id']]
-            if kit_layout is not None:
-                return kit_layout
-        raise NotImplementedError("The layout for the KIT system with ID %i "
-                                  "is missing. Please contact the developers "
-                                  "about adding it." % info['kit_system_id'])
+        return KIT_LAYOUT.get(info['kit_system_id'])
     elif n_grads == 160:
         return 'KIT-160'
-
     elif n_grads == 125:
         return 'KIT-125'
-
     elif n_grads > 157:
         return 'KIT-AD'
 
@@ -700,6 +694,9 @@ def _auto_topomap_coords(info, picks, ignore_overlap=False, to_sphere=True):
         eeg_ch_locs = dict(zip(eeg_ch_names, locs3d))
         locs3d = np.array([eeg_ch_locs[ch['ch_name']] for ch in chs])
 
+    # Sometimes we can get nans
+    locs3d[~np.isfinite(locs3d)] = 0.
+
     # Duplicate points cause all kinds of trouble during visualization
     dist = pdist(locs3d)
     if len(locs3d) > 1 and np.min(dist) < 1e-10 and not ignore_overlap:
@@ -715,6 +712,7 @@ def _auto_topomap_coords(info, picks, ignore_overlap=False, to_sphere=True):
     if to_sphere:
         # use spherical (theta, pol) as (r, theta) for polar->cartesian
         return _pol_to_cart(_cart_to_sph(locs3d)[:, 1:][:, ::-1])
+
     return _pol_to_cart(_cart_to_sph(locs3d))
 
 


Test patch:
diff --git a/mne/channels/tests/test_layout.py b/mne/channels/tests/test_layout.py
--- a/mne/channels/tests/test_layout.py
+++ b/mne/channels/tests/test_layout.py
@@ -254,6 +254,10 @@ def test_find_layout():
     raw_kit.info['bads'] = ['MEG  13', 'MEG  14', 'MEG  15', 'MEG  16']
     lout = find_layout(raw_kit.info)
     assert_equal(lout.kind, 'KIT-157')
+    # fallback for missing IDs
+    raw_kit.info['kit_system_id'] = 35
+    lout = find_layout(raw_kit.info)
+    assert lout.kind == 'custom'
 
     raw_umd = read_raw_kit(fname_kit_umd)
     lout = find_layout(raw_umd.info)