Coverage for tests/test_readFitsCatalog.py: 25%
92 statements
« prev ^ index » next coverage.py v7.4.0, created at 2023-12-29 11:22 +0000
« prev ^ index » next coverage.py v7.4.0, created at 2023-12-29 11:22 +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 self.assertTrue(np.array_equal(self.arr1, table))
102 self.assertEqual(len(table), 2)
104 schema = lsst.afw.table.SimpleTable.makeMinimalSchema()
105 keyMap = {}
106 _addExtraColumnsToSchema(schema, table.dtype, table.dtype.names, keyMap)
107 self.assertEqual(
108 set(keyMap.keys()),
109 set(table.dtype.names),
110 )
111 self.assertEqual(
112 set(schema.getNames()),
113 set(table.dtype.names).union(set(["id", "coord_ra", "coord_dec"])),
114 )
116 def testHDU1GivenNames(self):
117 """Test the data in HDU 1 with some column renaming
119 All columns should be in the same order; those that are renamed should have
120 their new name, and the rest should have their original name.
121 """
122 column_map = {
123 "name": "source",
124 "ra": "ra_deg",
125 "dec": "dec_deg",
126 }
127 config = ReadFitsCatalogTask.ConfigClass()
128 config.column_map = column_map
129 self.assertEqual(config.hdu, 1)
130 task = ReadFitsCatalogTask(config=config)
131 arr = task.run(FitsPath)
132 self.assertEqual(len(Table(arr).columns), len(Table(self.arr1).columns))
133 for inname, outname in zip(self.arr1.dtype.names, arr.dtype.names):
134 des_outname = column_map.get(inname, inname)
135 self.assertEqual(outname, des_outname)
136 if inname == "name":
137 # Special check for strings.
138 np.testing.assert_array_equal(self.arr1[inname].astype(str), arr[outname].astype(str))
139 else:
140 np.testing.assert_array_equal(self.arr1[inname], arr[outname])
142 def testHDU2(self):
143 """Test reading HDU 2 with original order"""
144 config = ReadFitsCatalogTask.ConfigClass()
145 config.hdu = 2
146 task = ReadFitsCatalogTask(config=config)
147 arr = task.run(FitsPath)
148 self.assertTrue(np.array_equal(self.arr2, arr))
150 schema = lsst.afw.table.SimpleTable.makeMinimalSchema()
151 keyMap = {}
152 _addExtraColumnsToSchema(schema, arr.dtype, arr.dtype.names, keyMap)
153 self.assertEqual(
154 set(keyMap.keys()),
155 set(arr.dtype.names),
156 )
157 self.assertEqual(
158 set(schema.getNames()),
159 set(arr.dtype.names).union(set(["id", "coord_ra", "coord_dec"])),
160 )
162 def testBadPath(self):
163 """Test that an invalid path causes an error"""
164 task = ReadFitsCatalogTask()
165 badPath = "does/not/exists.garbage"
166 with self.assertRaises(IOError):
167 task.run(badPath)
169 def testBadColumnName(self):
170 """Test that non-existent columns in column_map cause an error"""
171 config = ReadFitsCatalogTask.ConfigClass()
172 for badColNames in (
173 ["name", "ra", "dec", "counts", "flux", "resolved", "other"], # "other" only in hdu 2
174 ["name", "ra", "dec", "counts", "flux", "invalidname"],
175 ["invalid1"],
176 ):
177 config.column_map = dict((name, "col %s" % (i,)) for i, name in enumerate(badColNames))
178 task = ReadFitsCatalogTask(config=config)
179 with self.assertRaises(RuntimeError):
180 task.run(FitsPath)
182 def testBadHdu(self):
183 """Test that non-existent HDUs cause an error"""
184 for badHdu in [0, 3, 4]:
185 config = ReadFitsCatalogTask.ConfigClass()
186 config.hdu = badHdu
187 task = ReadFitsCatalogTask(config=config)
188 with self.assertRaises(Exception):
189 task.run(FitsPath)
192class TestMemory(lsst.utils.tests.MemoryTestCase):
193 pass
196def setup_module(module):
197 lsst.utils.tests.init()
200if __name__ == "__main__": 200 ↛ 201line 200 didn't jump to line 201, because the condition on line 200 was never true
201 lsst.utils.tests.init()
202 unittest.main()