Coverage for tests/test_applyLookupTable.py: 24%

66 statements  

« prev     ^ index     » next       coverage.py v7.2.4, created at 2023-04-29 03:42 -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 

23 

24import numpy as np 

25 

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 

31 

32 

33def referenceApply(image, table, indOffset): 

34 """!Reference implementation of applyLookupTable 

35 

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 

44 

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 

49 

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 

61 

62 

63class ApplyLookupTableTestCase(lsst.utils.tests.TestCase): 

64 

65 def setUp(self): 

66 np.random.seed(42) 

67 

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) 

81 

82 refImage = imageClass(inImage, True) 

83 refNumBad = referenceApply(image=refImage, table=table, indOffset=indOffset) 

84 

85 measImage = imageClass(inImage, True) 

86 measNumBad = applyLookupTable(measImage, table, indOffset) 

87 

88 self.assertEqual(refNumBad, measNumBad) 

89 self.assertImagesAlmostEqual(refImage, measImage) 

90 

91 def testKnown(self): 

92 """Test that a given image and lookup table produce the known answer 

93 

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) 

132 

133 

134class MemoryTester(lsst.utils.tests.MemoryTestCase): 

135 pass 

136 

137 

138def setup_module(module): 

139 lsst.utils.tests.init() 

140 

141 

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()