Coverage for tests/test_fits.py: 20%

81 statements  

« prev     ^ index     » next       coverage.py v6.5.0, created at 2022-11-18 02:24 -0800

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 testReadUndefined(self): 

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

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

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

80 

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

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

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

84 

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

86 # was undefined 

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

88 

89 def testReadBlankKeywordComment(self): 

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

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

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

93 

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

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

96 

97 def testIgnoreKeywords(self): 

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

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

100 notAtAll = [ 

101 # FITS core keywords 

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

103 # FITS compression keywords 

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

105 "ZNAXIS", "ZTILE", "ZNAME", "ZVAL", "ZQUANTIZ", 

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

107 "DATASUM", "CHECKSUM", 

108 ] 

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

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

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

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

113 

114 header = PropertyList() 

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

116 header.add(key, ii) 

117 metadata = self.writeAndRead(header) 

118 for key in self.single: 

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

120 for key in notAtAll: 

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

122 for key in others: 

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

124 

125 def testUndefinedVector(self): 

126 header = PropertyList() 

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

128 metadata = self.writeAndRead(header) 

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

130 

131 def test_ticket_dm_36207(self): 

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

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

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

135 

136 # parent.fits has 2 HDUs. 

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

138 fts.setHdu(5) 

139 

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

141 fts.setHdu(0) 

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

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

144 

145 def testNamedHeaderNavigate(self): 

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

147 

148 # load metadata from the extra table header 

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

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

151 self.assertTrue("FVALUE" in md_extra_tab) 

152 

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

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

155 self.assertTrue("BLORP" in md_extra_im) 

156 

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

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

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

160 

161 

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

163 pass 

164 

165 

166def setup_module(module): 

167 lsst.utils.tests.init() 

168 

169 

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

171 import sys 

172 setup_module(sys.modules[__name__]) 

173 unittest.main()