internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: mne-tools/mne-python

Issue:
Inconsistency in behavior between concatenate_raws() and concatenate_epochs()
I just ran into an issue because I blindly assumed `concatenate_epochs()` would modify the first element in-place, just like `concatenate_raws()` does. Turns out, this is not the case.

The docstring of the `Returns` portion says:

> The result of the concatenation (first Epochs instance passed in).

The part in the parentheses is misleading.

## Proposed fix

Since we'll probably not find a consensus to change the API, I'd propose to change the docstring of `concatenate_epochs()`:

- The `Return` bit should drop the `(first Epochs instance passed in)` part.
- A `Note` should be added, clearly informing users of the behavior difference between `concatenate_epochs()` and `concatenate_raws()`

Thoughts?


Discussion:
+1 to update the doc with maybe a " .. note:: " to make it obvious?

>


Resolving patch:
diff --git a/mne/epochs.py b/mne/epochs.py
--- a/mne/epochs.py
+++ b/mne/epochs.py
@@ -3514,12 +3514,15 @@ def _finish_concat(info, data, events, event_id, tmin, tmax, metadata,
 @verbose
 def concatenate_epochs(epochs_list, add_offset=True, *, on_mismatch='raise',
                        verbose=None):
-    """Concatenate a list of epochs into one epochs object.
+    """Concatenate a list of `~mne.Epochs` into one `~mne.Epochs` object.
+
+    .. note:: Unlike `~mne.concatenate_raws`, this function does **not**
+              modify any of the input data.
 
     Parameters
     ----------
     epochs_list : list
-        List of Epochs instances to concatenate (in order).
+        List of `~mne.Epochs` instances to concatenate (in that order).
     add_offset : bool
         If True, a fixed offset is added to the event times from different
         Epochs sets, such that they are easy to distinguish after the
@@ -3533,7 +3536,7 @@ def concatenate_epochs(epochs_list, add_offset=True, *, on_mismatch='raise',
     Returns
     -------
     epochs : instance of Epochs
-        The result of the concatenation (first Epochs instance passed in).
+        The result of the concatenation.
 
     Notes
     -----
diff --git a/mne/io/base.py b/mne/io/base.py
--- a/mne/io/base.py
+++ b/mne/io/base.py
@@ -2490,7 +2490,7 @@ def _check_raw_compatibility(raw):
 @verbose
 def concatenate_raws(raws, preload=None, events_list=None, *,
                      on_mismatch='raise', verbose=None):
-    """Concatenate raw instances as if they were continuous.
+    """Concatenate `~mne.io.Raw` instances as if they were continuous.
 
     .. note:: ``raws[0]`` is modified in-place to achieve the concatenation.
               Boundaries of the raw files are annotated bad. If you wish to use


Test patch:
Repository: mne-tools/mne-python

Issue:
Inconsistency in behavior between concatenate_raws() and concatenate_epochs()
I just ran into an issue because I blindly assumed `concatenate_epochs()` would modify the first element in-place, just like `concatenate_raws()` does. Turns out, this is not the case.

The docstring of the `Returns` portion says:

> The result of the concatenation (first Epochs instance passed in).

The part in the parentheses is misleading.

## Proposed fix

Since we'll probably not find a consensus to change the API, I'd propose to change the docstring of `concatenate_epochs()`:

- The `Return` bit should drop the `(first Epochs instance passed in)` part.
- A `Note` should be added, clearly informing users of the behavior difference between `concatenate_epochs()` and `concatenate_raws()`

Thoughts?


Discussion:
+1 to update the doc with maybe a " .. note:: " to make it obvious?

>


Resolving patch:
diff --git a/mne/epochs.py b/mne/epochs.py
--- a/mne/epochs.py
+++ b/mne/epochs.py
@@ -3490,12 +3490,15 @@ def _finish_concat(info, data, events, event_id, tmin, tmax, metadata,
 @verbose
 def concatenate_epochs(epochs_list, add_offset=True, *, on_mismatch='raise',
                        verbose=None):
-    """Concatenate a list of epochs into one epochs object.
+    """Concatenate a list of `~mne.Epochs` into one `~mne.Epochs` object.
+
+    .. note:: Unlike `~mne.concatenate_raws`, this function does **not**
+              modify any of the input data.
 
     Parameters
     ----------
     epochs_list : list
-        List of Epochs instances to concatenate (in order).
+        List of `~mne.Epochs` instances to concatenate (in that order).
     add_offset : bool
         If True, a fixed offset is added to the event times from different
         Epochs sets, such that they are easy to distinguish after the
@@ -3509,7 +3512,7 @@ def concatenate_epochs(epochs_list, add_offset=True, *, on_mismatch='raise',
     Returns
     -------
     epochs : instance of Epochs
-        The result of the concatenation (first Epochs instance passed in).
+        The result of the concatenation.
 
     Notes
     -----
diff --git a/mne/io/base.py b/mne/io/base.py
--- a/mne/io/base.py
+++ b/mne/io/base.py
@@ -2490,7 +2490,7 @@ def _check_raw_compatibility(raw):
 @verbose
 def concatenate_raws(raws, preload=None, events_list=None, *,
                      on_mismatch='raise', verbose=None):
-    """Concatenate raw instances as if they were continuous.
+    """Concatenate `~mne.io.Raw` instances as if they were continuous.
 
     .. note:: ``raws[0]`` is modified in-place to achieve the concatenation.
               Boundaries of the raw files are annotated bad. If you wish to use


Test patch:
Repository: mne-tools/mne-python

Issue:
CSP.fit() requires y to work, however the parameter is optional in fit_transform()
Reported on the forum:

https://mne.discourse.group/t/can-not-do-csp-fit-transform-without-label/4072

Calling `CSP.fit_transform()` without `y` (which is alright according to the API, which defaults `y=None`) yields the following exception:

```python
Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "/Users/long/anaconda/envs/3.6/lib/python3.6/site-packages/mne/decoding/mixin.py", line 30, in fit_transform
    return self.fit(X, **fit_params).transform(X)
TypeError: fit() missing 1 required positional argument: 'y'
```

This is because the `fit_transform()` method inherited from `TransformerMixin` is not compatible with the `fit` method implemented in `CSP`.

Solution is to give `CSP` its very own `fit_transform` method that doesn't make `y` an optional parameter.


Discussion:
I think our typical solution is just to put y=None in the fit method, then never use it
Since CSP is supervised, it cannot work without `y`.

I'll propose a fix shortly.

Resolving patch:
diff --git a/mne/decoding/csp.py b/mne/decoding/csp.py
--- a/mne/decoding/csp.py
+++ b/mne/decoding/csp.py
@@ -15,7 +15,7 @@
 from .mixin import TransformerMixin
 from ..cov import _regularized_covariance
 from ..fixes import pinv
-from ..utils import fill_doc, _check_option, _validate_type
+from ..utils import fill_doc, _check_option, _validate_type, copy_doc
 
 
 @fill_doc
@@ -231,6 +231,10 @@ def transform(self, X):
                 X /= self.std_
         return X
 
+    @copy_doc(TransformerMixin.fit_transform)
+    def fit_transform(self, X, y, **fit_params):  # noqa: D102
+        return super().fit_transform(X, y=y, **fit_params)
+
     @fill_doc
     def plot_patterns(self, info, components=None, ch_type=None,
                       vmin=None, vmax=None, cmap='RdBu_r', sensors=True,
diff --git a/mne/decoding/mixin.py b/mne/decoding/mixin.py
--- a/mne/decoding/mixin.py
+++ b/mne/decoding/mixin.py
@@ -6,17 +6,17 @@ class TransformerMixin(object):
     def fit_transform(self, X, y=None, **fit_params):
         """Fit to data, then transform it.
 
-        Fits transformer to X and y with optional parameters fit_params
-        and returns a transformed version of X.
+        Fits transformer to ``X`` and ``y`` with optional parameters
+        ``fit_params``, and returns a transformed version of ``X``.
 
         Parameters
         ----------
         X : array, shape (n_samples, n_features)
             Training set.
         y : array, shape (n_samples,)
-            Target values.
+            Target values or class labels.
         **fit_params : dict
-            Additional fitting parameters passed to ``self.fit``.
+            Additional fitting parameters passed to the ``fit`` method..
 
         Returns
         -------


Test patch:
Repository: mne-tools/mne-python

Issue:
Raw.save logs too many `"Overwriting existing file."` infos
MWE: 

```python
# %%
import os
from pathlib import Path
import mne
import numpy as np


sample_dir = Path(mne.datasets.sample.data_path())
sample_fname = sample_dir / 'MEG' / 'sample' / 'sample_audvis_raw.fif'
raw = mne.io.read_raw_fif(sample_fname, preload=True)

fname = Path(os.path.expanduser("~")) / "Desktop" / "try-raw.fif.gz"
raw.save(fname)
raw.save(fname, overwrite=True)

```

Output after second `.save` call:

```
Overwriting existing file.
Overwriting existing file.
Overwriting existing file.
Writing /home/stefanappelhoff/Desktop/try-raw.fif.gz
Closing /home/stefanappelhoff/Desktop/try-raw.fif.gz
[done]
```

These are two `Overwriting existing file.` too many, aren't they?


Discussion:
Comes from two calls in `.save`:

https://github.com/mne-tools/mne-python/blob/9dff61616bfc9ca411df578a4f3b963de8ac023c/mne/io/base.py#L1430

https://github.com/mne-tools/mne-python/blob/9dff61616bfc9ca411df578a4f3b963de8ac023c/mne/io/base.py#L1458

And then one additional one in `_write_raw`:

https://github.com/mne-tools/mne-python/blob/9dff61616bfc9ca411df578a4f3b963de8ac023c/mne/io/base.py#L2168


potentially an accident from #9613 @hoechenberger ?

Resolving patch:
diff --git a/mne/io/base.py b/mne/io/base.py
--- a/mne/io/base.py
+++ b/mne/io/base.py
@@ -1427,7 +1427,7 @@ def save(self, fname, picks=None, tmin=0, tmax=None, buffer_size_sec=None,
         endings_err = ('.fif', '.fif.gz')
 
         # convert to str, check for overwrite a few lines later
-        fname = _check_fname(fname, overwrite=True)
+        fname = _check_fname(fname, overwrite=True, verbose="error")
         check_fname(fname, 'raw', endings, endings_err=endings_err)
 
         split_size = _get_split_size(split_size)
@@ -1455,7 +1455,8 @@ def save(self, fname, picks=None, tmin=0, tmax=None, buffer_size_sec=None,
                              '"double", not "short"')
 
         # check for file existence and expand `~` if present
-        fname = _check_fname(fname=fname, overwrite=overwrite)
+        fname = _check_fname(fname=fname, overwrite=overwrite,
+                             verbose="error")
 
         if proj:
             info = deepcopy(self.info)
diff --git a/mne/utils/check.py b/mne/utils/check.py
--- a/mne/utils/check.py
+++ b/mne/utils/check.py
@@ -18,7 +18,7 @@
 import numpy as np
 
 from ..fixes import _median_complex, _compare_version
-from ._logging import warn, logger
+from ._logging import warn, logger, verbose
 
 
 def _ensure_int(x, name='unknown', must_be='an int'):
@@ -147,8 +147,9 @@ def _check_event_id(event_id, events):
     return event_id
 
 
+@verbose
 def _check_fname(fname, overwrite=False, must_exist=False, name='File',
-                 need_dir=False):
+                 need_dir=False, *, verbose=None):
     """Check for file existence, and return string of its absolute path."""
     _validate_type(fname, 'path-like', name)
     fname = str(


Test patch:
Repository: mne-tools/mne-python

Issue:
VTK version with python 3.9 and windows
I have set up a new venv on a different windows laptop for MNE and I wanted to move from Python 3.8.10 to 3.9.9. 
When doing `py -m pip install -r requirements.txt`, the installation fails because there are no wheels on Pypi for `vtk<=9.0.1` for windows/Python 3.9.
I installed version 9.1.0 instead; and for now, at least, I didn't notice any issues with MNE. I couldn't run yet the test suite as my battery died.. but if you have some tests in mind to make sure version 9.1.0 works fine; I can run them tomorrow. 

Maybe the requirement `vtk<=9.0.1; platform_system == "Windows"` is outdated?



Discussion:
+1 for a quick PR to make this change and see if CIs come back happy. It's probably there because CIs are problematic. Did you look at `git blame`?

https://github.com/mne-tools/mne-python/blame/main/requirements.txt

Looks like it came from a PR to fix Mayavi: https://github.com/mne-tools/mne-python/pull/9512

So I'm at least a bit optimistic that we can remove this limitation now that we don't use mayavi...

Resolving patch:
diff --git a/mne/viz/backends/renderer.py b/mne/viz/backends/renderer.py
--- a/mne/viz/backends/renderer.py
+++ b/mne/viz/backends/renderer.py
@@ -270,7 +270,7 @@ def set_3d_title(figure, title, size=40):
 
 
 def create_3d_figure(size, bgcolor=(0, 0, 0), smooth_shading=True,
-                     handle=None, scene=True):
+                     handle=None, scene=True, *, show=False):
     """Return an empty figure based on the current 3d backend.
 
     .. warning:: Proceed with caution when the renderer object is
@@ -291,6 +291,10 @@ def create_3d_figure(size, bgcolor=(0, 0, 0), smooth_shading=True,
     scene : bool
         Specify if the returned object is the scene. If False,
         the renderer object is returned. Defaults to True.
+    show : bool
+        If True, show the renderer immediately.
+
+        .. versionadded:: 1.0
 
     Returns
     -------
@@ -303,6 +307,7 @@ def create_3d_figure(size, bgcolor=(0, 0, 0), smooth_shading=True,
         size=size,
         bgcolor=bgcolor,
         smooth_shading=smooth_shading,
+        show=show,
     )
     if scene:
         return renderer.scene()


Test patch:
diff --git a/mne/viz/backends/tests/test_renderer.py b/mne/viz/backends/tests/test_renderer.py
--- a/mne/viz/backends/tests/test_renderer.py
+++ b/mne/viz/backends/tests/test_renderer.py
@@ -178,7 +178,7 @@ def test_renderer(renderer, monkeypatch):
     """Test that renderers are available on demand."""
     backend = renderer.get_3d_backend()
     cmd = [sys.executable, '-uc',
-           'import mne; mne.viz.create_3d_figure((800, 600)); '
+           'import mne; mne.viz.create_3d_figure((800, 600), show=True); '
            'backend = mne.viz.get_3d_backend(); '
            'assert backend == %r, backend' % (backend,)]
     monkeypatch.setenv('MNE_3D_BACKEND', backend)
Repository: mne-tools/mne-python

Issue:
ignore warning via nilearn (py3.10)
ignores a deprecation warning coming courtesy of nilearn.


Discussion:
upstream report: https://github.com/nilearn/nilearn/issues/3108

Resolving patch:
diff --git a/mne/conftest.py b/mne/conftest.py
--- a/mne/conftest.py
+++ b/mne/conftest.py
@@ -126,6 +126,7 @@ def pytest_configure(config):
     ignore:.*Found the following unknown channel type.*:RuntimeWarning
     ignore:.*np\.MachAr.*:DeprecationWarning
     ignore:.*Passing unrecognized arguments to super.*:DeprecationWarning
+    ignore:.*distutils Version classes are deprecated.*:DeprecationWarning
     always::ResourceWarning
     """  # noqa: E501
     for warning_line in warning_lines.split('\n'):


Test patch:
Repository: mne-tools/mne-python

Issue:
Clarification on the relation between SNR and regularization factor 
#### Proposed documentation enhancement
Could we reconcile the different mentions of the relation between SNR and regularization factor for inverse solution? Following are couple of places that don't agree with each other: 

- https://mne.tools/stable/overview/implementation.html#whitening-and-scaling says \lambda^2 ~ 1 / SNR
- https://github.com/mne-tools/mne-python/blob/c3ff05c05c7bfcf765249f27a517803f27f48b4e/mne/minimum_norm/inverse.py#L532 recommends \lambda^2 ~ 1 / SNR^2 
- https://mne.tools/stable/auto_examples/inverse/mixed_source_space_inverse.html?highlight=snr#compute-inverse-solution also uses \lambda^2 ~ 1 / SNR^2
- https://mne.tools/stable/generated/mne.minimum_norm.estimate_snr.html?highlight=snr#mne-minimum-norm-estimate-snr docstring says \lambda ~ 1 / SNR^2

It will be helpful too if there's a reference for this relation. 


Discussion:
good point @mh105 

I think the confusion comes from the implicit definition of SNR in each context. Is the SNR in power (ie amplitude squared) or in amplitude.

this "lambda2 = 1/snr**2" comes from the historical convention in MNE-C code I think.

@mshamalainen any thought?

@larsoner can you find some historicals refs to this in the C code?
Thanks! @agramfort 

Since the published tutorial treats SNR in amplitude, would it make sense to update the implementation details white page to say the same? This could be helpful if people have a priori knowledge about SNR in their data - they can use it correctly to specify lambda2 and not accidentally square it. 

And I assume the \lambda ~ 1 / SNR^2 in this [docstring](https://mne.tools/stable/generated/mne.minimum_norm.estimate_snr.html?highlight=snr#mne-minimum-norm-estimate-snr) is just a typo then. It should say lambda2 \approx 1 / SNR^2 (SNR in amplitude). 

Resolving patch:
diff --git a/mne/minimum_norm/inverse.py b/mne/minimum_norm/inverse.py
--- a/mne/minimum_norm/inverse.py
+++ b/mne/minimum_norm/inverse.py
@@ -1705,7 +1705,7 @@ def estimate_snr(evoked, inv, verbose=None):
         \tilde{M} = R^\frac{1}{2}V\Gamma U^T
 
     The values in the diagonal matrix :math:`\Gamma` are expressed in terms
-    of the chosen regularization :math:`\lambda\approx\frac{1}{\rm{SNR}^2}`
+    of the chosen regularization :math:`\lambda^2 \sim 1/\rm{SNR}^2`
     and singular values :math:`\lambda_k` as:
 
     .. math::


Test patch:
Repository: mne-tools/mne-python

Issue:
DOC: Description of picks in `ica.plot_properties` is incorrect
With the `picks` keyword in `ica.plot_properties`, one can specify what ica sources to plot the properties of. So picks should code the ica source. However, at the moment, the description of picks is the [standard phrase](https://mne.tools/stable/generated/mne.preprocessing.ICA.html#mne.preprocessing.ICA.plot_properties): 

> Channels to include. Slices and lists of integers will be interpreted as channel indices. In lists, channel type strings (e.g., ['meg', 'eeg']) will pick channels of those types, channel name strings (e.g., ['MEG0111', 'MEG2623'] will pick the given channels. Can also be the string values “all” to pick all channels, or “data” to pick data channels. 

plus something specific to this plot: 

> None (default) will pick the first five sources. If more than one components were chosen in the picks, each one will be plotted in a separate figure.

#### Proposed documentation ehancement
The first part does not make sense here, and should be replaced by something like: 

> Sources to plot. None (default) will pick the first five sources. If more than one components were chosen in the picks, each one will be plotted in a separate figure.



Discussion:
Good catch, wanna give it a shot?
Sure, will do!

Resolving patch:
diff --git a/mne/viz/ica.py b/mne/viz/ica.py
--- a/mne/viz/ica.py
+++ b/mne/viz/ica.py
@@ -272,9 +272,10 @@ def plot_ica_properties(ica, inst, picks=None, axes=None, dB=True,
         The ICA solution.
     inst : instance of Epochs or Raw
         The data to use in plotting properties.
-    %(picks_base)s the first five sources.
-        If more than one components were chosen in the picks,
-        each one will be plotted in a separate figure.
+    picks : str | list | slice | None
+        Components to include. Slices and lists of integers will be interpreted
+        as component indices. ``None`` (default) will use the first five
+        components. Each component will be plotted in a separate figure.
     axes : list of Axes | None
         List of five matplotlib axes to use in plotting: [topomap_axis,
         image_axis, erp_axis, spectrum_axis, variance_axis]. If None a new


Test patch:
Repository: mne-tools/mne-python

Issue:
raw.plot() does not produce specified background color.
#### Describe the bug
*raw.plot resluts in a graph that does not use specified background color*

Example:

```python
raw.plot(bgcolor='y', color='r')
```


#### Expected results
Background of plot should be yellow and traces colored red.


#### Actual results
Background is white and traces are red.


#### Additional information
Experimentation with other background color options does not change the outcome. 



Discussion:
As stated on [MNE Discourse discussion](https://mne.discourse.group/t/unable-to-control-background-colors-for-raw-plot/4385/2) I can reproduce the problem. I can take a look at this in around 5 hours, unless someone looks first. :) 

Resolving patch:
diff --git a/mne/viz/_mpl_figure.py b/mne/viz/_mpl_figure.py
--- a/mne/viz/_mpl_figure.py
+++ b/mne/viz/_mpl_figure.py
@@ -363,6 +363,9 @@ def __init__(self, inst, figsize, ica=None,
         # this only gets shown in zen mode
         self.mne.zen_xlabel = ax_main.set_xlabel(xlabel)
         self.mne.zen_xlabel.set_visible(not self.mne.scrollbars_visible)
+        # make sure background color of the axis is set
+        if 'bgcolor' in kwargs:
+            ax_main.set_facecolor(kwargs['bgcolor'])
 
         # SCROLLBARS
         ax_hscroll = div.append_axes(position='bottom',
diff --git a/mne/viz/raw.py b/mne/viz/raw.py
--- a/mne/viz/raw.py
+++ b/mne/viz/raw.py
@@ -345,6 +345,7 @@ def plot_raw(raw, events=None, duration=10.0, start=0.0, n_channels=20,
                   scrollbars_visible=show_scrollbars,
                   scalebars_visible=show_scalebars,
                   window_title=title,
+                  bgcolor=bgcolor,
                   # pyqtgraph-specific
                   precompute=precompute,
                   use_opengl=use_opengl)


Test patch:
Repository: mne-tools/mne-python

Issue:
sys_info doesn't display VTK version number for VTK 9.1
For an environment with VTK 9.1, `mne sys_info` doesn't display the VTK version number:

```shell
ipyvtklink:       0.2.2
vtk:              
PyQt5:            5.12.3
```


Discussion:

Resolving patch:
diff --git a/mne/utils/config.py b/mne/utils/config.py
--- a/mne/utils/config.py
+++ b/mne/utils/config.py
@@ -582,12 +582,15 @@ def sys_info(fid=None, show_paths=False, *, dependencies='user'):
                     gi = GPUInfo()
                     extra += f' {{OpenGL {gi.version} via {gi.renderer}}}'
             if mod_name == 'vtk':
-                version = mod.vtkVersion()
+                vtk_version = mod.vtkVersion()
                 # 9.0 dev has VersionFull but 9.0 doesn't
                 for attr in ('GetVTKVersionFull', 'GetVTKVersion'):
-                    if hasattr(version, attr):
-                        version = getattr(version, attr)()
-                        break
+                    if hasattr(vtk_version, attr):
+                        version = getattr(vtk_version, attr)()
+                        if version != '':
+                            break
+                else:
+                    version = 'unknown'
             elif mod_name == 'PyQt5':
                 version = _check_pyqt5_version()
             else:


Test patch: