Coverage for tests/test_readFitsCatalog.py: 22%

100 statements  

« prev     ^ index     » next       coverage.py v7.5.0, created at 2024-05-04 02:40 -0700

1# 

2# LSST Data Management System 

3# 

4# Copyright 2008-2016 AURA/LSST. 

5# 

6# This product includes software developed by the 

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

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 LSST License Statement and 

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

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

22# 

23 

24import os 

25import unittest 

26 

27import numpy as np 

28from astropy.io import fits 

29from astropy.table import Table 

30 

31from lsst.meas.algorithms.readFitsCatalogTask import ReadFitsCatalogTask 

32from lsst.meas.algorithms.convertReferenceCatalog import _addExtraColumnsToSchema 

33import lsst.afw.table 

34import lsst.utils.tests 

35 

36# If you want to update the FITS table used for this test: 

37# - modify makeFitsTable to create the table as you want it 

38# - set SaveFitsTable = True 

39# - sun the test once to create the new file 

40# - set SaveFitsTable = False again 

41SaveFitsTable = False # construct and save a new FITS table file? 

42TestDir = os.path.dirname(__file__) 

43FitsPath = os.path.join(TestDir, "data", "testReadFitsCatalog.fits") 

44 

45 

46def makeFitsTable(): 

47 """Create a fits file containing two tables""" 

48 hdu0 = fits.PrimaryHDU() 

49 

50 # table for HDU 1 

51 cols1 = [ 

52 fits.Column(name='name', format='10A', array=np.array(["object 1", "object 2"])), 

53 fits.Column(name='ra', format='E', array=[10, 5]), 

54 fits.Column(name='dec', format='E', array=[-5, 45]), 

55 fits.Column(name='counts', format='J', array=[1000, 2000]), 

56 fits.Column(name='flux', format='D', array=[1.1, 2.2]), 

57 fits.Column(name='resolved', format='L', array=[True, False]), 

58 ] 

59 hdu1 = fits.BinTableHDU.from_columns(fits.ColDefs(cols1), character_as_bytes=True) 

60 

61 # table for HDU 2, 

62 cols2 = [ 

63 fits.Column(name='name', format='10A', array=["object 3", "object 4"]), 

64 fits.Column(name='ra', format='E', array=[16, 3]), 

65 fits.Column(name='dec', format='E', array=[75, -34]), 

66 fits.Column(name='resolved', format='L', array=[False, True]), 

67 fits.Column(name='flux', format='D', array=[10.1, 20.2]), 

68 fits.Column(name='counts', format='J', array=[15000, 22000]), 

69 fits.Column(name='other', format='D', array=[11, 12]), 

70 ] 

71 hdu2 = fits.BinTableHDU.from_columns(fits.ColDefs(cols2), character_as_bytes=True) 

72 

73 # add an image HDU to test that these are not treated as tables 

74 hdu3 = fits.ImageHDU(data=np.zeros([5, 5])) 

75 

76 foo = fits.HDUList([hdu0, hdu1, hdu2, hdu3]) 

77 return foo 

78 

79 

80if SaveFitsTable: 80 ↛ 81line 80 didn't jump to line 81, because the condition on line 80 was never true

81 print("Warning: writing a new FITS file; to stop this set SaveFitsTable = False") 

82 fitsTable = makeFitsTable() 

83 fitsTable.writeto(FitsPath, clobber=True) 

84 

85 

86class ReadFitsCatalogTaskTestCase(lsst.utils.tests.TestCase): 

87 """Test ReadFitsCatalogTask""" 

88 

89 def setUp(self): 

90 fitsTable = makeFitsTable() 

91 self.arr1 = Table(fitsTable[1].data).as_array() 

92 self.arr2 = Table(fitsTable[2].data).as_array() 

93 

94 self.fitsTable = fitsTable 

95 

96 def testHDU1DefaultNames(self): 

97 """Test the data in HDU 1, loading all columns without renaming 

98 """ 

99 task = ReadFitsCatalogTask() 

100 table = task.run(FitsPath) 

101 for name in self.arr1.dtype.names: 

102 self.assertIn(name, table.dtype.names) 

103 if name == "name": 

104 np.testing.assert_array_equal(self.arr1[name].astype(str), table[name]) 

105 else: 

106 np.testing.assert_array_equal(self.arr1[name], table[name]) 

107 self.assertEqual(len(table), 2) 

108 

109 schema = lsst.afw.table.SimpleTable.makeMinimalSchema() 

110 keyMap = {} 

111 _addExtraColumnsToSchema(schema, table.dtype, table.dtype.names, keyMap) 

112 self.assertEqual( 

113 set(keyMap.keys()), 

114 set(table.dtype.names), 

115 ) 

116 self.assertEqual( 

117 set(schema.getNames()), 

118 set(table.dtype.names).union(set(["id", "coord_ra", "coord_dec"])), 

119 ) 

120 

121 def testHDU1GivenNames(self): 

122 """Test the data in HDU 1 with some column renaming 

123 

124 All columns should be in the same order; those that are renamed should have 

125 their new name, and the rest should have their original name. 

126 """ 

127 column_map = { 

128 "name": "source", 

129 "ra": "ra_deg", 

130 "dec": "dec_deg", 

131 } 

132 config = ReadFitsCatalogTask.ConfigClass() 

133 config.column_map = column_map 

134 self.assertEqual(config.hdu, 1) 

135 task = ReadFitsCatalogTask(config=config) 

136 arr = task.run(FitsPath) 

137 self.assertEqual(len(Table(arr).columns), len(Table(self.arr1).columns)) 

138 for inname, outname in zip(self.arr1.dtype.names, arr.dtype.names): 

139 des_outname = column_map.get(inname, inname) 

140 self.assertEqual(outname, des_outname) 

141 if inname == "name": 

142 # Special check for strings. 

143 np.testing.assert_array_equal(self.arr1[inname].astype(str), arr[outname].astype(str)) 

144 else: 

145 np.testing.assert_array_equal(self.arr1[inname], arr[outname]) 

146 

147 def testHDU2(self): 

148 """Test reading HDU 2 with original order""" 

149 config = ReadFitsCatalogTask.ConfigClass() 

150 config.hdu = 2 

151 task = ReadFitsCatalogTask(config=config) 

152 arr = task.run(FitsPath) 

153 for name in self.arr1.dtype.names: 

154 self.assertIn(name, arr.dtype.names) 

155 if name == "name": 

156 np.testing.assert_array_equal(self.arr2[name].astype(str), arr[name]) 

157 else: 

158 np.testing.assert_array_equal(self.arr2[name], arr[name]) 

159 

160 schema = lsst.afw.table.SimpleTable.makeMinimalSchema() 

161 keyMap = {} 

162 _addExtraColumnsToSchema(schema, arr.dtype, arr.dtype.names, keyMap) 

163 self.assertEqual( 

164 set(keyMap.keys()), 

165 set(arr.dtype.names), 

166 ) 

167 self.assertEqual( 

168 set(schema.getNames()), 

169 set(arr.dtype.names).union(set(["id", "coord_ra", "coord_dec"])), 

170 ) 

171 

172 def testBadPath(self): 

173 """Test that an invalid path causes an error""" 

174 task = ReadFitsCatalogTask() 

175 badPath = "does/not/exists.garbage" 

176 with self.assertRaises(IOError): 

177 task.run(badPath) 

178 

179 def testBadColumnName(self): 

180 """Test that non-existent columns in column_map cause an error""" 

181 config = ReadFitsCatalogTask.ConfigClass() 

182 for badColNames in ( 

183 ["name", "ra", "dec", "counts", "flux", "resolved", "other"], # "other" only in hdu 2 

184 ["name", "ra", "dec", "counts", "flux", "invalidname"], 

185 ["invalid1"], 

186 ): 

187 config.column_map = dict((name, "col %s" % (i,)) for i, name in enumerate(badColNames)) 

188 task = ReadFitsCatalogTask(config=config) 

189 with self.assertRaises(RuntimeError): 

190 task.run(FitsPath) 

191 

192 def testBadHdu(self): 

193 """Test that non-existent HDUs cause an error""" 

194 for badHdu in [0, 3, 4]: 

195 config = ReadFitsCatalogTask.ConfigClass() 

196 config.hdu = badHdu 

197 task = ReadFitsCatalogTask(config=config) 

198 with self.assertRaises(Exception): 

199 task.run(FitsPath) 

200 

201 

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

203 pass 

204 

205 

206def setup_module(module): 

207 lsst.utils.tests.init() 

208 

209 

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

211 lsst.utils.tests.init() 

212 unittest.main()