Coverage for tests/test_fits.py: 20%
85 statements
« prev ^ index » next coverage.py v7.5.0, created at 2024-05-01 15:48 -0700
« prev ^ index » next coverage.py v7.5.0, created at 2024-05-01 15:48 -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#
23import os
24import unittest
26from lsst.daf.base import PropertyList
28import lsst.afw.fits
29import lsst.utils.tests
31testPath = os.path.abspath(os.path.dirname(__file__))
34class FitsTestCase(lsst.utils.tests.TestCase):
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"]
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
51 def testSimpleIO(self):
52 """Check that a simple header can be written and read back."""
54 expected = {
55 "ASTRING": "Test String",
56 "ANUNDEF": None,
57 "AFLOAT": 3.1415,
58 "ANINT": 42,
59 }
61 header = PropertyList()
62 for k, v in expected.items():
63 header[k] = v
65 output = self.writeAndRead(header)
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"]
74 self.assertEqual(output.toDict(), header.toDict())
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 )
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)
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)
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)
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)
104 self.assertEqual("---- Checksums ----", metadata["COMMENT"])
105 self.assertNotIn("", metadata, "Check empty strings as keys")
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"]
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)
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])
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")
146 # parent.fits has 2 HDUs.
147 with self.assertRaises(lsst.afw.fits.FitsError):
148 fts.setHdu(5)
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)
155 def testNamedHeaderNavigate(self):
156 testfile = os.path.join(testPath, "data", "multi_extension_metadata.fits")
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)
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)
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")
172class TestMemory(lsst.utils.tests.MemoryTestCase):
173 pass
176def setup_module(module):
177 lsst.utils.tests.init()
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()