Coverage for tests/test_repair.py: 94%
50 statements
« prev ^ index » next coverage.py v7.16.2, created at 2026-10-24 09:42 +0000
« prev ^ index » next coverage.py v7.16.2, created at 2026-10-24 09:42 +0000
1# This file is part of pipe_tasks.
2#
3# Developed for the LSST Data Management System.
4# This product includes software developed by the LSST Project
5# (https://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 program is free software: you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation, either version 3 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program. If not, see <https://www.gnu.org/licenses/>.
22"""Tests for RepairTask cosmic ray finding."""
23import unittest
25import numpy as np
27import lsst.afw.detection as afwDet
28import lsst.afw.image as afwImage
29import lsst.geom
30import lsst.utils.tests
31from lsst.pipe.tasks.repair import RepairTask
34class RepairTaskTestCase(lsst.utils.tests.TestCase):
35 """Test RepairTask.cosmicRay with and without a local background model."""
37 def setUp(self):
38 self.sky = 100.0
39 self.gain = 2.0
40 self.crValue = 5000.0
41 self.crPosition = (40, 60) # x, y
42 rng = np.random.default_rng(12345)
43 size = 200
44 exposure = afwImage.ExposureF(lsst.geom.Box2I(lsst.geom.Point2I(0, 0),
45 lsst.geom.Extent2I(size, size)))
46 image = exposure.image.array
47 image[:] = rng.normal(self.sky, np.sqrt(self.sky/self.gain), size=(size, size))
48 x, y = self.crPosition
49 image[y, x] = self.crValue
50 exposure.variance.array[:] = image/self.gain
51 exposure.setPsf(afwDet.GaussianPsf(11, 11, 1.5))
52 self.exposure = exposure
53 self.originalMedian = np.median(image)
55 def _checkRepaired(self, exposure):
56 x, y = self.crPosition
57 crBit = exposure.mask.getPlaneBitMask("CR")
58 self.assertEqual(exposure.mask.array[y, x] & crBit, crBit)
59 self.assertLess(exposure.image.array[y, x], 10*np.sqrt(self.sky/self.gain) + self.sky)
60 # The background must not be changed by the repair.
61 self.assertFloatsAlmostEqual(np.median(exposure.image.array), self.originalMedian, rtol=0.02)
63 def testConstantBackground(self):
64 """With the default binSize (larger than the image) a single median
65 background is used."""
66 config = RepairTask.ConfigClass()
67 config.doInterpolate = False
68 task = RepairTask(config=config)
69 task.run(self.exposure)
70 self._checkRepaired(self.exposure)
72 def testLocalBackground(self):
73 """With binSize smaller than the image a background model is
74 subtracted before finding cosmic rays and added back afterwards."""
75 config = RepairTask.ConfigClass()
76 config.doInterpolate = False
77 config.cosmicray.background.binSize = 64
78 task = RepairTask(config=config)
79 task.run(self.exposure)
80 self._checkRepaired(self.exposure)
83class MemoryTester(lsst.utils.tests.MemoryTestCase):
84 pass
87def setup_module(module):
88 lsst.utils.tests.init()
91if __name__ == "__main__": 91 ↛ 92line 91 didn't jump to line 92 because the condition on line 91 was never true
92 lsst.utils.tests.init()
93 unittest.main()