|
| 1 | +import unittest |
| 2 | + |
| 3 | +import lsst.utils.tests |
| 4 | +import numpy as np |
| 5 | +from lsst.afw.geom import makeCdMatrix, makeSkyWcs |
| 6 | +from lsst.afw.table import SourceTable |
| 7 | +from lsst.geom import Box2I, Extent2I, Point2D, Point2I, SpherePoint, degrees |
| 8 | +from lsst.meas.algorithms import AdaptiveThresholdDetectionTask |
| 9 | +from lsst.meas.algorithms.testUtils import plantSources |
| 10 | + |
| 11 | + |
| 12 | +class AdaptiveThresholdDetectionTest(lsst.utils.tests.TestCase): |
| 13 | + def setUp(self): |
| 14 | + xy0 = Point2I(12345, 67890) # xy0 for image |
| 15 | + dims = Extent2I(2345, 2345) # Dimensions of image |
| 16 | + self.box = Box2I(xy0, dims) # Bounding box of image |
| 17 | + self.sigma = 3.21 # PSF sigma |
| 18 | + self.nSigmaForKernel = 5.0 # Number of PSF sigmas for kernel |
| 19 | + self.sky = 12345.6 # Sky level |
| 20 | + noise = np.sqrt(self.sky)*np.pi*self.sigma**2 # Poisson noise per PSF |
| 21 | + self.faint = 1.0*noise # Faintest level for star fluxes |
| 22 | + self.bright = 100.0*noise # Brightest level for star fluxes |
| 23 | + self.starBox = Box2I(self.box) # Area on image in which we can put star centers |
| 24 | + starBoxBuffer = 4.0 # Buffer for star centers around edge |
| 25 | + self.starBox.grow(-int(starBoxBuffer*self.sigma)) |
| 26 | + self.scale = 1.0e-5*degrees # Pixel scale |
| 27 | + self.config = AdaptiveThresholdDetectionTask.ConfigClass() |
| 28 | + self.rtol = 1e-4 |
| 29 | + |
| 30 | + def makeMockExposure(self, numStars=300): |
| 31 | + rng = np.random.Generator(np.random.MT19937(12345)) |
| 32 | + stars = [(xx, yy, ff, self.sigma) for xx, yy, ff in |
| 33 | + zip(rng.uniform(self.starBox.getMinX(), self.starBox.getMaxX(), numStars), |
| 34 | + rng.uniform(self.starBox.getMinY(), self.starBox.getMaxY(), numStars), |
| 35 | + np.linspace(self.faint, self.bright, numStars))] |
| 36 | + exposure = plantSources(self.box, 2*int(self.nSigmaForKernel*self.sigma) + 1, self.sky, stars, True) |
| 37 | + exposure.setWcs(makeSkyWcs(crpix=Point2D(0, 0), |
| 38 | + crval=SpherePoint(0, 0, degrees), |
| 39 | + cdMatrix=makeCdMatrix(scale=self.scale))) |
| 40 | + return exposure |
| 41 | + |
| 42 | + def tearDown(self): |
| 43 | + # del self.exposure |
| 44 | + del self.config |
| 45 | + |
| 46 | + def check(self, expectFactor, initialThreshold=None): |
| 47 | + schema = SourceTable.makeMinimalSchema() |
| 48 | + table = SourceTable.make(schema) |
| 49 | + task = AdaptiveThresholdDetectionTask(config=self.config) |
| 50 | + results = task.run(table, self.exposure, initialThreshold=initialThreshold) |
| 51 | + self.assertFloatsAlmostEqual(results.thresholdValue, expectFactor, rtol=self.rtol) |
| 52 | + |
| 53 | + def testUncrowded(self): |
| 54 | + """Add sparse-ish numbers of stars. |
| 55 | + """ |
| 56 | + self.exposure = self.makeMockExposure() |
| 57 | + self.check(5.0) |
| 58 | + self.exposure = self.makeMockExposure(numStars=100) |
| 59 | + self.check(5.0) |
| 60 | + |
| 61 | + def testCrowded(self): |
| 62 | + """Add enough stars to be considered crowded and test adjusting |
| 63 | + initial detection threshold. |
| 64 | + """ |
| 65 | + self.exposure = self.makeMockExposure(numStars=8000) |
| 66 | + self.check(23.8) |
| 67 | + self.exposure = self.makeMockExposure(numStars=8000) |
| 68 | + self.check(50.0, initialThreshold=50.0) |
| 69 | + self.exposure = self.makeMockExposure(numStars=25000) |
| 70 | + self.check(173.4, initialThreshold=20.0) |
| 71 | + |
| 72 | + |
| 73 | +class TestMemory(lsst.utils.tests.MemoryTestCase): |
| 74 | + pass |
| 75 | + |
| 76 | + |
| 77 | +def setup_module(module): |
| 78 | + lsst.utils.tests.init() |
| 79 | + |
| 80 | + |
| 81 | +if __name__ == "__main__": |
| 82 | + import sys |
| 83 | + setup_module(sys.modules['__main__']) |
| 84 | + unittest.main() |
0 commit comments