Repository: mne-tools/mne-python

Issue:
Reset montage in raw?
I was wondering if the montage can somehow be reset in an existing `raw` object. Suppose I did `raw.set_montage('biosemi64')`, but later I decide I want to reset the montage to nothing - how can I do that?

Does this make sense (during interactive data exploration it would be useful for me)? If yes, is it doable (I assume only if `update_ch_names=False`, because otherwise how should we reconstruct the original channel names)?


Discussion:
> but later I decide I want to reset the montage to nothing

You'll have to be more specific about what you mean. If you mean removing channel position information for all EEG channels, that's easy. If you mean properly resetting to a previous state of the object (e.g., keeping track of which EEG channels had positions set and names changed and only changing those), it will be much harder. In other words, doing `raw.set_montage(None)` that just wipes EEG channel locations is easy, doing `raw.unset_montage()` that should get me back the same `raw` object I had before doing `raw.set_montage('biosemi64'`)` is much harder and probably not worth it.

How is wiping channel location information useful during data exploration?
It's maybe just a usability thing. If I can set a montage I'd expect that I can also unset it. I guess removing channel position information is sufficient for now (especially since names are not changed by default).

If this is not needed in MNE I can also just implement a custom function in MNELAB.
can you explain why you would want to reset it? just apply a new one if you
made a mistake no?

@agramfort right, but you usually start out with no montage, so although a little OCD it would be nice to go back to a blank slate (e.g. if it turns out that there is no suitable montage file that works with the data or something).
+1 for `set_montage(None)` erasing EEG channel and fiducial positions

Resolving patch:
diff --git a/mne/channels/channels.py b/mne/channels/channels.py
--- a/mne/channels/channels.py
+++ b/mne/channels/channels.py
@@ -480,8 +480,8 @@ def set_montage(self, montage, set_dig=True, verbose=None):
 
         Parameters
         ----------
-        montage : instance of Montage or DigMontage
-            The montage to use.
+        montage : instance of Montage | instance of DigMontage | None
+            The montage to use (None removes any location information).
         set_dig : bool
             If True, update the digitization information (``info['dig']``)
             in addition to the channel positions (``info['chs'][idx]['loc']``).
diff --git a/mne/channels/montage.py b/mne/channels/montage.py
--- a/mne/channels/montage.py
+++ b/mne/channels/montage.py
@@ -778,8 +778,8 @@ def _set_montage(info, montage, update_ch_names=False, set_dig=True):
     ----------
     info : instance of Info
         The measurement info to update.
-    montage : instance of Montage | instance of DigMontage
-        The montage to apply.
+    montage : instance of Montage | instance of DigMontage | None
+        The montage to apply (None removes any location information).
     update_ch_names : bool
         If True, overwrite the info channel names with the ones from montage.
         Defaults to False.
@@ -878,6 +878,11 @@ def _set_montage(info, montage, update_ch_names=False, set_dig=True):
             if len(did_not_set) > 0:
                 warn('Did not set %s channel positions:\n%s'
                      % (len(did_not_set), ', '.join(did_not_set)))
+    elif montage is None:
+        for ch in info['chs']:
+            ch['loc'] = np.zeros(12)
+        if set_dig:
+            info['dig'] = None
     else:
         raise TypeError("Montage must be a 'Montage' or 'DigMontage' "
                         "instead of '%s'." % type(montage))
diff --git a/mne/io/meas_info.py b/mne/io/meas_info.py
--- a/mne/io/meas_info.py
+++ b/mne/io/meas_info.py
@@ -1723,7 +1723,6 @@ def create_info(ch_names, sfreq, ch_types=None, montage=None, verbose=None):
                          '(%s != %s)' % (len(ch_types), nchan))
     info = _empty_info(sfreq)
     info['meas_date'] = np.array([0, 0], np.int32)
-    loc = np.concatenate((np.zeros(3), np.eye(3).ravel())).astype(np.float32)
     for ci, (name, kind) in enumerate(zip(ch_names, ch_types)):
         if not isinstance(name, string_types):
             raise TypeError('each entry in ch_names must be a string')
@@ -1733,7 +1732,7 @@ def create_info(ch_names, sfreq, ch_types=None, montage=None, verbose=None):
             raise KeyError('kind must be one of %s, not %s'
                            % (list(_kind_dict.keys()), kind))
         kind = _kind_dict[kind]
-        chan_info = dict(loc=loc.copy(), unit_mul=0, range=1., cal=1.,
+        chan_info = dict(loc=np.zeros(12), unit_mul=0, range=1., cal=1.,
                          kind=kind[0], coil_type=kind[1],
                          unit=kind[2], coord_frame=FIFF.FIFFV_COORD_UNKNOWN,
                          ch_name=name, scanno=ci + 1, logno=ci + 1)


Test patch: