Coverage for tests/test_calexpCutout.py: 19%

116 statements  

« prev     ^ index     » next       coverage.py v7.4.4, created at 2024-03-19 02:21 -0700

1# 

2# LSST Data Management System 

3# Copyright 2008-2016 AURA/LSST. 

4# 

5# This product includes software developed by the 

6# LSST Project (http://www.lsst.org/). 

7# 

8# This program is free software: you can redistribute it and/or modify 

9# it under the terms of the GNU General Public License as published by 

10# the Free Software Foundation, either version 3 of the License, or 

11# (at your option) any later version. 

12# 

13# This program is distributed in the hope that it will be useful, 

14# but WITHOUT ANY WARRANTY; without even the implied warranty of 

15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 

16# GNU General Public License for more details. 

17# 

18# You should have received a copy of the LSST License Statement and 

19# the GNU General Public License along with this program. If not, 

20# see <https://www.lsstcorp.org/LegalNotices/>. 

21# 

22"""Test configuration of CalexpCutoutTask and the run method. 

23 

24Run the task on one test image and perform various checks on the results 

25""" 

26import os 

27import random 

28import unittest 

29from astropy.coordinates import SkyCoord 

30from astropy.table import QTable 

31import astropy.units as u 

32 

33import lsst.utils 

34import lsst.utils.tests 

35from lsst.afw.image import ExposureF 

36from lsst.pipe.tasks.calexpCutout import CalexpCutoutTask 

37 

38random.seed(208241138) 

39 

40packageDir = lsst.utils.getPackageDir('pipe_tasks') 

41datadir = os.path.join(packageDir, 'tests', "data") 

42 

43 

44def make_data(bbox, wcs, border=100, ngood=13, nbad=7, nedge=3): 

45 dx, dy = bbox.getDimensions() 

46 data = {} 

47 

48 ident = [] 

49 pt = [] 

50 xspan = [] 

51 yspan = [] 

52 for i in range(ngood): 

53 x = random.random()*(dx - 2*border) + border 

54 y = random.random()*(dy - 2*border) + border 

55 sphpt = wcs.pixelToSky(x, y) 

56 pt.append(SkyCoord(sphpt.getRa().asDegrees(), sphpt.getDec().asDegrees(), 

57 frame='icrs', unit=u.deg)) 

58 ident.append((i+1)*u.dimensionless_unscaled) 

59 xspan.append(random.randint(13, 26)*u.dimensionless_unscaled) 

60 yspan.append(random.randint(13, 26)*u.dimensionless_unscaled) 

61 data['good'] = QTable([ident, pt, xspan, yspan], names=['id', 'position', 'xspan', 'yspan']) 

62 

63 ident = [] 

64 pt = [] 

65 xspan = [] 

66 yspan = [] 

67 for i in range(nbad): 

68 x = random.random()*(dx - 2*border) + border 

69 y = random.random()*(dy - 2*border) + border 

70 sphpt = wcs.pixelToSky(-x, -y) 

71 pt.append(SkyCoord(sphpt.getRa().asDegrees(), sphpt.getDec().asDegrees(), 

72 frame='icrs', unit=u.deg)) 

73 ident.append((i+1)*u.dimensionless_unscaled) 

74 xspan.append(random.randint(13, 26)*u.dimensionless_unscaled) 

75 yspan.append(random.randint(13, 26)*u.dimensionless_unscaled) 

76 data['bad'] = QTable([ident, pt, xspan, yspan], names=['id', 'position', 'xspan', 'yspan']) 

77 

78 ident = [] 

79 pt = [] 

80 xspan = [] 

81 yspan = [] 

82 for i in range(nedge): 

83 x_or_y = random.randint(0, 1) 

84 if x_or_y: 

85 x = random.random()*dx 

86 y = [0, dy][random.randint(0, 1)] 

87 else: 

88 x = [0, dx][random.randint(0, 1)] 

89 y = random.random()*dy 

90 

91 sphpt = wcs.pixelToSky(x, y) 

92 pt.append(SkyCoord(sphpt.getRa().asDegrees(), sphpt.getDec().asDegrees(), 

93 frame='icrs', unit=u.deg)) 

