internlm/SWE-Fixer-Train-110K huggingface dataset:
Repository: nilearn/nilearn

Issue:
Stop warning that `GLM` module is experimental
Since Nilearn 0.7.0, we have a warning saying that `nilearn.glm` is experimental and might be subject to change, as well as some warnings here and there in the docs.
Since we are about to reach 0.9.0, it could be time to remove these warnings.
There is no explicit end to these warnings though, so we can probably keep them a little longer if needed.
WDYT?


Discussion:
Thx. I'd go for another cycle.
It's almost been a year now, maybe we could silence them :relaxed: 

Resolving patch:
diff --git a/nilearn/glm/__init__.py b/nilearn/glm/__init__.py
--- a/nilearn/glm/__init__.py
+++ b/nilearn/glm/__init__.py
@@ -1,10 +1,6 @@
 """
 Analysing fMRI data using GLMs.
-
-Note that the nilearn.glm module is experimental.
-     It may change in any future (>0.7.0) release of Nilearn.
 """
-from warnings import warn
 from nilearn.glm.contrasts import (
     compute_contrast,
     compute_fixed_effects,
@@ -51,6 +47,3 @@
     'first_level',
     'second_level',
 ]
-
-warn('The nilearn.glm module is experimental. '
-     'It may change in any future release of Nilearn.', FutureWarning)


Test patch:
Repository: nilearn/nilearn

Issue:
Note that Masker.inverse_transform only performs spatial unmasking in docstring
I vaguely recall a conversation a while back in which a user thought that `NiftiMasker.inverse_transform` would reverse the denoising steps performed by `transform` (e.g., bandpass filtering). Unfortunately, I can't find that conversation. However, it seems like we could reduce confusion by clarifying that `inverse_transform` only performs spatial unmasking.

As far as I can tell, this isn't already documented anywhere.

<!--List any pages that would be impacted by the enhancement.-->
### Affected pages

- Maskers' API pages
- https://nilearn.github.io/stable/manipulating_images/masker_objects.html#inverse-transform-unmasking-data


Discussion:
You're completely right. 
+1 for making that explicit

