Coverage for tests/test_applyLookupTable.py: 24%
66 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-06 03:19 -0700
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-06 03:19 -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#
22import unittest
24import numpy as np
26import lsst.utils.tests
27import lsst.geom
28import lsst.afw.image as afwImage
29from lsst.afw.image.testUtils import makeRampImage
30from lsst.ip.isr import applyLookupTable
33def referenceApply(image, table, indOffset):
34 """!Reference implementation of applyLookupTable
36 The algorithm is as follows:
37 numOutOfRange = 0
38 For each i,j of the image:
39 lookupInd = int(indOffset + image[i,j])
40 if lookupInd not in range [0, table.size() - 1]:
41 set lookupInd to nearest edge and increment numOutOfRange
42 image[i,j] += table[lookupInd]
43 return numOutOfRange
45 @param[in,out] image image to which to add the values; modified in place
46 @param[in] table lookup table
47 @param[in] indOffset scalar added to image value before truncating to
48 lookup column
50 @return the number of pixels whose values were out of range
51 """
52 imArr = image.getArray()
53 indArr = np.array(imArr + indOffset, dtype=int)
54 maxInd = len(table) - 1
55 numBadPoints = np.sum(indArr < 0)
56 numBadPoints += np.sum(indArr > maxInd)
57 indArr = np.where(indArr < 0, 0, indArr)
58 indArr = np.where(indArr >= maxInd, maxInd, indArr)
59 imArr += table[indArr]
60 return numBadPoints
63class ApplyLookupTableTestCase(lsst.utils.tests.TestCase):
65 def setUp(self):
66 np.random.seed(42)
68 def testBasics(self):
69 """!Test basic functionality of applyLookupTable
70 """
71 bbox = lsst.geom.Box2I(lsst.geom.Point2I(-31, 22), lsst.geom.Extent2I(100, 85))
72 imMin = -5
73 imMax = 2500
74 tableLen = 2000
75 tableSigma = 55
76 for indOffset in (0, -50, 234):
77 for imageClass in (afwImage.ImageF, afwImage.ImageD):
78 inImage = makeRampImage(bbox=bbox, start=imMin, stop=imMax, imageClass=imageClass)
79 table = np.random.normal(scale=tableSigma, size=tableLen)
80 table = np.array(table, dtype=inImage.getArray().dtype)
82 refImage = imageClass(inImage, True)
83 refNumBad = referenceApply(image=refImage, table=table, indOffset=indOffset)
85 measImage = imageClass(inImage, True)
86 measNumBad = applyLookupTable(measImage, table, indOffset)
88 self.assertEqual(refNumBad, measNumBad)
89 self.assertImagesAlmostEqual(refImage, measImage)
91 def testKnown(self):
92 """Test that a given image and lookup table produce the known answer
94 Apply a negative ramp table to a positive ramp image to get a flat
95 image, but have one value out of range at each end, to offset each end
96 point by one
97 """
98 # generate a small ramp image with ascending integer values
99 # starting at some small negative value going positive
100 bbox = lsst.geom.Box2I(lsst.geom.Point2I(0, 0), lsst.geom.Extent2I(3, 4))
101 numPix = bbox.getWidth()*bbox.getHeight()
102 start = -3
103 stop = start + numPix - 1
104 im = makeRampImage(bbox=bbox, start=start, stop=stop, imageClass=afwImage.ImageF)
105 # generate a ramp lookup table with descending integer values,
106 # with a range offset by a small arbitrary value from the image ramp
107 # make it two elements too short so we can have one value out of range
108 # at each end
109 numOutOfRangePerEnd = 1
110 numOutOfRange = 2*numOutOfRangePerEnd
111 tableOffset = -2
112 table = np.linspace(
113 start=stop + tableOffset,
114 stop=numOutOfRange + start + tableOffset,
115 num=numPix - numOutOfRange)
116 table = np.array(table, dtype=im.getArray().dtype)
117 # apply the table with the first and last image value out of range by
118 # one.
119 indOffset = -(start + numOutOfRangePerEnd)
120 measNumOutOfRange = applyLookupTable(im, table, indOffset)
121 self.assertEqual(numOutOfRange, measNumOutOfRange)
122 # at this point the image should all have the same value
123 # except the first point will be one less and the last one more
124 imArr = im.getArray()
125 desVal = start + numOutOfRangePerEnd + table[0]
126 desImArr = np.zeros(numPix, dtype=im.getArray().dtype)
127 desImArr[:] = desVal
128 desImArr[0] -= 1
129 desImArr[-1] += 1
130 desImArr.shape = imArr.shape
131 self.assertFloatsAlmostEqual(desImArr, imArr)
134class MemoryTester(lsst.utils.tests.MemoryTestCase):
135 pass
138def setup_module(module):
139 lsst.utils.tests.init()
142if __name__ == "__main__": 142 ↛ 143line 142 didn't jump to line 143, because the condition on line 142 was never true
143 lsst.utils.tests.init()
144 unittest.main()