Coverage for tests/test_assemble.py: 31%
83 statements
« prev ^ index » next coverage.py v7.3.2, created at 2023-10-25 17:06 +0000
« prev ^ index » next coverage.py v7.3.2, created at 2023-10-25 17:06 +0000
1# This file is part of obs_lsst.
2#
3# Developed for the LSST Data Management System.
4# This product includes software developed by the LSST Project
5# (http://www.lsst.org).
6# See the COPYRIGHT file at the top-level directory of this distribution
7# for details of code ownership.
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 GNU General Public License
20# along with this program. If not, see <http://www.gnu.org/licenses/>.
22import numpy
23import os
24import sys
25import unittest
27import lsst.utils.tests
28from lsst.utils import getPackageDir
29from lsst.daf.butler import Butler
30from lsst.afw.cameraGeom import Detector
31from lsst.afw.image import ImageFitsReader
32import lsst.obs.base.yamlCamera as yamlCamera
33from lsst.ip.isr import AssembleCcdTask
35from lsst.obs.lsst.utils import readRawFile
37PACKAGE_DIR = getPackageDir("obs_lsst")
38TESTDIR = os.path.dirname(__file__)
39LATISS_DATA_ROOT = os.path.join(PACKAGE_DIR, 'data', 'input', 'latiss')
40BOT_DATA_ROOT = os.path.join(TESTDIR, 'data', 'input')
41E2V_DATA_ID = {'raft': 'R22', 'name_in_raft': 'S11', 'exposure': 3019103101985, 'instrument': 'LSSTCam'}
42ITL_DATA_ID = {'raft': 'R02', 'name_in_raft': 'S02', 'exposure': 3019110102212, 'instrument': 'LSSTCam'}
43TESTDATA_ROOT = os.path.join(TESTDIR, "data")
46class RawAssemblyTestCase(lsst.utils.tests.TestCase):
47 """Test assembly of each of data from each of the two
48 manufacturers. Data come from BOT spot data runs.
49 """
51 def setUp(self):
52 # E2V and ITL detecotrs and expected assembled images
53 self.e2v = {'detector': Detector.readFits(os.path.join(TESTDATA_ROOT, 'e2v_detector.fits')),
54 'expected': ImageFitsReader(os.path.join(TESTDATA_ROOT,
55 'e2v_expected_assembled.fits.gz'))}
56 self.itl = {'detector': Detector.readFits(os.path.join(TESTDATA_ROOT, 'itl_detector.fits')),
57 'expected': ImageFitsReader(os.path.join(TESTDATA_ROOT,
58 'itl_expected_assembled.fits.gz'))}
59 self.roots = [BOT_DATA_ROOT, BOT_DATA_ROOT]
60 self.ids = [E2V_DATA_ID, ITL_DATA_ID]
61 self.expecteds = [self.e2v, self.itl]
63 def assertAmpRawBBoxesEqual(self, amp1, amp2):
64 """Check that Raw bounding boxes match between amps.
66 Parameters
67 ----------
68 amp1 : `~lsst.afw.cameraGeom.Amplifier`
69 First amplifier.
70 amp2 : `~lsst.afw.cameraGeom.Amplifier`
71 Second amplifier.
72 """
73 self.assertEqual(amp1.getRawBBox(), amp2.getRawBBox())
74 self.assertEqual(amp1.getRawHorizontalOverscanBBox(), amp2.getRawHorizontalOverscanBBox())
75 self.assertEqual(amp1.getRawVerticalOverscanBBox(), amp2.getRawVerticalOverscanBBox())
77 def assertAmpRawBBoxesFlippablyEqual(self, amp1, amp2):
78 """Check that amp1 can be self-consistently transformed to match amp2.
80 This method compares amplifier bounding boxes by confirming
81 that they represent the same segment of the detector image.
82 If the offsets or amplifier flips differ between the
83 amplifiers, this method will pass even if the raw bounding
84 boxes returned by the amplifier accessors are not equal.
86 Parameters
87 ----------
88 amp1 : `~lsst.afw.cameraGeom.Amplifier`
89 Amplifier to transform.
90 amp2 : `~lsst.afw.cameraGeom.Amplifier`
91 Reference amplifier.
93 """
94 xFlip = amp1.getRawFlipX() ^ amp2.getRawFlipX()
95 yFlip = amp1.getRawFlipY() ^ amp2.getRawFlipY()
96 XYOffset = amp1.getRawXYOffset() - amp2.getRawXYOffset()
98 testRawBox = amp1.getRawBBox()
99 testHOSBox = amp1.getRawHorizontalOverscanBBox()
100 testVOSBox = amp1.getRawVerticalOverscanBBox()
102 if xFlip:
103 size = amp1.getRawBBox().getWidth()
104 testRawBox.flipLR(size)
105 testHOSBox.flipLR(size)
106 testVOSBox.flipLR(size)
107 if yFlip:
108 size = amp1.getRawBBox().getHeight()
109 testRawBox.flipTB(size)
110 testHOSBox.flipTB(size)
111 testVOSBox.flipTB(size)
113 testRawBox.shift(XYOffset)
114 testHOSBox.shift(XYOffset)
115 testVOSBox.shift(XYOffset)
117 self.assertEqual(testRawBox, amp2.getRawBBox())
118 self.assertEqual(testHOSBox, amp2.getRawHorizontalOverscanBBox())
119 self.assertEqual(testVOSBox, amp2.getRawVerticalOverscanBBox())
121 def testDetectors(self):
122 """Test that the detector returned by the butler is the same
123 as the expected one.
124 """
125 for root, did, expected in zip(self.roots, self.ids, self.expecteds):
126 butler = Butler(root)
127 raw = butler.get("raw", dataId=did, collections="LSSTCam/raw/all")
128 for amp1, amp2 in zip(expected['detector'], raw.getDetector()):
129 with self.subTest(amp=amp1.getName()):
130 self.assertEqual(amp1.getName(), amp2.getName())
131 self.assertAmpRawBBoxesEqual(amp1, amp2)
133 def testAssemble(self):
134 """Test the assembly of E2V and ITL sensors
135 """
136 task = AssembleCcdTask()
137 # exclude LATISS for this test since we don't have an expected output
138 for root, did, expected in zip(self.roots, self.ids, self.expecteds):
139 butler = Butler(root)
140 raw = butler.get("raw", dataId=did, collections="LSSTCam/raw/all")
141 assembled = task.assembleCcd(raw)
142 count = numpy.sum(expected['expected'].read().array - assembled.getImage().array)
143 self.assertEqual(count, 0)
146class ReadRawFileTestCase(lsst.utils.tests.TestCase):
147 def testReadRawLatissFile(self):
148 fileName = os.path.join(LATISS_DATA_ROOT, "raw/2018-09-20/3018092000065-det000.fits")
149 policy = os.path.join(PACKAGE_DIR, "policy", "latiss.yaml")
150 camera = yamlCamera.makeCamera(policy)
151 exposure = readRawFile(fileName, camera[0], dataId={"file": fileName})
152 self.assertIsInstance(exposure, lsst.afw.image.Exposure)
153 md = exposure.getMetadata()
154 self.assertIn("INSTRUME", md)
157def setup_module(module):
158 lsst.utils.tests.init()
161if __name__ == "__main__": 161 ↛ 162line 161 didn't jump to line 162, because the condition on line 161 was never true
162 setup_module(sys.modules[__name__])
163 unittest.main()