94 ident.append((i+1)*u.dimensionless_unscaled) 

95 xspan.append(random.randint(13, 26)*u.dimensionless_unscaled) 

96 yspan.append(random.randint(13, 26)*u.dimensionless_unscaled) 

97 data['edge'] = QTable([ident, pt, xspan, yspan], names=['id', 'position', 'xspan', 'yspan']) 

98 return data 

99 

100 

101class CalexpCutoutTestCase(lsst.utils.tests.TestCase): 

102 def setUp(self): 

103 self.exp = ExposureF.readFits(os.path.join(datadir, 'v695833-e0-c000-a00.sci.fits')) 

104 self.data = make_data(self.exp.getBBox(), self.exp.getWcs()) 

105 

106 def tearDown(self): 

107 del self.data 

108 del self.exp 

109 

110 def testCalexpCutout(self): 

111 config = CalexpCutoutTask.ConfigClass() 

112 task = CalexpCutoutTask(config=config) 

113 result = task.run(self.data['good'], self.exp) 

114 self.assertEqual(len(result.cutouts), len(self.data['good'])) 

115 indims = [(x, y) for x, y in zip(self.data['good']['xspan'], self.data['good']['yspan'])] 

116 outdims = [tuple(el.stamp_im.getDimensions()) for el in result.cutouts] 

117 self.assertEqual(indims, outdims) 

118 

119 # Test configuration of the max number of cutouts 

120 config.max_cutouts = 4 

121 task = CalexpCutoutTask(config=config) 

122 result = task.run(self.data['good'], self.exp) 

123 self.assertEqual(len(result.cutouts), task.config.max_cutouts) 

124 indims = [(x, y) for x, y in zip(self.data['good']['xspan'][:config.max_cutouts], 

125 self.data['good']['yspan'][:config.max_cutouts])] 

126 outdims = [tuple(el.stamp_im.getDimensions()) for el in result.cutouts[:config.max_cutouts]] 

127 self.assertEqual(indims, outdims) 

128 

129 def testEdge(self): 

130 # Currently edge cutouts are handled the same way 

131 # as cutouts completely outside the image. That 

132 # could change in the future 

133 config = CalexpCutoutTask.ConfigClass() 

134 task = CalexpCutoutTask(config=config) 

135 result = task.run(self.data['edge'], self.exp) 

136 # Cutouts on the edge should be skipped 

137 self.assertEqual(len(result.cutouts), 0) 

138 self.assertEqual(len(result.skipped_positions), len(self.data['edge'])) 

139 

140 config.skip_bad = False 

141 task = CalexpCutoutTask(config=config) 

142 # Should now raise for cutouts on the edge 

143 with self.assertRaises(ValueError): 

144 result = task.run(self.data['edge'], self.exp) 

145 

146 def testBad(self): 

147 config = CalexpCutoutTask.ConfigClass() 

148 task = CalexpCutoutTask(config=config) 

149 result = task.run(self.data['bad'], self.exp) 

150 # Cutouts outside the image should be skipped 

151 self.assertEqual(len(result.cutouts), 0) 

152 self.assertEqual(len(result.skipped_positions), len(self.data['bad'])) 

153 

154 config.skip_bad = False 

155 task = CalexpCutoutTask(config=config) 

156 # Should now raise for cutouts outside the image 

157 with self.assertRaises(ValueError): 

158 result = task.run(self.data['bad'], self.exp) 

159 

160 def testBadColumns(self): 

161 config = CalexpCutoutTask.ConfigClass() 

162 task = CalexpCutoutTask(config=config) 

163 table = QTable([[], []], names=['one', 'two']) 

164 with self.assertRaises(ValueError): 

165 result = task.run(table, self.exp) # noqa 

166 

167 

168class MemoryTestCase(lsst.utils.tests.MemoryTestCase): 

169 pass 

170 

171 

172def setup_module(module): 

173 lsst.utils.tests.init() 

174 

175 

176if __name__ == "__main__": 176 ↛ 177line 176 didn't jump to line 177, because the condition on line 176 was never true

177 lsst.utils.tests.init() 

178 unittest.main()