Coverage for tests/test_readFitsCatalog.py: 22%
100 statements
« prev ^ index » next coverage.py v7.4.4, created at 2024-03-26 10:23 +0000
« prev ^ index » next coverage.py v7.4.4, created at 2024-03-26 10:23 +0000
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#
24import os
25import unittest
27import numpy as np
28from astropy.io import fits
29from astropy.table import Table
31from lsst.meas.algorithms.readFitsCatalogTask import ReadFitsCatalogTask
32from lsst.meas.algorithms.convertReferenceCatalog import _addExtraColumnsToSchema
33import lsst.afw.table
34import lsst.utils.tests
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")
46def makeFitsTable():
47 """Create a fits file containing two tables"""
48 hdu0 = fits.PrimaryHDU()
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)
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)
73 # add an image HDU to test that these are not treated as tables
74 hdu3 = fits.ImageHDU(data=np.zeros([5, 5]))
76 foo = fits.HDUList([hdu0, hdu1, hdu2, hdu3])
77 return foo
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)
86class ReadFitsCatalogTaskTestCase(lsst.utils.tests.TestCase):
87 """Test ReadFitsCatalogTask"""
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()
94 self.fitsTable = fitsTable
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)
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 )
121 def testHDU1GivenNames(self):
122 """Test the data in HDU 1 with some column renaming
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])
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])
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 )
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)
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)
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)
202class TestMemory(lsst.utils.tests.MemoryTestCase):
203 pass
206def setup_module(module):
207 lsst.utils.tests.init()
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()