Coverage for tests / test_subtractBackground.py: 21%
71 statements
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-25 08:26 +0000
« prev ^ index » next coverage.py v7.13.5, created at 2026-04-25 08:26 +0000
1# This file is part of meas_algorithms.
2#
3# Developed for the LSST Data Management System.
4# This product includes software developed by the LSST Project
5# (http://www.lsst.org).
6# See the COPYRIGHT file at the top-level directory of this distribution
7# for details of code ownership.
8#
9# This software is dual licensed under the GNU General Public License and also
10# under a 3-clause BSD license. Recipients may choose which of these licenses
11# to use; please see the files gpl-3.0.txt and/or bsd_license.txt,
12# respectively. If you choose the GPL option then the following text applies
13# (but note that there is still no warranty even if you opt for BSD instead):
14#
15# This program is free software: you can redistribute it and/or modify
16# it under the terms of the GNU General Public License as published by
17# the Free Software Foundation, either version 3 of the License, or
18# (at your option) any later version.
19#
20# This program is distributed in the hope that it will be useful,
21# but WITHOUT ANY WARRANTY; without even the implied warranty of
22# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23# GNU General Public License for more details.
24#
25# You should have received a copy of the GNU General Public License
26# along with this program. If not, see <http://www.gnu.org/licenses/>.
27import unittest
28import numpy as np
30import lsst.geom
31from lsst.meas.algorithms.testUtils import plantSources
32import lsst.utils.tests
34from lsst.meas.algorithms.subtractBackground import (
35 SubtractBackgroundConfig,
36 SubtractBackgroundTask,
37 backgroundFlatContext,
38)
41class SubtractBackgroundTaskTestCase(lsst.utils.tests.TestCase):
43 def _create_exposure(self, keepSky=True):
44 """Return a simulated exposure with some background."""
46 bbox = lsst.geom.Box2I(lsst.geom.Point2I(0, 0), lsst.geom.Extent2I(1024, 1024))
47 kwid = 11
48 self.sky = 2000
50 coordList = [[10, 10, 0, 2.0]]
52 exposure = plantSources(
53 bbox=bbox,
54 kwid=kwid,
55 sky=self.sky,
56 coordList=coordList,
57 addPoissonNoise=True,
58 )
59 if keepSky:
60 # Add sky level back in.
61 exposure.image.array += self.sky
63 return exposure
65 def test_subtractBackground(self):
66 exp = self._create_exposure()
68 config = SubtractBackgroundConfig()
69 task = SubtractBackgroundTask(config=config)
71 results = task.run(exp)
73 # Check the background was subtracted.
74 self.assertFloatsAlmostEqual(np.mean(exp.image.array), 0.0, atol=0.1)
76 # Check the background level.
77 backgroundImage = results.background.getImage()
78 self.assertFloatsAlmostEqual(np.mean(backgroundImage.array), self.sky, atol=0.1)
80 # Do a second pass and confirm everything works.
81 results2 = task.run(exp, background=results.background)
82 self.assertEqual(len(results2.background), 2)
84 self.assertFloatsAlmostEqual(np.mean(exp.image.array), 0.0, atol=0.1)
85 backgroundImage2 = results2.background.getImage()
86 self.assertFloatsAlmostEqual(np.mean(backgroundImage2.array), self.sky, atol=0.1)
88 def test_subtractBackgroundWithFlatRatio(self):
89 exp = self._create_exposure()
91 config = SubtractBackgroundConfig()
92 config.doApplyFlatBackgroundRatio = True
93 task = SubtractBackgroundTask(config=config)
95 ratioImage = exp.image.clone()
96 ratioImage.array[:, :] = 2.0
98 results = task.run(exp, backgroundToPhotometricRatio=ratioImage)
100 # Check the background was subtracted.
101 self.assertFloatsAlmostEqual(np.mean(exp.image.array), 0.0, atol=0.1)
103 # Check the background level.
104 # This will be twice as large (in "background units") because of the
105 # ratio scaling.
106 backgroundImage = results.background.getImage()
107 self.assertFloatsAlmostEqual(np.mean(backgroundImage.array), self.sky * 2.0, atol=0.2)
109 # Check that we get Raises with improper inputs.
110 with self.assertRaises(RuntimeError):
111 _ = task.run(exp)
113 with self.assertRaises(ValueError):
114 _ = task.run(exp, backgroundToPhotometricRatio=exp.maskedImage)
116 def test_backgroundFlatContext(self):
117 exp = self._create_exposure(keepSky=False)
119 # Check that doApply=False does nothing inside and out.
120 maskedImage = exp.maskedImage.clone()
121 with backgroundFlatContext(maskedImage, False):
122 self.assertMaskedImagesAlmostEqual(maskedImage, exp.maskedImage)
123 self.assertMaskedImagesAlmostEqual(maskedImage, exp.maskedImage)
125 # Check that doApply=True does the conversions correctly.
126 ratioImage = exp.image.clone()
127 ratioImage.array[:, :] = 2.0
128 maskedImage = exp.maskedImage.clone()
129 with backgroundFlatContext(maskedImage, True, backgroundToPhotometricRatio=ratioImage):
130 comparisonImage = exp.maskedImage.clone()
131 comparisonImage *= ratioImage
132 self.assertMaskedImagesAlmostEqual(maskedImage, comparisonImage)
133 self.assertMaskedImagesAlmostEqual(maskedImage, exp.maskedImage)
135 # Check that doApply=True with an incorrect ratio image raises.
136 with self.assertRaises(ValueError):
137 with backgroundFlatContext(maskedImage, True, backgroundToPhotometricRatio=exp.maskedImage):
138 pass
140 # Check that doApply=True with no ratio image raises.
141 with self.assertRaises(RuntimeError):
142 with backgroundFlatContext(maskedImage, True):
143 pass
146class TestMemory(lsst.utils.tests.MemoryTestCase):
147 pass
150def setup_module(module):
151 lsst.utils.tests.init()
154if __name__ == "__main__": 154 ↛ 155line 154 didn't jump to line 155 because the condition on line 154 was never true
155 lsst.utils.tests.init()
156 unittest.main()