Repository: mne-tools/mne-bids-pipeline

Issue:
Report section on original raw data doesn't contain bads
In my BIDS data, 3 channels are marked as bad. These show up correctly in the HTML repr for the filtered and cleaned raw, but not for the original raw. The content of the generated `*_bads.tsv` file is:

```
name	reason
P8	pre-existing (before MNE-BIDS-pipeline was run)
T7	pre-existing (before MNE-BIDS-pipeline was run)
TP10	pre-existing (before MNE-BIDS-pipeline was run)
```

<img width="984" alt="Screenshot 2024-04-23 at 13 17 29" src="https://github.com/mne-tools/mne-bids-pipeline/assets/2046265/3ffc2d00-a723-4418-8c15-c06c52695671">


<img width="984" alt="Screenshot 2024-04-23 at 13 17 34" src="https://github.com/mne-tools/mne-bids-pipeline/assets/2046265/85e577b6-6abe-47f5-9ca2-2c6d63183379">

I tried to understand what was going on but so far I don't really have a clue.



Discussion:
I also just realized that experimenter and participant are also not correctly represented in the "original" repr.
@SophieHerbst Do you see similar issues with your reports?
Are you fully up to date with your MNE version? If you're a couple weeks behind you might be hitting a bug that was in MNE for a bit
... Or if you generated those sections a couple of weeks ago could be same thing. Might be worth rerunning from scratch now to check
https://github.com/mne-tools/mne-python/pull/12548
everything's up to date and i had deleted the outputs entirely...

will check again to be sure 
> https://github.com/mne-tools/mne-python/pull/12548

that's not the problem, it is as of part of my raw.info is simply missing 
Sounds like the bads just aren't being loaded from the sidecar then. I bet bads aren't displayed in the info repr if the list is empty. And they probably aren't defined in the raw on disk itself but rather in the sidecar file
> Sounds like the bads just aren't being loaded from the sidecar then.

Yep that's it. Looking into this now. Thanks for your help!

Resolving patch:
diff --git a/mne_bids_pipeline/_report.py b/mne_bids_pipeline/_report.py
--- a/mne_bids_pipeline/_report.py
+++ b/mne_bids_pipeline/_report.py
@@ -848,9 +848,9 @@ def _add_raw(
     cfg: SimpleNamespace,
     report: mne.report.Report,
     bids_path_in: BIDSPath,
+    raw: BaseRaw,
     title: str,
     tags: tuple = (),
-    raw: BaseRaw | None = None,
     extra_html: str | None = None,
 ):
     if bids_path_in.run is not None:
@@ -865,7 +865,7 @@ def _add_raw(
     tags = ("raw", f"run-{bids_path_in.run}") + tags
     with mne.use_log_level("error"):
         report.add_raw(
-            raw=raw or bids_path_in,
+            raw=raw,
             title=title,
             butterfly=5,
             psd=plot_raw_psd,
diff --git a/mne_bids_pipeline/steps/preprocessing/_01_data_quality.py b/mne_bids_pipeline/steps/preprocessing/_01_data_quality.py
--- a/mne_bids_pipeline/steps/preprocessing/_01_data_quality.py
+++ b/mne_bids_pipeline/steps/preprocessing/_01_data_quality.py
@@ -101,7 +101,7 @@ def assess_data_quality(
             cfg=cfg,
             data_is_rest=data_is_rest,
         )
-    preexisting_bads = set(raw.info["bads"])
+    preexisting_bads = sorted(raw.info["bads"])
 
     if _do_mf_autobad(cfg=cfg):
         (
@@ -118,13 +118,13 @@ def assess_data_quality(
             task=task,
         )
         bads = sorted(set(raw.info["bads"] + auto_noisy_chs + auto_flat_chs))
-        msg = f"Found {len(bads)} channel{_pl(bads)} as bad."
+        msg = f"Found {len(bads)} bad channel{_pl(bads)}."
         raw.info["bads"] = bads
         del bads
         logger.info(**gen_log_kwargs(message=msg))
     else:
         auto_scores = auto_noisy_chs = auto_flat_chs = None
-    del key, raw
+    del key
 
     # Always output the scores and bads TSV
     out_files["auto_scores"] = bids_path_in.copy().update(
@@ -149,27 +149,40 @@ def assess_data_quality(
     reasons = []
 
     if auto_flat_chs:
-        bads_for_tsv.extend(auto_flat_chs)
-        reasons.extend(["auto-flat"] * len(auto_flat_chs))
-        preexisting_bads -= set(auto_flat_chs)
+        for ch in auto_flat_chs:
+            reason = (
+                "pre-existing (before MNE-BIDS-pipeline was run) & auto-flat"
+                if ch in preexisting_bads
+                else "auto-flat"
+            )
+            bads_for_tsv.append(ch)
+            reasons.append(reason)
 
-    if auto_noisy_chs is not None:
-        bads_for_tsv.extend(auto_noisy_chs)
-        reasons.extend(["auto-noisy"] * len(auto_noisy_chs))
-        preexisting_bads -= set(auto_noisy_chs)
+    if auto_noisy_chs:
+        for ch in auto_noisy_chs:
+            reason = (
+                "pre-existing (before MNE-BIDS-pipeline was run) & auto-noisy"
+                if ch in preexisting_bads
+                else "auto-noisy"
+            )
+            bads_for_tsv.append(ch)
+            reasons.append(reason)
 
-    preexisting_bads = sorted(preexisting_bads)
     if preexisting_bads:
-        bads_for_tsv.extend(preexisting_bads)
-        reasons.extend(
-            ["pre-existing (before MNE-BIDS-pipeline was run)"] * len(preexisting_bads)
-        )
+        for ch in preexisting_bads:
+            if ch in bads_for_tsv:
+                continue
+            bads_for_tsv.append(ch)
+            reasons.append("pre-existing (before MNE-BIDS-pipeline was run)")
 
     tsv_data = pd.DataFrame(dict(name=bads_for_tsv, reason=reasons))
     tsv_data = tsv_data.sort_values(by="name")
     tsv_data.to_csv(out_files["bads_tsv"], sep="\t", index=False)
 
     # Report
+    # Restore bads to their original state so they will show up in the report
+    raw.info["bads"] = preexisting_bads
+
     with _open_report(
         cfg=cfg,
         exec_params=exec_params,
@@ -186,6 +199,7 @@ def assess_data_quality(
             cfg=cfg,
             report=report,
             bids_path_in=bids_path_in,
+            raw=raw,
             title=f"Raw ({kind})",
             tags=("data-quality",),
         )
@@ -218,7 +232,7 @@ def _find_bads_maxwell(
     *,
     cfg: SimpleNamespace,
     exec_params: SimpleNamespace,
-    raw: mne.io.Raw,
+    raw: mne.io.BaseRaw,
     subject: str,
     session: str | None,
     run: str | None,


Test patch: