Skip to content

Commit

Permalink
Merge pull request #1703 from larrybradley/psf-localbkg
Browse files Browse the repository at this point in the history
Change default to not include local background in PSF model/residual images
  • Loading branch information
larrybradley authored Feb 13, 2024
2 parents 7d0da10 + 5d7e35d commit dbf6cb0
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 9 deletions.
5 changes: 5 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,11 @@ API Changes
- The ``GridddedPSFModel`` string representations now include the
model ``flux``, ``x_0``, and ``y_0`` parameters. [#1680]

- The PSF photometry ``make_model_image`` and ``make_residual_image``
methods no longer include the local background by default. This is a
backwards-incompatible change. If the previous behavior is desired,
set ``include_localbkg=True``. [#1703]

- ``photutils.segmentation``

- The ``SourceCatalog`` ``get_label`` and ``get_labels`` methods now
Expand Down
24 changes: 15 additions & 9 deletions photutils/psf/photometry.py
Original file line number Diff line number Diff line change
Expand Up @@ -1027,9 +1027,10 @@ def __call__(self, data, *, mask=None, error=None, init_params=None):

return source_tbl

def make_model_image(self, shape, psf_shape, include_localbkg=True):
def make_model_image(self, shape, psf_shape, *, include_localbkg=False):
"""
Create a 2D image from the fit PSF models and local background.
Create a 2D image from the fit PSF models and optional local
background.
Parameters
----------
Expand All @@ -1042,8 +1043,11 @@ def make_model_image(self, shape, psf_shape, include_localbkg=True):
include_localbkg : bool, optional
Whether to include the local background in the rendered
output image.
Default is True.
output image. Note that the local background level is
included around each source over the region defined by
``psf_shape``. Thus, regions where the ``psf_shape`` of
sources overlap will have the local background added
multiple times.
Returns
-------
Expand Down Expand Up @@ -1078,7 +1082,7 @@ def make_model_image(self, shape, psf_shape, include_localbkg=True):

return data

def make_residual_image(self, data, psf_shape, include_localbkg=True):
def make_residual_image(self, data, psf_shape, *, include_localbkg=False):
"""
Create a 2D residual image from the fit PSF models and local
background.
Expand All @@ -1096,8 +1100,10 @@ def make_residual_image(self, data, psf_shape, include_localbkg=True):
include_localbkg : bool, optional
Whether to include the local background in the subtracted
model.
Default is True.
model. Note that the local background level is subtracted
around each source over the region defined by ``psf_shape``.
Thus, regions where the ``psf_shape`` of sources overlap
will have the local background subtracted multiple times.
Returns
-------
Expand All @@ -1107,8 +1113,8 @@ def make_residual_image(self, data, psf_shape, include_localbkg=True):
"""
if isinstance(data, NDData):
residual = deepcopy(data)
residual.data[:] = self.make_residual_image(data.data, psf_shape,
include_localbkg=include_localbkg)
residual.data[:] = self.make_residual_image(
data.data, psf_shape, include_localbkg=include_localbkg)
else:
unit = None
if isinstance(data, u.Quantity):
Expand Down
38 changes: 38 additions & 0 deletions photutils/psf/tests/test_photometry.py
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,44 @@ def test_psf_photometry(test_data):
assert resid_data3.unit == unit


@pytest.mark.skipif(not HAS_SCIPY, reason='scipy is required')
def test_model_residual_image(test_data):
data, error, _ = test_data

data = data + 10
psf_model = IntegratedGaussianPRF(flux=1, sigma=2.7 / 2.35)
fit_shape = (5, 5)
finder = DAOStarFinder(16.0, 2.0)
bkgstat = MMMBackground()
localbkg_estimator = LocalBackground(5, 10, bkgstat)
psfphot = PSFPhotometry(psf_model, fit_shape, finder=finder,
aperture_radius=4,
localbkg_estimator=localbkg_estimator)
psfphot(data, error=error)

psf_shape = (25, 25)
model1 = psfphot.make_model_image(data.shape, psf_shape,
include_localbkg=False)
model2 = psfphot.make_model_image(data.shape, psf_shape,
include_localbkg=True)
resid1 = psfphot.make_residual_image(data, psf_shape,
include_localbkg=False)
resid2 = psfphot.make_residual_image(data, psf_shape,
include_localbkg=True)

x, y = 0, 100
assert model1[y, x] < 0.1
assert model2[y, x] > 9
assert resid1[y, x] > 9
assert resid2[y, x] < 0

x, y = 0, 80
assert model1[y, x] < 0.1
assert model2[y, x] > 18
assert resid1[y, x] > 9
assert resid2[y, x] < -9


@pytest.mark.skipif(not HAS_SCIPY, reason='scipy is required')
def test_psf_photometry_compound(test_data):
"""
Expand Down

0 comments on commit dbf6cb0

Please sign in to comment.