Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1# 

2# LSST Data Management System 

3# Copyright 2008, 2009, 2010 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 sys 

23import os 

24from astropy.io import fits 

25import numpy as num 

26import lsst.afw.image as afwImage 

27import lsst.afw.math as afwMath 

28import lsst.meas.algorithms as measAlg 

29DEBUG = False 

30 

31filtToHdu = {'u': 1, 'g': 2, 'r': 3, 'i': 4, 'z': 5} 

32 

33# Mapping from psField coefficient locations to PolynomialFunction2 locations 

34skMatrixPos2TriSeqPosT = [ 

35 0, 2, 5, 9, 14, 

36 1, 4, 8, 13, 19, 

37 3, 7, 12, 18, 25, 

38 6, 11, 17, 24, 32, 

39 10, 16, 23, 31, 40, 

40] 

41 

42 

43def convertpsField(infile, filt, trim=True, rcscale=0.001, MAX_ORDER_B=5, LSST_ORDER=4): 

44 if filt not in filtToHdu: 44 ↛ 45line 44 didn't jump to line 45, because the condition on line 44 was never true

45 print("INVALID FILTER", filt) 

46 sys.exit(1) 

47 

48 with open(infile, "rb") as buff: 

49 pstruct = fits.getdata(buff, ext=filtToHdu[filt]) 

50 

51 spaParList = [[]]*len(pstruct) 

52 kernelList = [] 

53 for i in range(len(pstruct)): 

54 nrow_b = pstruct[i][0] # ny 

55 ncol_b = pstruct[i][1] # nx 

56 cmat = pstruct[i][2].reshape((MAX_ORDER_B, MAX_ORDER_B)) 

57 krow = pstruct[i][4] # RNROW 

58 kcol = pstruct[i][5] # RNCOL 

59 # This is *not* transposed 

60 karr = pstruct[i][7].reshape((krow, kcol)).astype(num.float64) 

61 

62 if trim: 62 ↛ 65line 62 didn't jump to line 65, because the condition on line 62 was never false

63 karr = karr[10:41, 10:41] 

64 

65 kim = afwImage.ImageD(karr) 

66 kern = afwMath.FixedKernel(kim) 

67 kernelList.append(kern) 

68 

69 # NOTES: 

70 

71 # Afw has the polynomial terms like: 

72 # 

73 # * f(x,y) = c0 (0th order) 

74 # * + c1 x + c2 y (1st order) 

75 # * + c3 x^2 + c4 x y + c5 y^2 (2nd order) 

76 # * + c6 x^3 + c7 x^2 y + c8 x y^2 + c9 y^3 (3rd order) 

77 # * + c10 x^4 + c11 x^3 y + c12 x^2 y^2 + c13 x y^3 + c14 y^4 (4th order) 

78 # 

79 # So, ordered: x^0,y^0 x^1,y^0 x^0,y^1 x^2,y^0 x^1,y^1 x^0,y^2 

80 

81 # SDSS has the terms ordered like, after reshape(): 

82 # 

83 # x^0,y^0 x^0,y^1 x^0,y^2 

84 # x^1,y^0 x^1,y^1 x^1,y^2 

85 # x^2,y^0 x^2,y^1 x^2,y^2 

86 # 

87 # So, it technically goes up to fourth order in LSST-speak. OK, that is the trick. 

88 # 

89 # Mapping: 

90 # cmat[0][0] = c0 x^0y^0 

91 # cmat[1][0] = c2 x^0y^1 

92 # cmat[2][0] = c5 x^0y^2 

93 # cmat[0][1] = c1 x^1y^0 

94 # cmat[1][1] = c4 x^1y^1 

95 # cmat[2][1] = c8 x^1y^2 

96 # cmat[0][2] = c3 x^2y^0 

97 # cmat[1][2] = c7 x^2y^1 

98 # cmat[2][2] = c12 x^2y^2 

99 # 

100 # This is quantified in skMatrixPos2TriSeqPosT 

101 

102 spaParamsTri = num.zeros(MAX_ORDER_B * MAX_ORDER_B) 

103 for k in range(nrow_b * ncol_b): 

104 row = k % nrow_b 

105 col = k // nrow_b 

106 coeff = cmat[row, col] 

107 scale = pow(rcscale, row) * pow(rcscale, col) 

108 scaledCoeff = coeff * scale 

109 

110 # Was originally written like this, but the SDSS code 

111 # takes inputs as y,x instead of x,y meaning it was 

112 # originally transposed 

113 # 

114 # idx = row * MAX_ORDER_B + col 

115 

116 idx = col * MAX_ORDER_B + row 

117 spaParamsTri[skMatrixPos2TriSeqPosT[idx]] = scaledCoeff 

118 

119 # print "%d y=%d x=%d %10.3e %2d %2d %10.3e" % \ 

120 # (i, row, col, cmat[row,col], idx, skMatrixPos2TriSeqPosT[idx], scaledCoeff) 

121 

122 # print spaParamsTri 

123 nTerms = (LSST_ORDER + 1) * (LSST_ORDER + 2) // 2 

124 spaParamsTri = spaParamsTri[:nTerms] 

125 spaParList[i] = spaParamsTri 

126 

127 spaFun = afwMath.PolynomialFunction2D(LSST_ORDER) 

128 spatialKernel = afwMath.LinearCombinationKernel(kernelList, spaFun) 

129 spatialKernel.setSpatialParameters(spaParList) 

130 spatialPsf = measAlg.PcaPsf(spatialKernel) 

131 return spatialPsf 

132 

133 

134def directCompare(infile, filt, x, y, soft_bias=1000, amp=30000, outfile="/tmp/sdss_psf.fits"): 

135 if filt not in filtToHdu.keys(): 

136 print("INVALID FILTER", filt) 

137 sys.exit(1) 

138 

139 # Make the kernel image from LSST 

140 psf = convertpsField(infile, filt, trim=False) 

141 kernel = psf.getKernel() 

142 

143 # Assumes you have built dervish and have read_PSF in your path 

144 # 

145 # read_PSF takes coordinates in the order row,col or y,x 

146 cmd = "read_PSF %s %s %f %f %s" % (infile, filtToHdu[filt], y, x, outfile) 

147 os.system(cmd) 

148 if not os.path.isfile(outfile): 

149 print("Cannot find SDSS-derived kernel", outfile) 

150 sys.exit(1) 

151 

152 if False: 

153 # Default version that integerizes Psf 

154 kImage1 = afwImage.ImageD(outfile) 

155 kImage1 -= soft_bias 

156 kImage1 /= (amp - soft_bias) 

157 maxVal = afwMath.makeStatistics(kImage1, afwMath.MAX).getValue(afwMath.MAX) 

158 print("TEST 1", maxVal == 1.0) 

159 kImage1.writeFits("/tmp/sdss_psf_scaled.fits") 

160 else: 

161 # Hacked version of main_PSF.c that writes floats 

162 kImage1 = afwImage.ImageD(outfile) 

163 maxVal = afwMath.makeStatistics(kImage1, afwMath.MAX).getValue(afwMath.MAX) 

164 kImage1 /= maxVal 

165 kImage1.writeFits("/tmp/sdss_psf_scaled.fits") 

166 

167 # 

168 kImage2 = afwImage.ImageD(kernel.getDimensions()) 

169 kernel.computeImage(kImage2, True, x, y) 

170 maxVal = afwMath.makeStatistics(kImage2, afwMath.MAX).getValue(afwMath.MAX) 

171 kImage2 /= maxVal 

172 kImage2.writeFits("/tmp/kernel.fits") 

173 

174 kImage3 = afwImage.ImageD(kImage2, True) 

175 kImage3 -= kImage1 

176 kImage3.writeFits("/tmp/diff.fits") 

177 residSum = afwMath.makeStatistics(kImage3, afwMath.SUM).getValue(afwMath.SUM) 

178 print("TEST 2", residSum) 

179 

180 kImage4 = afwImage.ImageD(kImage2, True) 

181 kImage4 /= kImage1 

182 kImage4.writeFits("/tmp/rat.fits") 

183 

184 

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

186 infile = sys.argv[1] 

187 filt = sys.argv[2] 

188 x = float(sys.argv[3]) # col 

189 y = float(sys.argv[4]) # row 

190 outfile = sys.argv[5] 

191 

192 if not os.path.isfile(infile): 

193 sys.exit(1) 

194 

195 if DEBUG: 

196 directCompare(infile, filt, x, y) 

197 else: 

198 psf = convertpsField(infile, filt) 

199 kernel = psf.getKernel() 

200 kImage = afwImage.ImageD(kernel.getDimensions()) 

201 kernel.computeImage(kImage, True, x, y) 

202 kImage.writeFits(outfile) 

203 

204 # Persist the kernel at your own leisure