Repository: astropy/photutils

Issue:
Background2D corner-case bug
The 2.0 release inadvertently introduced a corner-case bug in `Background2D` where the input data array could be modified if the `box_size` value equals the `data.shape`.  I have a PR in progress to fix this issue, after which I'll make a 2.0.1 release.

Discussion:

Patch:
diff --git a/CHANGES.rst b/CHANGES.rst
index fd706668..21c4801b 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -16,6 +16,9 @@ Bug Fixes
     the returned value would not be preserved if the output was a single
     value. [#1934]
 
+  - Fixed an issue in ``Background2D`` where if the ``box_size`` equals
+    the input array shape the input data array could be modified. [#1935]
+
 API Changes
 ^^^^^^^^^^^
 
diff --git a/photutils/background/background_2d.py b/photutils/background/background_2d.py
index 862ad6b7..2ad49161 100644
--- a/photutils/background/background_2d.py
+++ b/photutils/background/background_2d.py
@@ -500,9 +500,11 @@ class Background2D:
         # another for the reshape). Only one copy of the data and mask
         # array is made (except for the extra corner). The boolean mask
         # copy is much smaller than the data array.
-        core = reshape_as_blocks(self._data[:y1, :x1], self.box_size)
+        # An explicit copy of the data array is needed to avoid
+        # modifying the original data array if the shape of the data
+        # array is (y1, x1) (i.e., box_size = data.shape).
+        core = reshape_as_blocks(self._data[:y1, :x1].copy(), self.box_size)
         core_mask = reshape_as_blocks(mask[:y1, :x1], self.box_size)
-        # these rehape operations need to make a temporary copy
         core = core.reshape((*nboxes, -1))
         core_mask = core_mask.reshape((*nboxes, -1))
         core[core_mask] = np.nan


Test patch:
diff --git a/photutils/background/tests/test_background_2d.py b/photutils/background/tests/test_background_2d.py
index cd187e87..2d0dca01 100644
--- a/photutils/background/tests/test_background_2d.py
+++ b/photutils/background/tests/test_background_2d.py
@@ -12,7 +12,7 @@ from astropy.utils.exceptions import (AstropyDeprecationWarning,
 from numpy.testing import assert_allclose, assert_equal
 
 from photutils.background.background_2d import Background2D
-from photutils.background.core import MeanBackground
+from photutils.background.core import MeanBackground, SExtractorBackground
 from photutils.background.interpolators import (BkgIDWInterpolator,
                                                 BkgZoomInterpolator)
 from photutils.utils._optional_deps import HAS_MATPLOTLIB
@@ -476,3 +476,23 @@ class TestBackground2D:
         assert_equal(arr2, arr3)
 
         assert_equal(bkgimg1, bkgimg2)
+
+    @pytest.mark.parametrize('bkg_est', [MeanBackground(),
+                                         SExtractorBackground()])
+    def test_large_boxsize(self, bkg_est):
+        """
+        Regression test to ensure that when boxsize is the same as the
+        image size that the input data left unchanged.
+        """
+        shape = (103, 107)
+        data = np.ones(shape)
+        data[50:55, 50:55] = 1000.0
+        data[20:25, 20:25] = 1000.0
+        box_size = data.shape
+        filter_size = (3, 3)
+        data_orig = data.copy()
+        bkg = Background2D(data, box_size, filter_size=filter_size,
+                           bkg_estimator=bkg_est)
+        bkgim = bkg.background
+        assert bkgim.shape == shape
+        assert_equal(data, data_orig)