Repository: mne-tools/mne-python

Issue:
Bad channels do not show up at all in `raw.plot()`
I don't know if this is an intentional change, but bad channels used to be drawn in gray, and now they don't show up at all:

```python
from numpy.random import default_rng

from mne import create_info
from mne.io import RawArray


def create_toy_data(n_channels=3, duration=25, sfreq=250, seed=None):
    rng = default_rng(seed)
    data = rng.standard_normal(size=(n_channels, duration * sfreq)) * 5e-6
    info = create_info(n_channels, sfreq, "eeg")
    return RawArray(data, info)


raw = create_toy_data()
raw.info["bads"] = ["1"]
raw.plot()  # channel 2 (labeled "1") is missing!
```

CC @hoechenberger 


Discussion:
Thanks for reporting this, @cbrnr. I ran into this today and I thought I was going crazy, constantly being unable to find certain channels – until I discovered they were bad and wouldn't even show up with `picks="all"` or `picks="eeg"`. Had to set `info["bads"] = []` to make them appear again.
PR #12467 introduced this regression. @ivopascal do you have time to fix this?
Can you see if changing this line

https://github.com/mne-tools/mne-python/pull/12467/files#diff-463b263c18142ec9504e9eef4ac62f3882d14cf0f3b6dfd001b0dc00d582ada7R316

To have `exclude=()` fixes the issue? I'm guessing it will

Resolving patch:
diff --git a/doc/conf.py b/doc/conf.py
--- a/doc/conf.py
+++ b/doc/conf.py
@@ -774,6 +774,7 @@ def append_attr_meth_examples(app, what, name, obj, options, lines):
 # -- Nitpicky ----------------------------------------------------------------
 
 nitpicky = True
+show_warning_types = True
 nitpick_ignore = [
     ("py:class", "None.  Remove all items from D."),
     ("py:class", "a set-like object providing a view on D's items"),
@@ -803,7 +804,10 @@ def append_attr_meth_examples(app, what, name, obj, options, lines):
         "(filename|metadata|proj|times|tmax|tmin|annotations|ch_names|compensation_grade|filenames|first_samp|first_time|last_samp|n_times|proj|times|tmax|tmin)",
     ),  # noqa: E501
 ]
-suppress_warnings = ["image.nonlocal_uri"]  # we intentionally link outside
+suppress_warnings = [
+    "image.nonlocal_uri",  # we intentionally link outside
+    "config.cache",  # our rebuild is okay
+]
 
 
 # -- Sphinx hacks / overrides ------------------------------------------------
diff --git a/mne/viz/raw.py b/mne/viz/raw.py
--- a/mne/viz/raw.py
+++ b/mne/viz/raw.py
@@ -313,7 +313,7 @@ def plot_raw(
     ch_names = np.array(raw.ch_names)
     ch_types = np.array(raw.get_channel_types())
 
-    picks = _picks_to_idx(info, picks, none="all")
+    picks = _picks_to_idx(info, picks, none="all", exclude=())
     order = _get_channel_plotting_order(order, ch_types, picks=picks)
     n_channels = min(info["nchan"], n_channels, len(order))
     # adjust order based on channel selection, if needed


Test patch:
diff --git a/mne/viz/tests/test_raw.py b/mne/viz/tests/test_raw.py
--- a/mne/viz/tests/test_raw.py
+++ b/mne/viz/tests/test_raw.py
@@ -541,6 +541,7 @@ def test_plot_raw_traces(raw, events, browser_backend):
     ismpl = browser_backend.name == "matplotlib"
     with raw.info._unlock():
         raw.info["lowpass"] = 10.0  # allow heavy decim during plotting
+    assert raw.info["bads"] == []
     fig = raw.plot(
         events=events, order=[1, 7, 5, 2, 3], n_channels=3, group_by="original"
     )
@@ -623,6 +624,12 @@ def test_plot_raw_traces(raw, events, browser_backend):
         raw.plot(event_color={"foo": "r"})
     plot_raw(raw, events=events, event_color={-1: "r", 998: "b"})
 
+    # gh-12547
+    raw.info["bads"] = raw.ch_names[1:2]
+    picks = [1, 7, 5, 2, 3]
+    fig = raw.plot(events=events, order=picks, group_by="original")
+    assert_array_equal(fig.mne.picks, picks)
+
 
 def test_plot_raw_picks(raw, browser_backend):
     """Test functionality of picks and order arguments."""