Coverage for python/lsst/obs/sdss/convertpsField.py : 50%

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
31filtToHdu = {'u': 1, 'g': 2, 'r': 3, 'i': 4, 'z': 5}
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]
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)
48 with open(infile, "rb") as buff:
49 pstruct = fits.getdata(buff, ext=filtToHdu[filt])
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)
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]
65 kim = afwImage.ImageD(karr)
66 kern = afwMath.FixedKernel(kim)
67 kernelList.append(kern)
69 # NOTES:
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
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
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
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
116 idx = col * MAX_ORDER_B + row
117 spaParamsTri[skMatrixPos2TriSeqPosT[idx]] = scaledCoeff
119 # print "%d y=%d x=%d %10.3e %2d %2d %10.3e" % \
120 # (i, row, col, cmat[row,col], idx, skMatrixPos2TriSeqPosT[idx], scaledCoeff)
122 # print spaParamsTri
123 nTerms = (LSST_ORDER + 1) * (LSST_ORDER + 2) // 2
124 spaParamsTri = spaParamsTri[:nTerms]
125 spaParList[i] = spaParamsTri
127 spaFun = afwMath.PolynomialFunction2D(LSST_ORDER)
128 spatialKernel = afwMath.LinearCombinationKernel(kernelList, spaFun)
129 spatialKernel.setSpatialParameters(spaParList)
130 spatialPsf = measAlg.PcaPsf(spatialKernel)
131 return spatialPsf
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)
139 # Make the kernel image from LSST
140 psf = convertpsField(infile, filt, trim=False)
141 kernel = psf.getKernel()
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)
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")
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")
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)
180 kImage4 = afwImage.ImageD(kImage2, True)
181 kImage4 /= kImage1
182 kImage4.writeFits("/tmp/rat.fits")
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]
192 if not os.path.isfile(infile):
193 sys.exit(1)
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)
204 # Persist the kernel at your own leisure