Coverage for tests/test_dynamicDetection.py: 31%
66 statements
« prev ^ index » next coverage.py v6.5.0, created at 2023-03-11 02:22 -0800
« prev ^ index » next coverage.py v6.5.0, created at 2023-03-11 02:22 -0800
1import unittest
2import numpy as np
4import lsst.utils.tests
6from lsst.geom import Box2I, Point2I, Point2D, Extent2I, SpherePoint, degrees
7from lsst.afw.geom import makeCdMatrix, makeSkyWcs
8from lsst.afw.image import PARENT
9from lsst.afw.table import SourceTable
10from lsst.meas.algorithms import DynamicDetectionTask
11from lsst.meas.algorithms.testUtils import plantSources
14class DynamicDetectionTest(lsst.utils.tests.TestCase):
15 def setUp(self):
16 xy0 = Point2I(12345, 67890) # xy0 for image
17 dims = Extent2I(2345, 2345) # Dimensions of image
18 box = Box2I(xy0, dims) # Bounding box of image
19 sigma = 3.21 # PSF sigma
20 buffer = 4.0 # Buffer for star centers around edge
21 nSigmaForKernel = 5.0 # Number of PSF sigmas for kernel
22 sky = 12345.6 # Sky level
23 numStars = 100 # Number of stars
24 noise = np.sqrt(sky)*np.pi*sigma**2 # Poisson noise per PSF
25 faint = 1.0*noise # Faintest level for star fluxes
26 bright = 100.0*noise # Brightest level for star fluxes
27 starBox = Box2I(box) # Area on image in which we can put star centers
28 starBox.grow(-int(buffer*sigma))
29 scale = 1.0e-5*degrees # Pixel scale
31 np.random.seed(12345)
32 stars = [(xx, yy, ff, sigma) for xx, yy, ff in
33 zip(np.random.uniform(starBox.getMinX(), starBox.getMaxX(), numStars),
34 np.random.uniform(starBox.getMinY(), starBox.getMaxY(), numStars),
35 np.linspace(faint, bright, numStars))]
36 self.exposure = plantSources(box, 2*int(nSigmaForKernel*sigma) + 1, sky, stars, True)
37 self.exposure.setWcs(makeSkyWcs(crpix=Point2D(0, 0),
38 crval=SpherePoint(0, 0, degrees),
39 cdMatrix=makeCdMatrix(scale=scale)))
41 # Make a large area of extra background; we should be robust against it
42 # Unfortunately, some tuning is required here to get something challenging but not impossible:
43 # * A very large box will cause failures because the "extra" and the "normal" are reversed.
44 # * A small box will not be challenging because it's simple to clip out.
45 # * A large value will cause failures because it produces large edges in background-subtrction that
46 # broaden flux distributions.
47 # * A small value will not be challenging because it has little effect.
48 extraBox = Box2I(xy0 + Extent2I(345, 456), Extent2I(1234, 1234)) # Box for extra background
49 extraValue = 0.5*noise # Extra background value to add in
50 self.exposure.image[extraBox, PARENT] += extraValue
52 self.config = DynamicDetectionTask.ConfigClass()
53 self.config.skyObjects.nSources = 300
54 self.config.reEstimateBackground = False
55 self.config.doTempWideBackground = True
56 self.config.thresholdType = "pixel_stdev"
58 # Relative tolerance for tweak factor
59 # Not sure why this isn't smaller; maybe due to use of Poisson instead of Gaussian noise?
60 self.rtol = 0.1
62 def tearDown(self):
63 del self.exposure
65 def check(self, expectFactor):
66 schema = SourceTable.makeMinimalSchema()
67 task = DynamicDetectionTask(config=self.config, schema=schema)
68 table = SourceTable.make(schema)
70 results = task.run(table, self.exposure, expId=12345)
71 self.assertFloatsAlmostEqual(results.factor, expectFactor, rtol=self.rtol)
73 def testVanilla(self):
74 """Dynamic detection used as normal detection"""
75 self.check(1.0)
77 def testDynamic(self):
78 """Modify the variance plane, and see if the task is able to determine what we did"""
79 factor = 2.0
80 self.exposure.maskedImage.variance /= factor
81 self.check(1.0/np.sqrt(factor))
83 def testNoWcs(self):
84 """Check that dynamic detection runs when the exposure wcs is None"""
85 self.exposure.setWcs(None)
86 self.check(1.0)
88 def testNoSources(self):
89 self.config.skyObjects.nSources = self.config.minNumSources - 1
90 self.check(1.0)
93class TestMemory(lsst.utils.tests.MemoryTestCase):
94 pass
97def setup_module(module):
98 lsst.utils.tests.init()
101if __name__ == "__main__": 101 ↛ 102line 101 didn't jump to line 102, because the condition on line 101 was never true
102 import sys
103 setup_module(sys.modules['__main__'])
104 unittest.main()