Repository: mne-tools/mne-python

Issue:
plot_evoked(gfp=True) with single-channel data behaves incorrectly
#### Problem
Plotting the GFP of data with only a single sensor via `plot_evoked(gfp=True)` produces a GFP, although the GFP – describing the spatial standard deviation – should not exist.

#### Steps to reproduce
```python
import os
import mne
sample_data_folder = mne.datasets.sample.data_path()
sample_data_raw_file = os.path.join(sample_data_folder, 'MEG', 'sample',
                                    'sample_audvis_raw.fif')
raw = mne.io.read_raw_fif(sample_data_raw_file, verbose=False)
events = mne.find_events(raw, stim_channel='STI 014')
event_dict = {'auditory/left': 1, 'auditory/right': 2, 'visual/left': 3,
              'visual/right': 4}
epochs = mne.Epochs(raw, events, tmin=-0.3, tmax=0.7, event_id=event_dict,
                    preload=True)
evoked = epochs['auditory/left'].average()

evoked.pick('EEG 001').plot(gfp=True)
```

#### Expected results
- either no GFP trace, or
- a GFP constantly at zero, or
- a warning, or
- an error message

#### Actual results
GFP is displayed as the absolute value of the sensor signal.
<img width="440" alt="Screen Shot 2021-01-22 at 16 27 48" src="https://user-images.githubusercontent.com/2046265/105510306-c69b0a80-5cce-11eb-90e5-3c628b4e2f62.png">


#### Additional information
Using `master`.


Discussion:

Resolving patch:
diff --git a/mne/viz/evoked.py b/mne/viz/evoked.py
--- a/mne/viz/evoked.py
+++ b/mne/viz/evoked.py
@@ -473,7 +473,14 @@ def _plot_lines(data, info, picks, fig, axes, spatial_colors, unit, units,
                                 linewidth=0.5)[0])
                     line_list[-1].set_pickradius(3.)
 
-            if gfp:  # 'only' or boolean True
+            if gfp == 'only' and D.shape[0] == 1:
+                # Only a single channel + only GFP -> abort mission!
+                raise ValueError('Cannot calculate GFP with only one data '
+                                 'channel')
+            elif gfp and D.shape[0] == 1:
+                warn('Cannot calculate GFP with only one data channel, '
+                     'not plotting GFP')
+            elif gfp:  # gfp 'only' or boolean True
                 gfp_color = 3 * (0.,) if spatial_colors is True else (0., 1.,
                                                                       0.)
                 this_gfp = np.sqrt((D * D).mean(axis=0))
@@ -674,8 +681,9 @@ def plot_evoked(evoked, picks=None, exclude='bads', unit=True, show=True,
         the same length as the number of channel types. If instance of
         Axes, there must be only one channel type plotted.
     gfp : bool | 'only'
-        Plot GFP in green if True or "only". If "only", then the individual
-        channel traces will not be shown.
+        Plot the GFP and the traces for all channels if ``True``; or only the
+        GFP if ``'only'``, hiding the channel traces. The color of the GFP
+        trace will be green if ``spatial_colors=False``, and black otherwise.
     window_title : str | None
         The title to put at the top of the figure.
     spatial_colors : bool


Test patch:
diff --git a/mne/viz/tests/test_evoked.py b/mne/viz/tests/test_evoked.py
--- a/mne/viz/tests/test_evoked.py
+++ b/mne/viz/tests/test_evoked.py
@@ -126,6 +126,13 @@ def test_plot_evoked():
     evoked.plot(gfp='only', time_unit='s')
     pytest.raises(ValueError, evoked.plot, gfp='foo', time_unit='s')
 
+    # test GFP plotting with only a single data channel
+    with pytest.warns(RuntimeWarning, match='Cannot calculate GFP'):
+        evoked.copy().pick(evoked.ch_names[0]).plot(gfp=True)
+    with pytest.raises(ValueError, match='Cannot calculate GFP'):
+        evoked.copy().pick(evoked.ch_names[0]).plot(gfp='only')
+    plt.close('all')
+
     # plot with bad channels excluded, spatial_colors, zorder & pos. layout
     evoked.rename_channels({'MEG 0133': 'MEG 0000'})
     evoked.plot(exclude=evoked.info['bads'], spatial_colors=True, gfp=True,