From 54dd4a11ba67c770a01d62bb35c76d19fdd8c34b Mon Sep 17 00:00:00 2001
From: 1himan <vanshumahor@gmail.com>
Date: Mon, 1 Dec 2025 19:38:02 +0530
Subject: [PATCH 01/25] Raising meaningful warnings/errors for
 interpolate_bads, when supplied loc field with missing or invalid data

---
 mne/channels/channels.py | 23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/mne/channels/channels.py b/mne/channels/channels.py
index ef98efd1731..4e4ba2a5234 100644
--- a/mne/channels/channels.py
+++ b/mne/channels/channels.py
@@ -714,6 +714,7 @@ def add_channels(self, add_list, force_update_info=False):
 
         _validate_type(add_list, (list, tuple), "Input")
 
+        
         # Object-specific checks
         for inst in add_list + [self]:
             _check_preload(inst, "adding channels")
@@ -828,6 +829,7 @@ def interpolate_bads(
         method=None,
         exclude=(),
         verbose=None,
+        **kwargs
     ):
         """Interpolate bad MEG and EEG channels.
 
@@ -896,6 +898,27 @@ def interpolate_bads(
 
         _check_preload(self, "interpolation")
         _validate_type(method, (dict, str, None), "method")
+        bads_to_check = self.info['bads']
+        for ch_name in bads_to_check:
+            try:
+                ch_idx = self.ch_names.index(ch_name)
+                ch_loc = self.info['chs'][ch_idx]['loc']
+                is_loc_invalid = np.allclose(ch_loc, 0.0, atol=1e-16) or np.any(np.isnan(ch_loc))
+            except ValueError:
+                continue
+
+            if is_loc_invalid:
+                msg = (
+                    f"Bad channel '{ch_name}' is missing valid sensor position (loc) information. "
+                    "Interpolation cannot proceed correctly."
+                )
+                _on_missing(
+                    kwargs.get("on_no_position", "error"),
+                    msg
+                    + " If you want to continue despite missing positions, set "
+                    "on_no_position='warn' or 'ignore'.",
+                )
+
         method = _handle_default("interpolation_method", method)
         ch_types = self.get_channel_types(unique=True)
         # figure out if we have "mag" for "meg", "hbo" for "fnirs", ... to filter the

From be254c4fd3bc1e52a031ed5b41b96160cb3ab1e4 Mon Sep 17 00:00:00 2001
From: "pre-commit-ci[bot]"
 <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Date: Mon, 1 Dec 2025 14:10:44 +0000
Subject: [PATCH 02/25] [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci
---
 mne/channels/channels.py | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/mne/channels/channels.py b/mne/channels/channels.py
index 4e4ba2a5234..e57de953e9d 100644
--- a/mne/channels/channels.py
+++ b/mne/channels/channels.py
@@ -714,7 +714,6 @@ def add_channels(self, add_list, force_update_info=False):
 
         _validate_type(add_list, (list, tuple), "Input")
 
-        
         # Object-specific checks
         for inst in add_list + [self]:
             _check_preload(inst, "adding channels")
@@ -829,7 +828,7 @@ def interpolate_bads(
         method=None,
         exclude=(),
         verbose=None,
-        **kwargs
+        **kwargs,
     ):
         """Interpolate bad MEG and EEG channels.
 