Resolving patch:
diff --git a/nilearn/maskers/base_masker.py b/nilearn/maskers/base_masker.py
--- a/nilearn/maskers/base_masker.py
+++ b/nilearn/maskers/base_masker.py
@@ -308,6 +308,10 @@ def fit_transform(self, X, y=None, confounds=None, sample_mask=None,
     def inverse_transform(self, X):
         """ Transform the 2D data matrix back to an image in brain space.
 
+        This step only performs spatial unmasking,
+        without inverting any additional processing performed by ``transform``,
+        such as temporal filtering or smoothing. 
+
         Parameters
         ----------
         X : 1D/2D :obj:`numpy.ndarray`


Test patch:
Repository: nilearn/nilearn

Issue:
`line_terminator` error in more recent versions of pandas
A "new" failure in CI seems related to a recent version of pandas.

for example: https://github.com/nilearn/nilearn/actions/runs/4231491657/jobs/7350086385#step:8:16744

https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.to_csv.html

```text
lineterminatorstr, optional

    The newline character or character sequence to use in the output file. Defaults to os.linesep, which depends on the OS in which this method is called (’\n’ for linux, ‘\r\n’ for Windows, i.e.).

    Changed in version 1.5.0: Previously was line_terminator, changed for consistency with read_csv and the standard library ‘csv’ module.
```


Discussion:

Resolving patch:
diff --git a/nilearn/interfaces/bids/glm.py b/nilearn/interfaces/bids/glm.py
--- a/nilearn/interfaces/bids/glm.py
+++ b/nilearn/interfaces/bids/glm.py
@@ -143,7 +143,6 @@ def save_glm_to_bids(
         design_matrix.to_csv(
             dm_file,
             sep='\t',
-            line_terminator='\n',
             index=False,
         )
 


Test patch:
Repository: nilearn/nilearn

Issue:
Use bibtex in nilearn/decomposition
Convert references in:

- `nilearn/decomposition/canica.py`
- `nilearn/decomposition/dict_learning.py`

to use footcite / footbibliography.
See #2759 


Discussion:

Resolving patch:
diff --git a/nilearn/decomposition/canica.py b/nilearn/decomposition/canica.py
--- a/nilearn/decomposition/canica.py
+++ b/nilearn/decomposition/canica.py
@@ -18,7 +18,9 @@
 
 @fill_doc
 class CanICA(_MultiPCA):
-    """Perform Canonical Independent Component Analysis [1]_ [2]_.
+    """Perform :term:`Canonical Independent Component Analysis<CanICA>`.
+
+    See :footcite:`Varoquaux2010c` and :footcite:`Varoquaux2010d`.
 
     Parameters
     ----------
@@ -151,11 +153,7 @@ class CanICA(_MultiPCA):
 
     References
     ----------
-    .. [1] G. Varoquaux et al. "A group model for stable multi-subject ICA on
-       fMRI datasets", NeuroImage Vol 51 (2010), p. 288-299
-
-    .. [2] G. Varoquaux et al. "ICA-based sparse features recovery from fMRI
-       datasets", IEEE ISBI 2010, p. 1177
+    .. footbibliography::
 
     """
 
diff --git a/nilearn/decomposition/dict_learning.py b/nilearn/decomposition/dict_learning.py
--- a/nilearn/decomposition/dict_learning.py
+++ b/nilearn/decomposition/dict_learning.py
@@ -37,10 +37,12 @@ def _compute_loadings(components, data):
 @fill_doc
 class DictLearning(_BaseDecomposition):
     """Perform a map learning algorithm based on spatial component sparsity, \
-    over a :term:`CanICA` initialization [1]_.
+    over a :term:`CanICA` initialization.
 
     This yields more stable maps than :term:`CanICA`.
 
+    See :footcite:`Mensch2016`.
+
      .. versionadded:: 0.2
 
     Parameters
@@ -176,10 +178,7 @@ class DictLearning(_BaseDecomposition):
 
     References
     ----------
-    .. [1] Arthur Mensch, Gael Varoquaux, Bertrand Thirion,
-       Compressed online dictionary learning for fast resting-state fMRI
-       decomposition. IEEE 13th International Symposium on Biomedical
-       Imaging (ISBI), 2016. pp. 1282-1285
+    .. footbibliography::
 
     """
 


Test patch:
Repository: nilearn/nilearn

Issue:
remove `pytest_collection_modifyitems` from conftest.py
              Do we really need this ?
I think we are only supporting 1.19 and above these days.

_Originally posted by @NicolasGensollen in https://github.com/nilearn/nilearn/pull/3609#discussion_r1145977539_
            


Discussion:

Resolving patch:
diff --git a/nilearn/conftest.py b/nilearn/conftest.py
--- a/nilearn/conftest.py
+++ b/nilearn/conftest.py
@@ -2,13 +2,11 @@
 import nibabel
 import numpy as np
 import pytest
-from _pytest.doctest import DoctestItem
 from nilearn import image
 
 # we need to import these fixtures even if not used in this module
 from nilearn.datasets._testing import request_mocker  # noqa: F401
 from nilearn.datasets._testing import temp_nilearn_data_dir  # noqa: F401
-from nilearn.version import _compare_version
 
 collect_ignore = ["datasets/data/convert_templates.py"]
 
@@ -77,21 +75,3 @@ def close_all():
         import matplotlib.pyplot as plt
 
         plt.close("all")  # takes < 1 us so just always do it
-
-
-def pytest_collection_modifyitems(items):
-    """Run doctests only for numpy >= 1.14.Adapted from scikit-learn.
-
-    numpy changed the str/repr formatting of numpy arrays in 1.14.
-    """
-    if _compare_version(np.__version__, "<", "1.14"):
-        reason = "doctests are only run for numpy >= 1.14"
-        skip_doctests = True
-    else:
-        skip_doctests = False
-
-    if skip_doctests:
-        skip_marker = pytest.mark.skip(reason=reason)
-        for item in items:
-            if isinstance(item, DoctestItem):
-                item.add_marker(skip_marker)


Test patch:
Repository: nilearn/nilearn

Issue:
Documentation build failure on main
Some examples failed on the doc build after last merge on main
https://github.com/nilearn/nilearn/actions/runs/4573237098/jobs/8073423194

Looking into it...


Discussion:

Resolving patch:
diff --git a/nilearn/glm/first_level/first_level.py b/nilearn/glm/first_level/first_level.py
--- a/nilearn/glm/first_level/first_level.py
+++ b/nilearn/glm/first_level/first_level.py
@@ -850,7 +850,7 @@ def first_level_from_bids(dataset_path,
         If 'None', will model all subjects in the dataset.
         .. versionadded:: 0.10.1.dev
 
-    img_filters : :obj:`list` of :obj:`tuples` (str, str), optional
+    img_filters : :obj:`list` of :obj:`tuple` (str, str), optional
         Filters are of the form (field, label). Only one filter per field
         allowed.
         A file that does not match a filter will be discarded.
diff --git a/nilearn/glm/second_level/second_level.py b/nilearn/glm/second_level/second_level.py
--- a/nilearn/glm/second_level/second_level.py
+++ b/nilearn/glm/second_level/second_level.py
@@ -136,7 +136,7 @@ def _check_input_as_nifti_images(second_level_input, none_design_matrix):
     if isinstance(second_level_input, (str, Nifti1Image)):
         second_level_input = [second_level_input]
     for niimg in second_level_input:
-        check_niimg(niimg=niimg, ensure_ndim=4)
+        check_niimg(niimg=niimg, atleast_4d=True)
     if none_design_matrix:
         raise ValueError('List of niimgs as second_level_input'
                          ' require a design matrix to be provided')


Test patch:
Repository: nilearn/nilearn

Issue:
check if  `pd.option_context("display.precision", 2)` are still necessary
Let's check if this comment is still relevant or needs to be updated because now we support pandas>=1.1.5

_Originally posted by @ymzayek in https://github.com/nilearn/nilearn/pull/3615#discussion_r1147292448_
       

Remove them if that's not the case


Discussion:

Resolving patch:
diff --git a/nilearn/reporting/glm_reporter.py b/nilearn/reporting/glm_reporter.py
--- a/nilearn/reporting/glm_reporter.py
+++ b/nilearn/reporting/glm_reporter.py
@@ -170,12 +170,6 @@ def make_glm_report(
     report_text : HTMLReport Object
         Contains the HTML code for the GLM Report.
 
-    """
-    """
-    Bug in Pandas 0.18 : https://github.com/pandas-dev/pandas/issues/13257
-    pd.set_option('display.precision', 2)
-    limits number of digits shown instead of precision.
-    Hence pd.option_context('display.precision', 2) has been used.
     """
     if bg_img == "MNI152TEMPLATE":
         bg_img = MNI152TEMPLATE


Test patch:
Repository: nilearn/nilearn

Issue:
Add doctest to as_ndarrays in `numpy_conversions.py` 
              Not necessary but can turn into a doctest:

```python
    >>> import numpy
    >>> a = numpy.asarray([0, 1, 2], dtype=numpy.int8)
    >>> b = as_ndarray(a, dtype=bool)
    >>> b
    array([False,  True,  True])
    >>> c = as_ndarray(b, dtype=numpy.int8)
    >>> c
    array([0, 1, 2], dtype=int8)
```

_Originally posted by @ymzayek in https://github.com/nilearn/nilearn/pull/3614#discussion_r1147404584_
            


Discussion:

Resolving patch:
diff --git a/nilearn/_utils/numpy_conversions.py b/nilearn/_utils/numpy_conversions.py
--- a/nilearn/_utils/numpy_conversions.py
+++ b/nilearn/_utils/numpy_conversions.py
@@ -56,9 +56,14 @@ def as_ndarray(arr, copy=False, dtype=None, order="K"):
 
     Example:
 
-        a = numpy.asarray([0, 1, 2], dtype=numpy.int8)
-        b = as_ndarray(a, dtype=bool) # array([False, True, True], dtype=bool)
-        c = as_ndarray(b, dtype=numpy.int8) # array([0, 1, 2], dtype=numpy.int8) # noqa
+    >>> import numpy
+    >>> a = numpy.asarray([0, 1, 2], dtype=numpy.int8)
+    >>> b = as_ndarray(a, dtype=bool)
+    >>> b
+    array([False,  True,  True])
+    >>> c = as_ndarray(b, dtype=numpy.int8)
+    >>> c
+    array([0, 1, 2], dtype=int8)
 
     The usually expected result for the last line would be array([0, 1, 1])
     because True evaluates to 1. Since there is no copy made here, the original


Test patch:
Repository: nilearn/nilearn

Issue:
Documentation builder failure on main
https://github.com/nilearn/nilearn/actions/workflows/build-docs.yml

started occurring after merging #3698 (doubt it is related given the content of the PR)
https://github.com/nilearn/nilearn/actions/runs/4741116007




Discussion:
The problem comes from this [PR](https://github.com/nilearn/nilearn/pull/3693/files#diff-a7e51d164f44800beebb5ec50d42c9cb0bc7fe129ac72db066d129ccc825b93a) where the import of `fetch_atlas_pauli_2017` was removed from \_\_init__.py probably because it wasn't set in `__all__`

Resolving patch:
diff --git a/nilearn/datasets/__init__.py b/nilearn/datasets/__init__.py
--- a/nilearn/datasets/__init__.py
+++ b/nilearn/datasets/__init__.py
@@ -10,6 +10,7 @@
     fetch_atlas_harvard_oxford,
     fetch_atlas_juelich,
     fetch_atlas_msdl,
+    fetch_atlas_pauli_2017,
     fetch_atlas_schaefer_2018,
     fetch_atlas_smith_2009,
     fetch_atlas_surf_destrieux,
@@ -24,6 +25,7 @@
     fetch_adhd,
     fetch_bids_langloc_dataset,
     fetch_development_fmri,
+    fetch_ds000030_urls,
     fetch_fiac_first_level,
     fetch_haxby,
     fetch_language_localizer_demo_dataset,
@@ -86,6 +88,7 @@
     "fetch_atlas_juelich",
     "fetch_atlas_harvard_oxford",
     "fetch_atlas_msdl",
+    "fetch_atlas_pauli_2017",
     "fetch_atlas_schaefer_2018",
     "fetch_coords_power_2011",
     "fetch_coords_seitzman_2018",
@@ -98,6 +101,7 @@
     "fetch_megatrawls_netmats",
     "fetch_surf_nki_enhanced",
     "fetch_development_fmri",
+    "fetch_ds000030_urls",
     "fetch_surf_fsaverage",
     "fetch_atlas_basc_multiscale_2015",
     "fetch_coords_dosenbach_2010",


Test patch:
Repository: nilearn/nilearn

Issue:
Remove unnecessary try block
we only support "scipy>=1.6.0" so maybe this is not needed anymore?

_Originally posted by @Remi-Gau in https://github.com/nilearn/nilearn/pull/3827#discussion_r1256329615_
            


Discussion:

Resolving patch:
diff --git a/nilearn/image/resampling.py b/nilearn/image/resampling.py
--- a/nilearn/image/resampling.py
+++ b/nilearn/image/resampling.py
@@ -584,11 +584,6 @@ def resample_img(
         target_shape = target_shape.tolist()
     target_shape = tuple(target_shape)
 
-    if _compare_version(scipy.__version__, "<", "0.20"):
-        # Before scipy 0.20, force native data types due to endian issues
-        # that caused instability.
-        data = data.astype(data.dtype.newbyteorder("N"))
-
     if interpolation == "continuous" and data.dtype.kind == "i":
         # cast unsupported data types to closest support dtype
         aux = data.dtype.name.replace("int", "float")
@@ -662,10 +657,6 @@ def resample_img(
         # If A is diagonal, ndimage.affine_transform is clever enough to use a
         # better algorithm.
         if np.all(np.diag(np.diag(A)) == A):
-            if _compare_version(scipy.__version__, "<", "0.18"):
-                # Before scipy 0.18, ndimage.affine_transform was applying a
-                # different logic to the offset for diagonal affine
-                b = np.dot(linalg.inv(A), b)
             A = np.diag(A)
         # Iterate over a set of 3D volumes, as the interpolation problem is
         # separable in the extra dimensions. This reduces the
diff --git a/nilearn/plotting/matrix_plotting.py b/nilearn/plotting/matrix_plotting.py
--- a/nilearn/plotting/matrix_plotting.py
+++ b/nilearn/plotting/matrix_plotting.py
@@ -6,6 +6,7 @@
 import numpy as np
 import pandas as pd
 from mpl_toolkits.axes_grid1 import make_axes_locatable
+from scipy.cluster.hierarchy import leaves_list, linkage, optimal_leaf_ordering
 
 from .._utils import fill_doc
 
@@ -129,17 +130,7 @@ def _reorder_matrix(mat, labels, reorder):
     """
     if not labels:
         raise ValueError("Labels are needed to show the reordering.")
-    try:
-        from scipy.cluster.hierarchy import (
-            leaves_list,
-            linkage,
-            optimal_leaf_ordering,
-        )
-    except ImportError:
-        raise ImportError(
-            "A scipy version of at least 1.0 is needed for "
-            "ordering the matrix with optimal_leaf_ordering."
-        )
+
     linkage_matrix = linkage(mat, method=reorder)
     ordered_linkage = optimal_leaf_ordering(linkage_matrix, mat)
     index = leaves_list(ordered_linkage)


Test patch:
Repository: nilearn/nilearn

Issue:
dead code: decorator for deprecated arguments
The decorator introduced in glm.regression in this commit seems now unused.

https://github.com/nilearn/nilearn/commit/e6591d8907ceae55eea6f04ce181acb6a12743b5

I wonder if it is better to remove it or to move it to _utils.helpers where other deprecation handling tools are located and to do some refactoring where possible to "standardize" how deprecation warnings are sent.


Discussion:
I'd remove it.

Resolving patch:
diff --git a/nilearn/glm/regression.py b/nilearn/glm/regression.py
--- a/nilearn/glm/regression.py
+++ b/nilearn/glm/regression.py
@@ -17,8 +17,6 @@
 
 __docformat__ = "restructuredtext en"
 
-import functools
-import warnings
 
 import numpy as np
 import scipy.linalg as spl
@@ -29,28 +27,6 @@
 from nilearn.glm.model import LikelihoodModelResults
 
 
-def _deprecation_warning(
-    old_param, new_param, start_version, end_version="future"
-):
-    def _warned_func(func):
-        @functools.wraps(func)
-        def wrapper(*args, **kwargs):
-            warnings.warn(
-                category=FutureWarning,
-                message=(
-                    f"'{old_param}' has been deprecated "
-                    f"in version {start_version} "
-                    f"and will be removed in version {end_version}.\n"
-                    f"Please use '{new_param}' instead."
-                ),
-            )
-            return func(*args, **kwargs)
-
-        return wrapper
-
-    return _warned_func
-
-
 class OLSModel:
     """A simple ordinary least squares model.
 


Test patch:
Repository: nilearn/nilearn

Issue:
Revert `plot_glass_brain` behavior to silently ignore `vmin`
The merged PR https://github.com/nilearn/nilearn/pull/3873 broke an example passing vmin to `plot_glass_brain` which now throws a ValueError. The bug throwing the error that a function does not except vmin was applicable to the fixed function (`plot_img_on_surf`) and to `plot_stat_map` but not to `plot_glass_brain`. `plot_glass_brain` actually accepts vmin but ignores it by not passing it to `_get_colorbar_and_data_ranges`. I'll revert the behavior of `plot_glass_brain` so that it does not throw an error but simply ignores vmin and I'll add a test. The original bug can then be fixed in a PR follow-up addressing #3084.


Discussion:

Resolving patch:
diff --git a/nilearn/plotting/img_plotting.py b/nilearn/plotting/img_plotting.py
--- a/nilearn/plotting/img_plotting.py
+++ b/nilearn/plotting/img_plotting.py
@@ -1079,14 +1079,12 @@ def plot_glass_brain(stat_map_img,
         if plot_abs:
             cbar_vmin, cbar_vmax, vmin, vmax = _get_colorbar_and_data_ranges(
                 _safe_get_data(stat_map_img, ensure_finite=True),
-                vmin=vmin,
                 vmax=vmax,
                 symmetric_cbar=symmetric_cbar,
                 force_min_stat_map_value=0)
         else:
             cbar_vmin, cbar_vmax, vmin, vmax = _get_colorbar_and_data_ranges(
                 _safe_get_data(stat_map_img, ensure_finite=True),
-                vmin=vmin,
                 vmax=vmax,
                 symmetric_cbar=symmetric_cbar)
     else:


Test patch:
diff --git a/nilearn/plotting/tests/test_img_plotting/test_plot_glass_brain.py b/nilearn/plotting/tests/test_img_plotting/test_plot_glass_brain.py
--- a/nilearn/plotting/tests/test_img_plotting/test_plot_glass_brain.py
+++ b/nilearn/plotting/tests/test_img_plotting/test_plot_glass_brain.py
@@ -114,3 +114,8 @@ def test_plot_glass_brain_with_completely_masked_img(display_mode):
     img = Nifti1Image(np.zeros((10, 20, 30)), np.eye(4))
     plot_glass_brain(img, display_mode=display_mode)
     plt.close()
+
+
+def test_plot_glass_brain_vmin_vmax(mni_3d_img):
+    """Smoke tests for plot_glass_brain being passed vmin and vmax."""
+    plot_glass_brain(mni_3d_img, vmin=-2, vmax=2)
Repository: nilearn/nilearn

Issue:
Updating contributors affiliations
Closes #1511

## Goal

Use citation.cff file to document contributors:
- affiliations
- email
- ORCID

## Process

### Collect information about the contributors

"crowd source" information about contributors in this google spreadsheet:

https://docs.google.com/spreadsheets/d/1FN_u72YuwTeo-VuuCWp7SeKqseeUzoo-Sn0oAlNIZWw/edit#gid=2079625190

Nilearn contributors present at the OHBM 2023 hackathon can directly update their information in that spreadsheet during the hackthon.

For the other contributors, the goal will be to search and update manually the details for them.

### Update the citation.cff content

Depending on how many people decide to work on this, updating the citation.cff can be done:
- by writing a script to read from the table to update the authors section of the citation file
- manually updating the content of the citation.cff files in several pull requests:
  - Contributors from A to C
  - Contributors from D to J
  - Contributors from K to P
  - Contributors from Q to Z




Discussion:

Resolving patch:
diff --git a/maint_tools/citation_cff_maint.py b/maint_tools/citation_cff_maint.py
--- a/maint_tools/citation_cff_maint.py
+++ b/maint_tools/citation_cff_maint.py
@@ -142,7 +142,10 @@ def write_team_section(f, authors: list[dict[str, str]]) -> None:
 """
     )
     for author_ in authors:
-        f.write(f"* `{author_['given-names']} {author_['family-names']}`_\n")
+        f.write(f"* `{author_['given-names']} {author_['family-names']}`_")
+        if author_.get("affiliation"):
+            f.write(f": {author_['affiliation']}")
+        f.write("\n")
 
     f.write(
         """


Test patch:
Repository: nilearn/nilearn

Issue:
[BUG] Contours in `plot_3d_map_to_surface_projection` examples are not being rendered correctly
BTW while checking this I noticed that in the same example where `plot_surf_contours` is used the contours are not rendered anymore. This is not related to this PR as I can also see it in the build artifacts dating back at least a month. I'll open a separate issue

_Originally posted by @ymzayek in https://github.com/nilearn/nilearn/issues/3949#issuecomment-1709626764_

Edit: If you look closely you can see small points, so it seems the rendering changed rather than being non existent.

See stable docs: https://nilearn.github.io/stable/auto_examples/01_plotting/plot_3d_map_to_surface_projection.html

See dev docs: https://nilearn.github.io/dev/auto_examples/01_plotting/plot_3d_map_to_surface_projection.html
            


Discussion:
It seems to be coming from this merge https://github.com/nilearn/nilearn/commit/069980cb5afb583704a2a26a1ece1e76b9ce4034

Resolving patch:
diff --git a/nilearn/plotting/surf_plotting.py b/nilearn/plotting/surf_plotting.py
--- a/nilearn/plotting/surf_plotting.py
+++ b/nilearn/plotting/surf_plotting.py
@@ -15,7 +15,7 @@
 from mpl_toolkits.mplot3d.art3d import Poly3DCollection
 
 from nilearn import image, surface
-from nilearn._utils import check_niimg_3d, fill_doc
+from nilearn._utils import _compare_version, check_niimg_3d, fill_doc
 from nilearn.plotting.cm import _mix_colormaps, cold_hot
 from nilearn.plotting.html_surface import _get_vertexcolor
 from nilearn.plotting.img_plotting import _get_colorbar_and_data_ranges
@@ -959,10 +959,20 @@ def plot_surf_contours(surf_mesh, roi_map, axes=None, figure=None, levels=None,
         # Fix: Matplotlib version 3.3.2 to 3.3.3
         # Attribute _facecolors3d changed to _facecolor3d in
         # matplotlib version 3.3.3
-        try:
+        if _compare_version(mpl.__version__, "<", "3.3.3"):
             axes.collections[0]._facecolors3d[faces_outside] = color
-        except AttributeError:
+            if axes.collections[0]._edgecolors3d.size == 0:
+                axes.collections[0].set_edgecolor(
+                    axes.collections[0]._facecolors3d
+                )
+            axes.collections[0]._edgecolors3d[faces_outside] = color
+        else:
             axes.collections[0]._facecolor3d[faces_outside] = color
+            if axes.collections[0]._edgecolor3d.size == 0:
+                axes.collections[0].set_edgecolor(
+                    axes.collections[0]._facecolor3d
+                )
+            axes.collections[0]._edgecolor3d[faces_outside] = color
         if label and legend:
             patch_list.append(Patch(color=color, label=label))
     # plot legend only if indicated and labels provided


Test patch: