Repository: astropy/photutils

Issue:
error with `centroid_func`
When using the `error` keyword with a None value, when using  a `centroid_func` which support it,

```
import numpy as np
from photutils.centroids import centroid_sources, centroid_2dg
xc, yc = centroid_sources(np.ones((10,10)), 5, 5, error=None, centroid_func=centroid_2dg)
```
 `centroid_func` raise a Type Error: 
```
/usr/lib/python3/dist-packages/photutils/centroids/core.py in centroid_sources(data, xpos, ypos, box_size, footprint, mask, centroid_func, **kwargs)
    403 
    404         if 'error' in centroid_kwargs:
--> 405             error_cutout = centroid_kwargs['error'][slices_large]
    406             centroid_kwargs['error'] = error_cutout
    407 

TypeError: 'NoneType' object is not subscriptable
```

I guess Line 404 should be written as 
```
if 'error' in centroid_kwargs and centroid_kwargs['error'] is not None:
```

Discussion:

Patch:
diff --git a/CHANGES.rst b/CHANGES.rst
index 2a56b086..c7b45790 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -38,6 +38,12 @@ Bug Fixes
     would result in incorrect image padding if only one of the axes needed
     padding. [#1292]
 
+- ``photutils.centroid``
+
+    - Fixed a bug in ``centroid_sources`` where setting ``error``,
+      ``xpeak``, or ``ypeak`` to ``None`` would result in an error.
+      [#1297]
+
 API Changes
 ^^^^^^^^^^^
 
diff --git a/photutils/centroids/core.py b/photutils/centroids/core.py
index 27ca6a97..85782f0b 100644
--- a/photutils/centroids/core.py
+++ b/photutils/centroids/core.py
@@ -399,13 +399,17 @@ def centroid_sources(data, xpos, ypos, box_size=11, footprint=None, mask=None,
 
         centroid_kwargs.update({'mask': mask_cutout})
 
-        if 'error' in centroid_kwargs:
-            error_cutout = centroid_kwargs['error'][slices_large]
-            centroid_kwargs['error'] = error_cutout
-
-        if 'xpeak' in centroid_kwargs and 'ypeak' in centroid_kwargs:
-            centroid_kwargs['xpeak'] -= slices_large[1].start
-            centroid_kwargs['ypeak'] -= slices_large[0].start
+        error = centroid_kwargs.get('error', None)
+        if error is not None:
+            centroid_kwargs['error'] = error[slices_large]
+
+        # remove xpeak and ypeak from the dict and add back only if both
+        # are specified and not None
+        xpeak = centroid_kwargs.pop('xpeak', None)
+        ypeak = centroid_kwargs.pop('ypeak', None)
+        if xpeak is not None and ypeak is not None:
+            centroid_kwargs['xpeak'] = xpeak - slices_large[1].start
+            centroid_kwargs['ypeak'] = ypeak - slices_large[0].start
 
         try:
             xcen, ycen = centroid_func(data_cutout, **centroid_kwargs)


Test patch:
diff --git a/photutils/centroids/tests/test_core.py b/photutils/centroids/tests/test_core.py
index e6be4747..d8835e70 100644
--- a/photutils/centroids/tests/test_core.py
+++ b/photutils/centroids/tests/test_core.py
@@ -314,3 +314,25 @@ class TestCentroidSources:
                                             box_size=(55, 55), mask=mask)
         assert not np.allclose(xcen1, xcen2)
         assert not np.allclose(ycen1, ycen2)
+
+    def test_error_none(self):
+        xycen1 = centroid_sources(self.data, xpos=25, ypos=25, error=None,
+                                  centroid_func=centroid_1dg)
+        xycen2 = centroid_sources(self.data, xpos=25, ypos=25, error=None,
+                                  centroid_func=centroid_2dg)
+        assert_allclose(xycen1, ([25], [25]), atol=1.e-3)
+        assert_allclose(xycen2, ([25], [25]), atol=1.e-3)
+
+    def test_xypeaks_none(self):
+        xycen1 = centroid_sources(self.data, xpos=25, ypos=25, error=None,
+                                  xpeak=None, ypeak=25,
+                                  centroid_func=centroid_quadratic)
+        xycen2 = centroid_sources(self.data, xpos=25, ypos=25, error=None,
+                                  xpeak=25, ypeak=None,
+                                  centroid_func=centroid_quadratic)
+        xycen3 = centroid_sources(self.data, xpos=25, ypos=25, error=None,
+                                  xpeak=None, ypeak=None,
+                                  centroid_func=centroid_quadratic)
+        assert_allclose(xycen1, ([25], [25]), atol=1.e-3)
+        assert_allclose(xycen2, ([25], [25]), atol=1.e-3)
+        assert_allclose(xycen3, ([25], [25]), atol=1.e-3)