Coverage for tests/test_applyLookupTable.py: 24%

66 statements  

« prev     ^ index     » next       coverage.py v7.1.0, created at 2023-02-05 18:17 -0800

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 lookup column 

48 

49 @return the number of pixels whose values were out of range 

50 """ 

51 imArr = image.getArray() 

52 indArr = np.array(imArr + indOffset, dtype=int) 

53 maxInd = len(table) - 1 

54 numBadPoints = np.sum(indArr < 0) 

55 numBadPoints += np.sum(indArr > maxInd) 

56 indArr = np.where(indArr < 0, 0, indArr) 

57 indArr = np.where(indArr >= maxInd, maxInd, indArr) 

58 imArr += table[indArr] 

59 return numBadPoints 

60 

61 

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

63 

64 def setUp(self): 

65 np.random.seed(42) 

66 

67 def testBasics(self): 

68 """!Test basic functionality of applyLookupTable 

69 """ 

70 bbox = lsst.geom.Box2I(lsst.geom.Point2I(-31, 22), lsst.geom.Extent2I(100, 85)) 

71 imMin = -5 

72 imMax = 2500 

73 tableLen = 2000 

74 tableSigma = 55 

75 for indOffset in (0, -50, 234): 

76 for imageClass in (afwImage.ImageF, afwImage.ImageD): 

77 inImage = makeRampImage(bbox=bbox, start=imMin, stop=imMax, imageClass=imageClass) 

78 table = np.random.normal(scale=tableSigma, size=tableLen) 

79 table = np.array(table, dtype=inImage.getArray().dtype) 

80 

81 refImage = imageClass(inImage, True) 

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

83 

84 measImage = imageClass(inImage, True) 

85 measNumBad = applyLookupTable(measImage, table, indOffset) 

86 

87 self.assertEqual(refNumBad, measNumBad) 

88 self.assertImagesAlmostEqual(refImage, measImage) 

89 

90 def testKnown(self): 

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

92 

93 Apply a negative ramp table to a positive ramp image to get a flat image, 

94 but have one value out of range at each end, to offset each end point by one 

95 """ 

96 # generate a small ramp image with ascending integer values 

97 # starting at some small negative value going positive 

98 bbox = lsst.geom.Box2I(lsst.geom.Point2I(0, 0), lsst.geom.Extent2I(3, 4)) 

99 numPix = bbox.getWidth()*bbox.getHeight() 

100 start = -3 

101 stop = start + numPix - 1 

102 im = makeRampImage(bbox=bbox, start=start, stop=stop, imageClass=afwImage.ImageF) 

103 # generate a ramp lookup table with descending integer values, 

104 # with a range offset by a small arbitrary value from the image ramp 

105 # make it two elements too short so we can have one value out of range at each end 

106 numOutOfRangePerEnd = 1 

107 numOutOfRange = 2*numOutOfRangePerEnd 

108 tableOffset = -2 

109 table = np.linspace( 

110 start=stop + tableOffset, 

111 stop=numOutOfRange + start + tableOffset, 

112 num=numPix - numOutOfRange) 

113 table = np.array(table, dtype=im.getArray().dtype) 

114 # apply the table with the first and last image value out of range by one 

115 indOffset = -(start + numOutOfRangePerEnd) 

116 measNumOutOfRange = applyLookupTable(im, table, indOffset) 

117 self.assertEqual(numOutOfRange, measNumOutOfRange) 

118 # at this point the image should all have the same value 

119 # except the first point will be one less and the last one more 

120 imArr = im.getArray() 

121 desVal = start + numOutOfRangePerEnd + table[0] 

122 desImArr = np.zeros(numPix, dtype=im.getArray().dtype) 

123 desImArr[:] = desVal 

124 desImArr[0] -= 1 

125 desImArr[-1] += 1 

126 desImArr.shape = imArr.shape 

127 self.assertFloatsAlmostEqual(desImArr, imArr) 

128 

129 

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

131 pass 

132 

133 

134def setup_module(module): 

135 lsst.utils.tests.init() 

136 

137 

138if __name__ == "__main__": 138 ↛ 139line 138 didn't jump to line 139, because the condition on line 138 was never true

139 lsst.utils.tests.init() 

140 unittest.main()