Coverage for tests/test_dynamicDetection.py: 31%

66 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2023-01-13 03:11 -0800

1import unittest 

2import numpy as np 

3 

4import lsst.utils.tests 

5 

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 

12 

13 

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 

30 

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))) 

40 

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 

51 

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" 

57 

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 

61 

62 def tearDown(self): 

63 del self.exposure 

64 

65 def check(self, expectFactor): 

66 schema = SourceTable.makeMinimalSchema() 

67 task = DynamicDetectionTask(config=self.config, schema=schema) 

68 table = SourceTable.make(schema) 

69 

70 results = task.run(table, self.exposure, expId=12345) 

71 self.assertFloatsAlmostEqual(results.factor, expectFactor, rtol=self.rtol) 

72 

73 def testVanilla(self): 

74 """Dynamic detection used as normal detection""" 

75 self.check(1.0) 

76 

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)) 

82 

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) 

87 

88 def testNoSources(self): 

89 self.config.skyObjects.nSources = self.config.minNumSources - 1 

90 self.check(1.0) 

91 

92 

93class TestMemory(lsst.utils.tests.MemoryTestCase): 

94 pass 

95 

96 

97def setup_module(module): 

98 lsst.utils.tests.init() 

99 

100 

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()