Coverage for tests/test_fits.py: 20%

85 statements  

« prev     ^ index     » next       coverage.py v7.4.4, created at 2024-03-23 03:25 -0700

1# 

2# LSST Data Management System 

3# Copyright 2017 LSST Corporation. 

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 <http://www.lsstcorp.org/LegalNotices/>. 

21# 

22 

23import os 

24import unittest 

25 

26from lsst.daf.base import PropertyList 

27 

28import lsst.afw.fits 

29import lsst.utils.tests 

30 

31testPath = os.path.abspath(os.path.dirname(__file__)) 

32 

33 

34class FitsTestCase(lsst.utils.tests.TestCase): 

35 

36 def setUp(self): 

37 # May appear only once in the FITS file (because cfitsio will insist on putting them there) 

38 self.single = ["SIMPLE", "BITPIX", "EXTEND", "NAXIS"] 

39 

40 def writeAndRead(self, header): 

41 """Write the supplied header and read it back again. 

42 """ 

43 fitsFile = lsst.afw.fits.MemFileManager() 

44 with lsst.afw.fits.Fits(fitsFile, "w") as fits: 

45 fits.createEmpty() 

46 fits.writeMetadata(header) 

47 with lsst.afw.fits.Fits(fitsFile, "r") as fits: 

48 metadata = fits.readMetadata() 

49 return metadata 

50 

51 def testSimpleIO(self): 

52 """Check that a simple header can be written and read back.""" 

53 

54 expected = { 

55 "ASTRING": "Test String", 

56 "ANUNDEF": None, 

57 "AFLOAT": 3.1415, 

58 "ANINT": 42, 

59 } 

60 

61 header = PropertyList() 

62 for k, v in expected.items(): 

63 header[k] = v 

64 

65 output = self.writeAndRead(header) 

66 

67 # Remove keys added by cfitsio 

68 for k in self.single: 

69 if k in output: 

70 del output[k] 

71 if "COMMENT" in output: 

72 del output["COMMENT"] 

73 

74 self.assertEqual(output.toDict(), header.toDict()) 

75 

76 def testReadEmptyValue(self): 

77 """Read a header with an extended comment including an empty value.""" 

78 testFile = os.path.join(testPath, "data", "ticket42210.fits") 

79 metadata = lsst.afw.fits.readMetadata(testFile) 

80 self.assertEqual( 

81 metadata.getComment("TTYPE251"), 

82 "ellipse used to set the pixel region for the final fit (before " 

83 "applying bad pixel mask)" 

84 ) 

85 

86 def testReadUndefined(self): 

87 """Read a header with some undefined values that might override.""" 

88 testFile = os.path.join(testPath, "data", "ticket18864.fits") 

89 metadata = lsst.afw.fits.readMetadata(testFile) 

90 

91 # Neither of these should be arrays despite having doubled keywords 

92 # The first value for ADC-STR should override the second undef value 

93 self.assertAlmostEqual(metadata.getScalar("ADC-STR"), 22.01) 

94 

95 # The value for DOM-WND should be the second value since the first 

96 # was undefined 

97 self.assertAlmostEqual(metadata.getScalar("DOM-WND"), 4.8) 

98 

99 def testReadBlankKeywordComment(self): 

100 """Read a header that uses blank keyword comments.""" 

101 testFile = os.path.join(testPath, "data", "ticket20143.fits") 

102 metadata = lsst.afw.fits.readMetadata(testFile) 

103 

104 self.assertEqual("---- Checksums ----", metadata["COMMENT"]) 

105 self.assertNotIn("", metadata, "Check empty strings as keys") 

106 

107 def testIgnoreKeywords(self): 

108 """Check that certain keywords are ignored in read/write of headers""" 

109 # May not appear at all in the FITS file (cfitsio doesn't write these by default) 

110 notAtAll = [ 

111 # FITS core keywords 

112 "GCOUNT", "PCOUNT", "XTENSION", "BSCALE", "BZERO", "TZERO", "TSCAL", 

113 # FITS compression keywords 

114 "ZBITPIX", "ZIMAGE", "ZCMPTYPE", "ZSIMPLE", "ZEXTEND", "ZBLANK", "ZDATASUM", "ZHECKSUM", 

115 "ZNAXIS", "ZTILE", "ZNAME", "ZVAL", "ZQUANTIZ", 

116 # Not essential these be excluded, but will prevent fitsverify warnings 

117 "DATASUM", "CHECKSUM", 

118 ] 

119 # Additional keywords to check; these should go straight through 

120 # Some of these are longer/shorter versions of strings above, 

121 # to test that the checks for just the start of strings is working. 

122 others = ["FOOBAR", "SIMPLETN", "DATASUMX", "NAX", "SIM"] 

123 

124 header = PropertyList() 

125 for ii, key in enumerate(self.single + notAtAll + others): 

126 header.add(key, ii) 

127 metadata = self.writeAndRead(header) 

128 for key in self.single: 

129 self.assertEqual(metadata.valueCount(key), 1, key) 

130 for key in notAtAll: 

131 self.assertEqual(metadata.valueCount(key), 0, key) 

132 for key in others: 

133 self.assertEqual(metadata.valueCount(key), 1, key) 

134 

135 def testUndefinedVector(self): 

136 header = PropertyList() 

137 header.set("FOO", [None, None]) 

138 metadata = self.writeAndRead(header) 

139 self.assertEqual(metadata.getArray("FOO"), [None, None]) 

140 

141 def test_ticket_dm_36207(self): 

142 # test whether moving to invalid HDU and then moving back throws or not 

143 testfile = os.path.join(testPath, "data", "parent.fits") 

144 fts = lsst.afw.fits.Fits(testfile, "r") 

145 

146 # parent.fits has 2 HDUs. 

147 with self.assertRaises(lsst.afw.fits.FitsError): 

148 fts.setHdu(5) 

149 

150 # check that we can move back to primary HDU and pull out a header 

151 fts.setHdu(0) 

152 mdattest = fts.readMetadata()["COMMENT"] 

153 self.assertIn("and Astrophysics', volume 376, page 359;", mdattest) 

154 

155 def testNamedHeaderNavigate(self): 

156 testfile = os.path.join(testPath, "data", "multi_extension_metadata.fits") 

157 

158 # load metadata from the extra table header 

159 md_extra_tab = lsst.afw.fits.readMetadata(testfile, hduName="EXTRA_TAB") 

160 # assert the value we put in is in the read metadata 

161 self.assertTrue("FVALUE" in md_extra_tab) 

162 

163 # load metadata from the extra image header, do same test 

164 md_extra_im = lsst.afw.fits.readMetadata(testfile, hduName="EXTRA_IM") 

165 self.assertTrue("BLORP" in md_extra_im) 

166 

167 # now try to load a non-existent named HDU and check that we throw 

168 with self.assertRaises(lsst.afw.fits.FitsError): 

169 lsst.afw.fits.readMetadata(testfile, hduName="CORDON_BLEAU") 

170 

171 

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

173 pass 

174 

175 

176def setup_module(module): 

177 lsst.utils.tests.init() 

178 

179 

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

181 import sys 

182 setup_module(sys.modules[__name__]) 

183 unittest.main()