@@ -898,12 +897,14 @@ def interpolate_bads(
 
         _check_preload(self, "interpolation")
         _validate_type(method, (dict, str, None), "method")
-        bads_to_check = self.info['bads']
+        bads_to_check = self.info["bads"]
         for ch_name in bads_to_check:
             try:
                 ch_idx = self.ch_names.index(ch_name)
-                ch_loc = self.info['chs'][ch_idx]['loc']
-                is_loc_invalid = np.allclose(ch_loc, 0.0, atol=1e-16) or np.any(np.isnan(ch_loc))
+                ch_loc = self.info["chs"][ch_idx]["loc"]
+                is_loc_invalid = np.allclose(ch_loc, 0.0, atol=1e-16) or np.any(
+                    np.isnan(ch_loc)
+                )
             except ValueError:
                 continue
 
@@ -914,8 +915,7 @@ def interpolate_bads(
                 )
                 _on_missing(
                     kwargs.get("on_no_position", "error"),
-                    msg
-                    + " If you want to continue despite missing positions, set "
+                    msg + " If you want to continue despite missing positions, set "
                     "on_no_position='warn' or 'ignore'.",
                 )
 

From 7f5d63b5a457c110733d7ca45dd3a95d59c090e4 Mon Sep 17 00:00:00 2001
From: 1himan <vanshumahor@gmail.com>
Date: Wed, 3 Dec 2025 11:31:22 +0530
Subject: [PATCH 03/25] Improved logic and error message

---
 app.py                   | 39 +++++++++++++++++++++++++++++++++++++++
 mne/channels/channels.py | 37 +++++++++++++++----------------------
 2 files changed, 54 insertions(+), 22 deletions(-)
 create mode 100644 app.py

diff --git a/app.py b/app.py
new file mode 100644
index 00000000000..22d0de3631f
--- /dev/null
+++ b/app.py
@@ -0,0 +1,39 @@
+import numpy as np
+import mne
+# 1. Load sample Raw data (ensures other channels have positions for interpolation)
+# We crop the data to 1 second to make it fast.
+print("Step 1: Loading sample MEG data...")
+data_path = mne.datasets.sample.data_path()
+raw_fname = data_path / 'MEG' / 'sample' / 'sample_audvis_raw.fif'
+raw = mne.io.read_raw_fif(raw_fname, preload=True).pick_types(meg=True).crop(0, 1)
+
+sfreq = raw.info['sfreq']
+n_samples = raw.n_times
+
+# 2. Create a new "empty" channel that *lacks sensor positions*
+new_ch_name = 'MEG_BAD_NO_POS'
+empty_ch_data = np.zeros((1, n_samples))
+
+# The key is here: The created info object for a new channel does NOT have sensor positions (loc).
+info_empty = mne.create_info(ch_names=[new_ch_name], sfreq=sfreq, ch_types=['mag'])
+raw_ch = mne.io.RawArray(data=empty_ch_data, info=info_empty)
+
+# 3. Add the new channel to the main Raw object
+raw.add_channels([raw_ch], force_update_info=True)
+
+# 4. Mark the channel as bad
+raw.info['bads'] = [new_ch_name]
+idx = raw.ch_names.index(new_ch_name)
+# 5. Interpolate bad channels (This runs *silently* without error/warning)
+print("\nStep 5: Running raw.interpolate_bads()...")
+raw_interp = raw.copy().interpolate_bads()
+
+# 6. Check the interpolated channel data (Replication of the error)
+interp_data = raw_interp.get_data(picks=new_ch_name)[0]
+is_nan = np.isnan(interp_data).all()
+print(interp_data)
+print("\n--- Replication Result ---")
+print(f"Is the interpolated channel '{new_ch_name}' entirely NaN? {is_nan}")
+if is_nan:
+    print("✅ The bug is replicated: Interpolation failed silently, resulting in NaN data.")
+print(raw.info['chs'][idx]['loc'])
\ No newline at end of file
diff --git a/mne/channels/channels.py b/mne/channels/channels.py
index e57de953e9d..50592cf234f 100644
--- a/mne/channels/channels.py
+++ b/mne/channels/channels.py
@@ -827,8 +827,8 @@ def interpolate_bads(
         origin="auto",
         method=None,
         exclude=(),
+        on_no_position="raise",
         verbose=None,
-        **kwargs,
     ):
         """Interpolate bad MEG and EEG channels.
 
@@ -897,27 +897,20 @@ def interpolate_bads(
 
         _check_preload(self, "interpolation")
         _validate_type(method, (dict, str, None), "method")
-        bads_to_check = self.info["bads"]
-        for ch_name in bads_to_check:
-            try:
-                ch_idx = self.ch_names.index(ch_name)
-                ch_loc = self.info["chs"][ch_idx]["loc"]
-                is_loc_invalid = np.allclose(ch_loc, 0.0, atol=1e-16) or np.any(
-                    np.isnan(ch_loc)
-                )
-            except ValueError:
-                continue
-
-            if is_loc_invalid:
-                msg = (
-                    f"Bad channel '{ch_name}' is missing valid sensor position (loc) information. "
-                    "Interpolation cannot proceed correctly."
-                )
-                _on_missing(
-                    kwargs.get("on_no_position", "error"),
-                    msg + " If you want to continue despite missing positions, set "
-                    "on_no_position='warn' or 'ignore'.",
-                )
+        
+        invalid_chs = []
+        for ch in self.info['bads']:
+            loc = self.info['chs'][self.ch_names.index(ch)]['loc']
+            if np.allclose(loc, 0.0, atol=1e-16) or np.isnan(loc).any():
+                invalid_chs.append(ch)
+
+        if invalid_chs:
+            msg = (
+                f"Bad channel(s) '{invalid_chs}' have missing valid sensor position (loc) information."
+                "\nInterpolation cannot proceed correctly. If you want to continue despite missing positions, set "
+                "on_no_position='warn' or 'ignore', which outputs all NaN values(np.nan) for the interpolated channel(s)."
+            )
+            _on_missing(on_no_position, msg)
 
         method = _handle_default("interpolation_method", method)
         ch_types = self.get_channel_types(unique=True)

From 0fa2ba9c8807fbad3d7da9aa16b0c48bf6051784 Mon Sep 17 00:00:00 2001
From: "pre-commit-ci[bot]"
 <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Date: Wed, 3 Dec 2025 06:01:54 +0000
Subject: [PATCH 04/25] [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci
---
 mne/channels/channels.py | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/mne/channels/channels.py b/mne/channels/channels.py
index 50592cf234f..5cdaf4fefac 100644
--- a/mne/channels/channels.py
+++ b/mne/channels/channels.py
@@ -897,10 +897,10 @@ def interpolate_bads(
 
         _check_preload(self, "interpolation")
         _validate_type(method, (dict, str, None), "method")
-        
+
         invalid_chs = []
-        for ch in self.info['bads']:
-            loc = self.info['chs'][self.ch_names.index(ch)]['loc']
+        for ch in self.info["bads"]:
+            loc = self.info["chs"][self.ch_names.index(ch)]["loc"]
             if np.allclose(loc, 0.0, atol=1e-16) or np.isnan(loc).any():
                 invalid_chs.append(ch)
 

From 272c38aa4d035a55e6ec21b3742aab63640d5fc6 Mon Sep 17 00:00:00 2001
From: 1himan <vanshumahor@gmail.com>
Date: Wed, 3 Dec 2025 11:32:37 +0530
Subject: [PATCH 05/25] Removed my custome testing file

---
 app.py | 39 ---------------------------------------
 1 file changed, 39 deletions(-)
 delete mode 100644 app.py

diff --git a/app.py b/app.py
deleted file mode 100644
index 22d0de3631f..00000000000
--- a/app.py
+++ /dev/null
@@ -1,39 +0,0 @@
-import numpy as np
-import mne
-# 1. Load sample Raw data (ensures other channels have positions for interpolation)
-# We crop the data to 1 second to make it fast.
-print("Step 1: Loading sample MEG data...")
-data_path = mne.datasets.sample.data_path()
-raw_fname = data_path / 'MEG' / 'sample' / 'sample_audvis_raw.fif'
-raw = mne.io.read_raw_fif(raw_fname, preload=True).pick_types(meg=True).crop(0, 1)
-
-sfreq = raw.info['sfreq']
-n_samples = raw.n_times
-
-# 2. Create a new "empty" channel that *lacks sensor positions*
-new_ch_name = 'MEG_BAD_NO_POS'
-empty_ch_data = np.zeros((1, n_samples))
-
-# The key is here: The created info object for a new channel does NOT have sensor positions (loc).
-info_empty = mne.create_info(ch_names=[new_ch_name], sfreq=sfreq, ch_types=['mag'])
-raw_ch = mne.io.RawArray(data=empty_ch_data, info=info_empty)
-
-# 3. Add the new channel to the main Raw object
-raw.add_channels([raw_ch], force_update_info=True)
-
-# 4. Mark the channel as bad
-raw.info['bads'] = [new_ch_name]
-idx = raw.ch_names.index(new_ch_name)
-# 5. Interpolate bad channels (This runs *silently* without error/warning)
-print("\nStep 5: Running raw.interpolate_bads()...")
-raw_interp = raw.copy().interpolate_bads()
-
-# 6. Check the interpolated channel data (Replication of the error)
-interp_data = raw_interp.get_data(picks=new_ch_name)[0]
-is_nan = np.isnan(interp_data).all()
-print(interp_data)
-print("\n--- Replication Result ---")
-print(f"Is the interpolated channel '{new_ch_name}' entirely NaN? {is_nan}")
-if is_nan:
-    print("✅ The bug is replicated: Interpolation failed silently, resulting in NaN data.")
-print(raw.info['chs'][idx]['loc'])
\ No newline at end of file

From 04d2f7ef5630777c8a93504de84862a7d9071207 Mon Sep 17 00:00:00 2001
From: 1himan <vanshumahor@gmail.com>
Date: Wed, 3 Dec 2025 11:40:54 +0530
Subject: [PATCH 06/25] minor changes

---
 mne/channels/channels.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mne/channels/channels.py b/mne/channels/channels.py
index 5cdaf4fefac..1fdc50fbec0 100644
--- a/mne/channels/channels.py
+++ b/mne/channels/channels.py
@@ -827,7 +827,7 @@ def interpolate_bads(
         origin="auto",
         method=None,
         exclude=(),
-        on_no_position="raise",
+        on_no_position="warn",
         verbose=None,
     ):
         """Interpolate bad MEG and EEG channels.

From db1b9934ac1c820d76f3494932bc5a14c31b3e7c Mon Sep 17 00:00:00 2001
From: 1himan <vanshumahor@gmail.com>
Date: Wed, 3 Dec 2025 12:05:41 +0530
Subject: [PATCH 07/25] Fixing CI tests

---
 mne/channels/channels.py | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/mne/channels/channels.py b/mne/channels/channels.py
index 1fdc50fbec0..f71d790bfb5 100644
--- a/mne/channels/channels.py
+++ b/mne/channels/channels.py
@@ -906,9 +906,12 @@ def interpolate_bads(
 
         if invalid_chs:
             msg = (
-                f"Bad channel(s) '{invalid_chs}' have missing valid sensor position (loc) information."
-                "\nInterpolation cannot proceed correctly. If you want to continue despite missing positions, set "
-                "on_no_position='warn' or 'ignore', which outputs all NaN values(np.nan) for the interpolated channel(s)."
+                f"Bad channel(s) {invalid_chs} have missing valid sensor position "
+                "(loc) information.\n"
+                "Interpolation cannot proceed correctly. If you want to continue "
+                "despite missing positions, set on_no_position='warn' or 'ignore', "
+                "which outputs all NaN values (np.nan) for the interpolated "
+                "channel(s)."
             )
             _on_missing(on_no_position, msg)
 

From 63f8dd509463036fc55f675765a3c333b5b39625 Mon Sep 17 00:00:00 2001
From: 1himan <vanshumahor@gmail.com>
Date: Sun, 21 Dec 2025 15:12:38 +0530
Subject: [PATCH 08/25] Validation warning while processing docstring for
 .interpolate_bads(), Parameters {on_no_position} not found - fix

---
 mne/channels/channels.py | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/mne/channels/channels.py b/mne/channels/channels.py
index f71d790bfb5..258fbcd5fd7 100644
--- a/mne/channels/channels.py
+++ b/mne/channels/channels.py
@@ -873,6 +873,9 @@ def interpolate_bads(
         exclude : list | tuple
             The channels to exclude from interpolation. If excluded a bad
             channel will stay in bads.
+        on_no_position : 'raise' | 'warn' | 'ignore'
+           Decides how to handle the case when sensor positions of input
+           channel(s) is invalid.
         %(verbose)s
 
         Returns

From c1bcbc59a66fb9982e2f68495a2db8ff39188cad Mon Sep 17 00:00:00 2001
From: 1himan <vanshumahor@gmail.com>
Date: Sun, 21 Dec 2025 15:22:18 +0530
Subject: [PATCH 09/25] Indentation fix

---
 mne/channels/channels.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/mne/channels/channels.py b/mne/channels/channels.py
index 258fbcd5fd7..8b07e615408 100644
--- a/mne/channels/channels.py
+++ b/mne/channels/channels.py
@@ -874,8 +874,8 @@ def interpolate_bads(
             The channels to exclude from interpolation. If excluded a bad
             channel will stay in bads.
         on_no_position : 'raise' | 'warn' | 'ignore'
-           Decides how to handle the case when sensor positions of input
-           channel(s) is invalid.
+            Decides how to handle the case when sensor positions of input
+            channel(s) is invalid.
         %(verbose)s
 
         Returns

From fec6daf25b84a0892e499071c6174b017513b41f Mon Sep 17 00:00:00 2001
From: 1himan <vanshumahor@gmail.com>
Date: Sun, 21 Dec 2025 15:34:30 +0530
Subject: [PATCH 10/25] CLI check fix

---
 mne/channels/channels.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mne/channels/channels.py b/mne/channels/channels.py
index 8b07e615408..89e6133cb48 100644
--- a/mne/channels/channels.py
+++ b/mne/channels/channels.py
@@ -873,7 +873,7 @@ def interpolate_bads(
         exclude : list | tuple
             The channels to exclude from interpolation. If excluded a bad
             channel will stay in bads.
-        on_no_position : 'raise' | 'warn' | 'ignore'
+        on_no_position : "raise" | "warn" | "ignore"
             Decides how to handle the case when sensor positions of input
             channel(s) is invalid.
         %(verbose)s

From d84c11fe4c96991bc2e7fa34123cbbbe5d99d7a1 Mon Sep 17 00:00:00 2001
From: 1himan <vanshumahor@gmail.com>
Date: Fri, 2 Jan 2026 19:17:44 +0530
Subject: [PATCH 11/25] this fixes the cli tests

---
 mne/channels/channels.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mne/channels/channels.py b/mne/channels/channels.py
index 89e6133cb48..0cfe86a502e 100644
--- a/mne/channels/channels.py
+++ b/mne/channels/channels.py
@@ -903,7 +903,7 @@ def interpolate_bads(
 
         invalid_chs = []
         for ch in self.info["bads"]:
-            loc = self.info["chs"][self.ch_names.index(ch)]["loc"]
+            loc = self.info["chs"][self.ch_names.index(ch)]["loc"][:3]
             if np.allclose(loc, 0.0, atol=1e-16) or np.isnan(loc).any():
                 invalid_chs.append(ch)
 

From 78ad836822aac617589f55ca9d7d0279ea705b76 Mon Sep 17 00:00:00 2001
From: 1himan <vanshumahor@gmail.com>
Date: Wed, 7 Jan 2026 12:34:35 +0530
Subject: [PATCH 12/25] Made suggested changes

---
 mne/channels/channels.py | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/mne/channels/channels.py b/mne/channels/channels.py
index ed86fa2c472..13b228218e4 100644
--- a/mne/channels/channels.py
+++ b/mne/channels/channels.py
@@ -827,7 +827,7 @@ def interpolate_bads(
         origin="auto",
         method=None,
         exclude=(),
-        on_no_position="warn",
+        on_bad_position="warn",
         verbose=None,
     ):
         """Interpolate bad MEG and EEG channels.
@@ -873,9 +873,10 @@ def interpolate_bads(
         exclude : list | tuple
             The channels to exclude from interpolation. If excluded a bad
             channel will stay in bads.
-        on_no_position : "raise" | "warn" | "ignore"
-            Decides how to handle the case when sensor positions of input
-            channel(s) is invalid.
+        on_bad_position : "raise" | "warn" | "ignore"
+            What to do when one or more sensor positions are invalid (zero or NaN).
+            If ``"warn"`` or ``"ignore"``, channels with invalid positions will be
+            filled with :data:`~numpy.nan`.
         %(verbose)s
 
         Returns
@@ -909,14 +910,13 @@ def interpolate_bads(
 
         if invalid_chs:
             msg = (
-                f"Bad channel(s) {invalid_chs} have missing valid sensor position "
-                "(loc) information.\n"
+                f"Channel(s) {invalid_chs} have invalid sensor position(s). "
                 "Interpolation cannot proceed correctly. If you want to continue "
-                "despite missing positions, set on_no_position='warn' or 'ignore', "
+                "despite missing positions, set on_bad_position='warn' or 'ignore', "
                 "which outputs all NaN values (np.nan) for the interpolated "
                 "channel(s)."
             )
-            _on_missing(on_no_position, msg)
+            _on_missing(on_bad_position, msg)
 
         method = _handle_default("interpolation_method", method)
         ch_types = self.get_channel_types(unique=True)

From 93580513a5ff737bb204396e05ffb5a29c46395f Mon Sep 17 00:00:00 2001
From: 1himan <vanshumahor@gmail.com>
Date: Wed, 7 Jan 2026 17:18:06 +0530
Subject: [PATCH 13/25] Improved tests

---
 mne/channels/tests/test_interpolation.py | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/mne/channels/tests/test_interpolation.py b/mne/channels/tests/test_interpolation.py
index de09a97c306..dcdd8f73d57 100644
--- a/mne/channels/tests/test_interpolation.py
+++ b/mne/channels/tests/test_interpolation.py
@@ -420,6 +420,30 @@ def test_nan_interpolation(raw):
     raw.interpolate_bads(method="nan", reset_bads=False)
     assert raw.info["bads"] == ch_to_interp
 
+    store = raw.info["chs"][1]["loc"]
+    # for on_bad_position="warn"
+    with pytest.warns(RuntimeWarning):
+        raw.info["bads"] = ch_to_interp
+        # delibrately set loc elements to np.nan
+        raw.info["chs"][1]["loc"] = np.full(12, np.nan)
+        raw.interpolate_bads(on_bad_position="warn")
+    assert np.isnan(raw.info["chs"][1]["loc"]).any() == True
+
+    # for on_bad_position="raise"
+    with pytest.raises(ValueError):
+        raw.info["bads"] = ch_to_interp
+        raw.info["chs"][1]["loc"] = np.full(12, np.nan)
+        raw.interpolate_bads(on_bad_position="raise")
+    assert np.isnan(raw.info["chs"][1]["loc"]).any() == True
+
+    # for on_bad_position="ignore"
+    raw.info["bads"] = ch_to_interp
+    raw.info["chs"][1]["loc"] = np.full(12, np.nan)
+    raw.interpolate_bads(on_bad_position="ignore")
+    assert np.isnan(raw.info["chs"][1]["loc"]).any() == True
+
+    raw.info["chs"][1]["loc"] = store
+
     # make sure other channels are untouched
     raw.drop_channels(ch_to_interp)
     good_chs = raw.get_data()

From 2d19ecbc674308dac0550d842fac7f458c03e9c7 Mon Sep 17 00:00:00 2001
From: 1himan <vanshumahor@gmail.com>
Date: Wed, 7 Jan 2026 20:51:07 +0530
Subject: [PATCH 14/25] Fixed linting errors

---
 mne/channels/tests/test_interpolation.py | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/mne/channels/tests/test_interpolation.py b/mne/channels/tests/test_interpolation.py
index dcdd8f73d57..299f67ce015 100644
--- a/mne/channels/tests/test_interpolation.py
+++ b/mne/channels/tests/test_interpolation.py
@@ -427,20 +427,20 @@ def test_nan_interpolation(raw):
         # delibrately set loc elements to np.nan
         raw.info["chs"][1]["loc"] = np.full(12, np.nan)
         raw.interpolate_bads(on_bad_position="warn")
-    assert np.isnan(raw.info["chs"][1]["loc"]).any() == True
+    assert np.isnan(raw.info["chs"][1]["loc"]).any()
 
     # for on_bad_position="raise"
     with pytest.raises(ValueError):
         raw.info["bads"] = ch_to_interp
         raw.info["chs"][1]["loc"] = np.full(12, np.nan)
         raw.interpolate_bads(on_bad_position="raise")
-    assert np.isnan(raw.info["chs"][1]["loc"]).any() == True
+    assert np.isnan(raw.info["chs"][1]["loc"]).any()
 
     # for on_bad_position="ignore"
     raw.info["bads"] = ch_to_interp
     raw.info["chs"][1]["loc"] = np.full(12, np.nan)
     raw.interpolate_bads(on_bad_position="ignore")
-    assert np.isnan(raw.info["chs"][1]["loc"]).any() == True
+    assert np.isnan(raw.info["chs"][1]["loc"]).any()
 
     raw.info["chs"][1]["loc"] = store
 

From 4915ff00ec5b3e34a4d8760b27adc1850ca779ca Mon Sep 17 00:00:00 2001
From: 1himan <vanshumahor@gmail.com>
Date: Thu, 8 Jan 2026 12:33:33 +0530
Subject: [PATCH 15/25] Rmoved redundancy

---
 mne/channels/tests/test_interpolation.py | 20 ++++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/mne/channels/tests/test_interpolation.py b/mne/channels/tests/test_interpolation.py
index 299f67ce015..3afbf9fd946 100644
--- a/mne/channels/tests/test_interpolation.py
+++ b/mne/channels/tests/test_interpolation.py
@@ -421,24 +421,24 @@ def test_nan_interpolation(raw):
     assert raw.info["bads"] == ch_to_interp
 
     store = raw.info["chs"][1]["loc"]
-    # for on_bad_position="warn"
-    with pytest.warns(RuntimeWarning):
-        raw.info["bads"] = ch_to_interp
-        # delibrately set loc elements to np.nan
-        raw.info["chs"][1]["loc"] = np.full(12, np.nan)
-        raw.interpolate_bads(on_bad_position="warn")
-    assert np.isnan(raw.info["chs"][1]["loc"]).any()
-
     # for on_bad_position="raise"
-    with pytest.raises(ValueError):
+    with pytest.raises(ValueError, match="have invalid sensor position"):
         raw.info["bads"] = ch_to_interp
         raw.info["chs"][1]["loc"] = np.full(12, np.nan)
+        # DOES NOT interpolates at all. So raw.info["bads"] remains as is
         raw.interpolate_bads(on_bad_position="raise")
     assert np.isnan(raw.info["chs"][1]["loc"]).any()
 
+    # for on_bad_position="warn"
+    with pytest.warns(RuntimeWarning, match="have invalid sensor position"):
+        # this DOES the interpolation BUT with a warning
+        # so raw.info["bad"] will be empty again,
+        # and interpolated channel with be all np.nan
+        raw.interpolate_bads(on_bad_position="warn")
+    assert np.isnan(raw.info["chs"][1]["loc"]).any()
+
     # for on_bad_position="ignore"
     raw.info["bads"] = ch_to_interp
-    raw.info["chs"][1]["loc"] = np.full(12, np.nan)
     raw.interpolate_bads(on_bad_position="ignore")
     assert np.isnan(raw.info["chs"][1]["loc"]).any()
 

From 68dbb2802d57019440a76584601a019108d8cfb8 Mon Sep 17 00:00:00 2001
From: 1himan <vanshumahor@gmail.com>
Date: Tue, 13 Jan 2026 12:01:29 +0530
Subject: [PATCH 16/25] Added dev entries, and fixed test logic

---
 doc/changes/dev/13518.bugfix.rst         |  1 +
 doc/changes/names.inc                    |  1 +
 mne/channels/tests/test_interpolation.py | 11 ++++-------
 3 files changed, 6 insertions(+), 7 deletions(-)
 create mode 100644 doc/changes/dev/13518.bugfix.rst

diff --git a/doc/changes/dev/13518.bugfix.rst b/doc/changes/dev/13518.bugfix.rst
new file mode 100644
index 00000000000..c98ab2d728b
--- /dev/null
+++ b/doc/changes/dev/13518.bugfix.rst
@@ -0,0 +1 @@
+Raise warning implementation in :meth:`mne.channels.InterpolationMixin.interpolate_bads` when interpolation of channels with invalid position is done, by :newcontrib:`Himanshu Mahor`_.
diff --git a/doc/changes/names.inc b/doc/changes/names.inc
index 5a5a1e98f89..6b58afd6960 100644
--- a/doc/changes/names.inc
+++ b/doc/changes/names.inc
@@ -117,6 +117,7 @@
 .. _Harrison Ritz: https://github.com/harrisonritz
 .. _Hasrat Ali Arzoo: https://github.com/hasrat17
 .. _Henrich Kolkhorst: https://github.com/hekolk
+.. _Himanshu Mahor: https://github.com/1himan
 .. _Hongjiang Ye: https://github.com/ye-hongjiang
 .. _Hubert Banville: https://github.com/hubertjb
 .. _Hyonyoung Shin: https://github.com/mcvain
diff --git a/mne/channels/tests/test_interpolation.py b/mne/channels/tests/test_interpolation.py
index 3afbf9fd946..3f7699622ce 100644
--- a/mne/channels/tests/test_interpolation.py
+++ b/mne/channels/tests/test_interpolation.py
@@ -422,12 +422,11 @@ def test_nan_interpolation(raw):
 
     store = raw.info["chs"][1]["loc"]
     # for on_bad_position="raise"
+    raw.info["bads"] = ch_to_interp
+    raw.info["chs"][1]["loc"] = np.full(12, np.nan)
     with pytest.raises(ValueError, match="have invalid sensor position"):
-        raw.info["bads"] = ch_to_interp
-        raw.info["chs"][1]["loc"] = np.full(12, np.nan)
         # DOES NOT interpolates at all. So raw.info["bads"] remains as is
         raw.interpolate_bads(on_bad_position="raise")
-    assert np.isnan(raw.info["chs"][1]["loc"]).any()
 
     # for on_bad_position="warn"
     with pytest.warns(RuntimeWarning, match="have invalid sensor position"):
@@ -435,13 +434,11 @@ def test_nan_interpolation(raw):
         # so raw.info["bad"] will be empty again,
         # and interpolated channel with be all np.nan
         raw.interpolate_bads(on_bad_position="warn")
-    assert np.isnan(raw.info["chs"][1]["loc"]).any()
 
     # for on_bad_position="ignore"
     raw.info["bads"] = ch_to_interp
-    raw.interpolate_bads(on_bad_position="ignore")
-    assert np.isnan(raw.info["chs"][1]["loc"]).any()
-
+    assert raw.interpolate_bads(on_bad_position="ignore")
+    assert np.isnan(bad_chs).all, "Interpolated channel should be all NaN"
     raw.info["chs"][1]["loc"] = store
 
     # make sure other channels are untouched

From a3f70e301c6299f64374a9f2293b82403c48f232 Mon Sep 17 00:00:00 2001
From: 1himan <vanshumahor@gmail.com>
Date: Tue, 13 Jan 2026 13:28:11 +0530
Subject: [PATCH 17/25] Fixing ci tests

---
 doc/changes/dev/13518.bugfix.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/doc/changes/dev/13518.bugfix.rst b/doc/changes/dev/13518.bugfix.rst
index c98ab2d728b..dfcbd7eee73 100644
--- a/doc/changes/dev/13518.bugfix.rst
+++ b/doc/changes/dev/13518.bugfix.rst
@@ -1 +1 @@
-Raise warning implementation in :meth:`mne.channels.InterpolationMixin.interpolate_bads` when interpolation of channels with invalid position is done, by :newcontrib:`Himanshu Mahor`_.
+Raise warning implementation in interpolate_bads() method when interpolation of channels with invalid position is done, by :newcontrib:`Himanshu Mahor`.

From 3828f824daff466e6c6ab9bad63bc55bb5ee3d7d Mon Sep 17 00:00:00 2001
From: 1himan <vanshumahor@gmail.com>
Date: Tue, 20 Jan 2026 20:14:57 +0530
Subject: [PATCH 18/25] Polish

---
 doc/changes/dev/13518.bugfix.rst | 2 +-
 mne/channels/channels.py         | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/doc/changes/dev/13518.bugfix.rst b/doc/changes/dev/13518.bugfix.rst
index dfcbd7eee73..f7d73a2cb04 100644
--- a/doc/changes/dev/13518.bugfix.rst
+++ b/doc/changes/dev/13518.bugfix.rst
@@ -1 +1 @@
-Raise warning implementation in interpolate_bads() method when interpolation of channels with invalid position is done, by :newcontrib:`Himanshu Mahor`.
+Raise warning implementation in interpolate_bads() method when interpolation of channels with invalid position is done, by `Himanshu Mahor`_.
diff --git a/mne/channels/channels.py b/mne/channels/channels.py
index 13b228218e4..4825fccd882 100644
--- a/mne/channels/channels.py
+++ b/mne/channels/channels.py
@@ -827,7 +827,7 @@ def interpolate_bads(
         origin="auto",
         method=None,
         exclude=(),
-        on_bad_position="warn",
+        on_bad_position="raise",
         verbose=None,
     ):
         """Interpolate bad MEG and EEG channels.

From c8013345338844a3246a16e76b818ef2f1284bec Mon Sep 17 00:00:00 2001
From: Himanshu Mahor <140396762+1himan@users.noreply.github.com>
Date: Mon, 23 Feb 2026 19:44:40 +0530
Subject: [PATCH 19/25] Change on_bad_position behavior from 'raise' to 'warn'

---
 mne/channels/channels.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mne/channels/channels.py b/mne/channels/channels.py
index bf09fcf3308..a7b358998d1 100644
--- a/mne/channels/channels.py
+++ b/mne/channels/channels.py
@@ -829,7 +829,7 @@ def interpolate_bads(
         origin="auto",
         method=None,
         exclude=(),
-        on_bad_position="raise",
+        on_bad_position="warn",
         verbose=None,
     ):
         """Interpolate bad MEG and EEG channels.

From 59072501449aadc9e0c379aa76e9beac59f41de5 Mon Sep 17 00:00:00 2001
From: 1himan <vanshumahor@gmail.com>
Date: Mon, 23 Feb 2026 20:03:03 +0530
Subject: [PATCH 20/25] More meaningful error and warning message to the user

---
 mne/channels/channels.py | 20 ++++++++++++--------
 1 file changed, 12 insertions(+), 8 deletions(-)

diff --git a/mne/channels/channels.py b/mne/channels/channels.py
index a7b358998d1..6f686a6df00 100644
--- a/mne/channels/channels.py
+++ b/mne/channels/channels.py
@@ -911,15 +911,19 @@ def interpolate_bads(
                 invalid_chs.append(ch)
 
         if invalid_chs:
-            msg = (
-                f"Channel(s) {invalid_chs} have invalid sensor position(s). "
-                "Interpolation cannot proceed correctly. If you want to continue "
-                "despite missing positions, set on_bad_position='warn' or 'ignore', "
-                "which outputs all NaN values (np.nan) for the interpolated "
-                "channel(s)."
+            _on_missing(
+                on_bad_position,
+                (
+                    f"Channel(s) {invalid_chs} have invalid sensor position(s). "
+                    "Interpolation cannot proceed correctly. If you want to continue "
+                    "despite missing positions, set on_bad_position='warn' or 'ignore', "
+                    "which outputs all NaN values (np.nan) for the interpolated channel(s)."
+                    if on_bad_position == "raise"
+                    else f"Channel(s) {invalid_chs} have invalid sensor position(s) and "
+                    "cannot be interpolated. The values of these channels will be all NaN. "
+                    "To ignore this warning, pass on_bad_position='ignore'."
+                ),
             )
-            _on_missing(on_bad_position, msg)
-
         method = _handle_default("interpolation_method", method)
         ch_types = self.get_channel_types(unique=True)
         # figure out if we have "mag" for "meg", "hbo" for "fnirs", ... to filter the

From 590861c8c1a96aaff696acacc4222ab4508bec06 Mon Sep 17 00:00:00 2001
From: 1himan <vanshumahor@gmail.com>
Date: Mon, 23 Feb 2026 20:15:02 +0530
Subject: [PATCH 21/25] fixed ruff error

---
 mne/channels/channels.py | 20 +++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/mne/channels/channels.py b/mne/channels/channels.py
index 6f686a6df00..d7c062e8bc3 100644
--- a/mne/channels/channels.py
+++ b/mne/channels/channels.py
@@ -914,14 +914,20 @@ def interpolate_bads(
             _on_missing(
                 on_bad_position,
                 (
-                    f"Channel(s) {invalid_chs} have invalid sensor position(s). "
-                    "Interpolation cannot proceed correctly. If you want to continue "
-                    "despite missing positions, set on_bad_position='warn' or 'ignore', "
-                    "which outputs all NaN values (np.nan) for the interpolated channel(s)."
+                    (
+                        f"Channel(s) {invalid_chs} have invalid sensor position(s). "
+                        "Interpolation cannot proceed correctly. If you want to "
+                        "continue despite missing positions, set "
+                        "on_bad_position='warn' or 'ignore', which outputs all "
+                        "NaN values (np.nan) for the interpolated channel(s)."
+                    )
                     if on_bad_position == "raise"
-                    else f"Channel(s) {invalid_chs} have invalid sensor position(s) and "
-                    "cannot be interpolated. The values of these channels will be all NaN. "
-                    "To ignore this warning, pass on_bad_position='ignore'."
+                    else (
+                        f"Channel(s) {invalid_chs} have invalid sensor position(s) "
+                        "and cannot be interpolated. The values of these channels "
+                        "will be all NaN. To ignore this warning, pass "
+                        "on_bad_position='ignore'."
+                    )
                 ),
             )
         method = _handle_default("interpolation_method", method)

From a2ab8c9b26e5b5a5e0eabeb384c9ea8303e0c536 Mon Sep 17 00:00:00 2001
From: 1himan <vanshumahor@gmail.com>
Date: Wed, 25 Feb 2026 15:11:30 +0530
Subject: [PATCH 22/25] Adding final suggestions

---
 doc/changes/dev/13518.bugfix.rst |  2 +-
 mne/channels/channels.py         | 39 ++++++++++++++++----------------
 2 files changed, 20 insertions(+), 21 deletions(-)

diff --git a/doc/changes/dev/13518.bugfix.rst b/doc/changes/dev/13518.bugfix.rst
index f7d73a2cb04..7b74ebb4453 100644
--- a/doc/changes/dev/13518.bugfix.rst
+++ b/doc/changes/dev/13518.bugfix.rst
@@ -1 +1 @@
-Raise warning implementation in interpolate_bads() method when interpolation of channels with invalid position is done, by `Himanshu Mahor`_.
+Make :meth:`~mne.io.Raw.interpolate_bads` method flexible (ignore, warn, raise) about how to handle interpolation of channels with invalid positions, by `Himanshu Mahor`_.
diff --git a/mne/channels/channels.py b/mne/channels/channels.py
index d7c062e8bc3..a90c200fa8f 100644
--- a/mne/channels/channels.py
+++ b/mne/channels/channels.py
@@ -904,32 +904,31 @@ def interpolate_bads(
         _check_preload(self, "interpolation")
         _validate_type(method, (dict, str, None), "method")
 
+        # check for channels with invalid position(s)
         invalid_chs = []
         for ch in self.info["bads"]:
             loc = self.info["chs"][self.ch_names.index(ch)]["loc"][:3]
-            if np.allclose(loc, 0.0, atol=1e-16) or np.isnan(loc).any():
+            if np.allclose(loc, 0.0, rtol=0, atol=1e-16) or np.isnan(loc).any():
                 invalid_chs.append(ch)
 
         if invalid_chs:
-            _on_missing(
-                on_bad_position,
-                (
-                    (
-                        f"Channel(s) {invalid_chs} have invalid sensor position(s). "
-                        "Interpolation cannot proceed correctly. If you want to "
-                        "continue despite missing positions, set "
-                        "on_bad_position='warn' or 'ignore', which outputs all "
-                        "NaN values (np.nan) for the interpolated channel(s)."
-                    )
-                    if on_bad_position == "raise"
-                    else (
-                        f"Channel(s) {invalid_chs} have invalid sensor position(s) "
-                        "and cannot be interpolated. The values of these channels "
-                        "will be all NaN. To ignore this warning, pass "
-                        "on_bad_position='ignore'."
-                    )
-                ),
-            )
+            if on_bad_position == "raise":
+                msg = (
+                    f"Channel(s) {invalid_chs} have invalid sensor position(s). "
+                    "Interpolation cannot proceed correctly. If you want to "
+                    "continue despite missing positions, set "
+                    "on_bad_position='warn' or 'ignore', which outputs all "
+                    "NaN values (np.nan) for the interpolated channel(s)."
+                )
+            else:
+                msg = (
+                    f"Channel(s) {invalid_chs} have invalid sensor position(s) "
+                    "and cannot be interpolated. The values of these channels "
+                    "will be all NaN. To ignore this warning, pass "
+                    "on_bad_position='ignore'."
+                )
+            _on_missing(on_bad_position, msg)
+
         method = _handle_default("interpolation_method", method)
         ch_types = self.get_channel_types(unique=True)
         # figure out if we have "mag" for "meg", "hbo" for "fnirs", ... to filter the

From 9512936739f1242e6b478133aaf58e99a4f6386f Mon Sep 17 00:00:00 2001
From: 1himan <vanshumahor@gmail.com>
Date: Thu, 12 Mar 2026 18:13:32 +0530
Subject: [PATCH 23/25] Adding version:1.12

---
 mne/channels/channels.py |   2 +
 mne/report/report.py     | 150 ++++++++++++++++++++++++++++++++++++++-
 2 files changed, 149 insertions(+), 3 deletions(-)

diff --git a/mne/channels/channels.py b/mne/channels/channels.py
index 427e9e4f2e6..fbfb759cf92 100644
--- a/mne/channels/channels.py
+++ b/mne/channels/channels.py
@@ -879,6 +879,8 @@ def interpolate_bads(
             What to do when one or more sensor positions are invalid (zero or NaN).
             If ``"warn"`` or ``"ignore"``, channels with invalid positions will be
             filled with :data:`~numpy.nan`.
+
+            .. versionadded:: 1.12
         %(verbose)s
 
         Returns
diff --git a/mne/report/report.py b/mne/report/report.py
index 071d15e3cee..8edeb82e26d 100644
--- a/mne/report/report.py
+++ b/mne/report/report.py
@@ -40,7 +40,7 @@
 from ..minimum_norm import InverseOperator, read_inverse_operator
 from ..parallel import parallel_func
 from ..preprocessing.ica import read_ica
-from ..proj import read_proj
+from ..proj import read_proj, sensitivity_map
 from ..source_estimate import SourceEstimate, read_source_estimate
 from ..source_space._source_space import _ensure_src
 from ..surface import dig_mri_distances
@@ -1546,6 +1546,7 @@ def add_forward(
         subject=None,
         subjects_dir=None,
         plot=False,
+        sensitivity=False,
         tags=("forward-solution",),
         section=None,
         replace=False,
@@ -1567,6 +1568,14 @@ def add_forward(
             If True, plot the source space of the forward solution.
 
             .. versionadded:: 1.10
+        sensitivity : bool | list of str
+            If True, compute and plot sensitivity maps for all available
+            channel types (MEG gradiometers, MEG magnetometers, and EEG).
+            If a list, compute sensitivity maps for only the specified
+            channel types (e.g., ``['grad', 'mag']``).
+            Valid channel types are ``'grad'``, ``'mag'``, and ``'eeg'``.
+
+            .. versionadded:: 1.12
         %(tags_report)s
         %(section_report)s
 
@@ -1589,6 +1598,7 @@ def add_forward(
             tags=tags,
             replace=replace,
             plot=plot,
+            sensitivity=sensitivity,
         )
 
     @fill_doc
@@ -3616,6 +3626,7 @@ def _add_forward(
         title,
         image_format,
         plot,
+        sensitivity,
         section,
         tags,
         replace,
@@ -3626,10 +3637,143 @@ def _add_forward(
 
         subject = self.subject if subject is None else subject
         subject = forward["src"][0]["subject_his_id"] if subject is None else subject
+        subjects_dir = self.subjects_dir if subjects_dir is None else subjects_dir
 
-        # XXX Todo
-        # Render sensitivity maps
         sensitivity_maps_html = ""
+        if sensitivity:
+            if subjects_dir is None:
+                raise ValueError(
+                    "subjects_dir must be provided to compute sensitivity maps"
+                )
+
+            info = forward["info"]
+            meg_info = info.get("meg", False)
+            has_grad = meg_info and (
+                isinstance(meg_info, dict)
+                and meg_info.get("grad", False)
+                or meg_info is True
+            )
+            has_mag = meg_info and (
+                isinstance(meg_info, dict)
+                and meg_info.get("mag", False)
+                or meg_info is True
+            )
+            has_eeg = info.get("eeg", False)
+
+            all_ch_types = []
+            if has_grad:
+                all_ch_types.append("grad")
+            if has_mag:
+                all_ch_types.append("mag")
+            if has_eeg:
+                all_ch_types.append("eeg")
+
+            if not all_ch_types:
+                raise ValueError(
+                    "No MEG or EEG channels found in forward solution. "
+                    "Cannot compute sensitivity maps."
+                )
+
+            if sensitivity is True:
+                ch_types = all_ch_types
+            else:
+                ch_types = list(sensitivity)
+                for ch_type in ch_types:
+                    _check_option("ch_type", ch_type, ["grad", "mag", "eeg"])
+                    if ch_type not in all_ch_types:
+                        raise ValueError(
+                            f"Channel type '{ch_type}' not found in forward solution. "
+                            f"Available types are: {all_ch_types}"
+                        )
+
+            html_parts = []
+            for ch_type in ch_types:
+                _check_option("ch_type", ch_type, ["grad", "mag", "eeg"])
+
+            html_parts = []
+            for ch_type in ch_types:
+                stc = sensitivity_map(forward, ch_type=ch_type, mode="fixed")
+
+                stc_plot_kwargs = _handle_default("report_stc_plot_kwargs", dict())
+                stc_plot_kwargs.update(
+                    subject=subject,
+                    subjects_dir=subjects_dir,
+                    clim=dict(kind="value", lims=[0, 50, 100]),
+                    colorbar=True,
+                )
+
+                import matplotlib.pyplot as plt
+
+                if get_3d_backend() is not None:
+                    brain = stc.plot(**stc_plot_kwargs)
+                    brain._renderer.plotter.subplot(0, 0)
+                    fig, ax = plt.subplots(figsize=(4.5, 4.5), layout="constrained")
+                    ax.imshow(brain.screenshot(time_viewer=False, mode="rgb"))
+                    ax.axis("off")
+                    _constrain_fig_resolution(
+                        fig,
+                        max_width=stc_plot_kwargs.get("size", (800, 600))[0],
+                        max_res=self.img_max_res,
+                    )
+                    plt.close(fig)
+                    brain.close()
+                else:
+                    fig_lh = plt.figure(layout="constrained")
+                    fig_rh = plt.figure(layout="constrained")
+                    brain_lh = stc.plot(
+                        views="lat",
+                        hemi="lh",
+                        initial_time=stc.times[0],
+                        backend="matplotlib",
+                        subject=subject,
+                        subjects_dir=subjects_dir,
+                        figure=fig_lh,
+                        **stc_plot_kwargs,
+                    )
+                    brain_rh = stc.plot(
+                        views="lat",
+                        hemi="rh",
+                        initial_time=stc.times[0],
+                        subject=subject,
+                        subjects_dir=subjects_dir,
+                        backend="matplotlib",
+                        figure=fig_rh,
+                        **stc_plot_kwargs,
+                    )
+                    _constrain_fig_resolution(
+                        fig_lh,
+                        max_width=stc_plot_kwargs.get("size", (800, 600))[0],
+                        max_res=self.img_max_res,
+                    )
+                    _constrain_fig_resolution(
+                        fig_rh,
+                        max_width=stc_plot_kwargs.get("size", (800, 600))[0],
+                        max_res=self.img_max_res,
+                    )
+                    fig = fig_lh
+                    plt.close(fig_rh)
+                    brain_lh.close()
+                    brain_rh.close()
+
+                img = self._fig_to_img(fig=fig, image_format=image_format)
+                plt.close(fig)
+
+                img_id = f"forward-sensitivity-{ch_type}"
+                img_html = _html_image_element(
+                    id_=img_id,
+                    img=img,
+                    image_format=image_format,
+                    caption=f"Sensitivity map ({ch_type})",
+                    show=True,
+                    div_klass="forward-sensitivity-map",
+                    img_klass="forward-sensitivity-map",
+                    title=f"Sensitivity Map - {ch_type.upper()}",
+                    tags=(),
+                )
+                html_parts.append(img_html)
+
+            sensitivity_maps_html = "\n".join(html_parts)
+
         source_space_html = ""
         if plot:
             source_space_html = self._src_html(

From 7a79dd1e87f8500048c9908fb3c93402e5487fd2 Mon Sep 17 00:00:00 2001
From: 1himan <vanshumahor@gmail.com>
Date: Thu, 12 Mar 2026 20:25:05 +0530
Subject: [PATCH 24/25] Reverting changes

---
 doc/changes/dev/13518.bugfix.rst |   1 -
 mne/report/report.py             | 150 +------------------------------
 2 files changed, 3 insertions(+), 148 deletions(-)
 delete mode 100644 doc/changes/dev/13518.bugfix.rst

diff --git a/doc/changes/dev/13518.bugfix.rst b/doc/changes/dev/13518.bugfix.rst
deleted file mode 100644
index 7b74ebb4453..00000000000
--- a/doc/changes/dev/13518.bugfix.rst
+++ /dev/null
@@ -1 +0,0 @@
-Make :meth:`~mne.io.Raw.interpolate_bads` method flexible (ignore, warn, raise) about how to handle interpolation of channels with invalid positions, by `Himanshu Mahor`_.
diff --git a/mne/report/report.py b/mne/report/report.py
index 8edeb82e26d..071d15e3cee 100644
--- a/mne/report/report.py
+++ b/mne/report/report.py
@@ -40,7 +40,7 @@
 from ..minimum_norm import InverseOperator, read_inverse_operator
 from ..parallel import parallel_func
 from ..preprocessing.ica import read_ica
-from ..proj import read_proj, sensitivity_map
+from ..proj import read_proj
 from ..source_estimate import SourceEstimate, read_source_estimate
 from ..source_space._source_space import _ensure_src
 from ..surface import dig_mri_distances
@@ -1546,7 +1546,6 @@ def add_forward(
         subject=None,
         subjects_dir=None,
         plot=False,
-        sensitivity=False,
         tags=("forward-solution",),
         section=None,
         replace=False,
@@ -1568,14 +1567,6 @@ def add_forward(
             If True, plot the source space of the forward solution.
 
             .. versionadded:: 1.10
-        sensitivity : bool | list of str
-            If True, compute and plot sensitivity maps for all available
-            channel types (MEG gradiometers, MEG magnetometers, and EEG).
-            If a list, compute sensitivity maps for only the specified
-            channel types (e.g., ``['grad', 'mag']``).
-            Valid channel types are ``'grad'``, ``'mag'``, and ``'eeg'``.
-
-            .. versionadded:: 1.12
         %(tags_report)s
         %(section_report)s
 
@@ -1598,7 +1589,6 @@ def add_forward(
             tags=tags,
             replace=replace,
             plot=plot,
-            sensitivity=sensitivity,
         )
 
     @fill_doc
@@ -3626,7 +3616,6 @@ def _add_forward(
         title,
         image_format,
         plot,
-        sensitivity,
         section,
         tags,
         replace,
@@ -3637,143 +3626,10 @@ def _add_forward(
 
         subject = self.subject if subject is None else subject
         subject = forward["src"][0]["subject_his_id"] if subject is None else subject
-        subjects_dir = self.subjects_dir if subjects_dir is None else subjects_dir
 
+        # XXX Todo
+        # Render sensitivity maps
         sensitivity_maps_html = ""
-        if sensitivity:
-            if subjects_dir is None:
-                raise ValueError(
-                    "subjects_dir must be provided to compute sensitivity maps"
-                )
-
-            info = forward["info"]
-            meg_info = info.get("meg", False)
-            has_grad = meg_info and (
-                isinstance(meg_info, dict)
-                and meg_info.get("grad", False)
-                or meg_info is True
-            )
-            has_mag = meg_info and (
-                isinstance(meg_info, dict)
-                and meg_info.get("mag", False)
-                or meg_info is True
-            )
-            has_eeg = info.get("eeg", False)
-
-            all_ch_types = []
-            if has_grad:
-                all_ch_types.append("grad")
-            if has_mag:
-                all_ch_types.append("mag")
-            if has_eeg:
-                all_ch_types.append("eeg")
-
-            if not all_ch_types:
-                raise ValueError(
-                    "No MEG or EEG channels found in forward solution. "
-                    "Cannot compute sensitivity maps."
-                )
-
-            if sensitivity is True:
-                ch_types = all_ch_types
-            else:
-                ch_types = list(sensitivity)
-                for ch_type in ch_types:
-                    _check_option("ch_type", ch_type, ["grad", "mag", "eeg"])
-                    if ch_type not in all_ch_types:
-                        raise ValueError(
-                            f"Channel type '{ch_type}' not found in forward solution. "
-                            f"Available types are: {all_ch_types}"
-                        )
-
-            html_parts = []
-            for ch_type in ch_types:
-                _check_option("ch_type", ch_type, ["grad", "mag", "eeg"])
-
-            html_parts = []
-            for ch_type in ch_types:
-                stc = sensitivity_map(forward, ch_type=ch_type, mode="fixed")
-
-                stc_plot_kwargs = _handle_default("report_stc_plot_kwargs", dict())
-                stc_plot_kwargs.update(
-                    subject=subject,
-                    subjects_dir=subjects_dir,
-                    clim=dict(kind="value", lims=[0, 50, 100]),
-                    colorbar=True,
-                )
-
-                import matplotlib.pyplot as plt
-
-                if get_3d_backend() is not None:
-                    brain = stc.plot(**stc_plot_kwargs)
-                    brain._renderer.plotter.subplot(0, 0)
-                    fig, ax = plt.subplots(figsize=(4.5, 4.5), layout="constrained")
-                    ax.imshow(brain.screenshot(time_viewer=False, mode="rgb"))
-                    ax.axis("off")
-                    _constrain_fig_resolution(
-                        fig,
-                        max_width=stc_plot_kwargs.get("size", (800, 600))[0],
-                        max_res=self.img_max_res,
-                    )
-                    plt.close(fig)
-                    brain.close()
-                else:
-                    fig_lh = plt.figure(layout="constrained")
-                    fig_rh = plt.figure(layout="constrained")
-                    brain_lh = stc.plot(
-                        views="lat",
-                        hemi="lh",
-                        initial_time=stc.times[0],
-                        backend="matplotlib",
-                        subject=subject,
-                        subjects_dir=subjects_dir,
-                        figure=fig_lh,
-                        **stc_plot_kwargs,
-                    )
-                    brain_rh = stc.plot(
-                        views="lat",
-                        hemi="rh",
-                        initial_time=stc.times[0],
-                        subject=subject,
-                        subjects_dir=subjects_dir,
-                        backend="matplotlib",
-                        figure=fig_rh,
-                        **stc_plot_kwargs,
-                    )
-                    _constrain_fig_resolution(
-                        fig_lh,
-                        max_width=stc_plot_kwargs.get("size", (800, 600))[0],
-                        max_res=self.img_max_res,
-                    )
-                    _constrain_fig_resolution(
-                        fig_rh,
-                        max_width=stc_plot_kwargs.get("size", (800, 600))[0],
-                        max_res=self.img_max_res,
-                    )
-                    fig = fig_lh
-                    plt.close(fig_rh)
-                    brain_lh.close()
-                    brain_rh.close()
-
-                img = self._fig_to_img(fig=fig, image_format=image_format)
-                plt.close(fig)
-
-                img_id = f"forward-sensitivity-{ch_type}"
-                img_html = _html_image_element(
-                    id_=img_id,
-                    img=img,
-                    image_format=image_format,
-                    caption=f"Sensitivity map ({ch_type})",
-                    show=True,
-                    div_klass="forward-sensitivity-map",
-                    img_klass="forward-sensitivity-map",
-                    title=f"Sensitivity Map - {ch_type.upper()}",
-                    tags=(),
-                )
-                html_parts.append(img_html)
-
-            sensitivity_maps_html = "\n".join(html_parts)
-
         source_space_html = ""
         if plot:
             source_space_html = self._src_html(

From 72aa5de4be9875da36ae74c9c537464cf48e28bd Mon Sep 17 00:00:00 2001
From: 1himan <vanshumahor@gmail.com>
Date: Thu, 12 Mar 2026 20:28:08 +0530
Subject: [PATCH 25/25] Reverting changes

---
 doc/changes/dev/13518.bugfix.rst | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 doc/changes/dev/13518.bugfix.rst

diff --git a/doc/changes/dev/13518.bugfix.rst b/doc/changes/dev/13518.bugfix.rst
new file mode 100644
index 00000000000..7b74ebb4453
--- /dev/null
+++ b/doc/changes/dev/13518.bugfix.rst
@@ -0,0 +1 @@
+Make :meth:`~mne.io.Raw.interpolate_bads` method flexible (ignore, warn, raise) about how to handle interpolation of channels with invalid positions, by `Himanshu Mahor`_.
