99def compute_approx_psf_size_and_shape(ccd_row, ra, dec, nx=20, ny=20, orderx=2, ordery=2):
100 """Compute the approximate psf size and shape.
101
102 This routine fits how the psf size and shape varies over a field by approximating
103 with a Chebyshev bounded field.
104
105 Parameters
106 ----------
107 ccd_row : `lsst.afw.table.ExposureRecord`
108 Exposure metadata for a given detector exposure.
109 ra : `np.ndarray`
110 Right ascension of points to compute size and shape (degrees).
111 dec : `np.ndarray`
112 Declination of points to compute size and shape (degrees).
113 nx : `int`, optional
114 Number of sampling points in the x direction.
115 ny : `int`, optional
116 Number of sampling points in the y direction.
117 orderx : `int`, optional
118 Chebyshev polynomial order for fit in x direction.
119 ordery : `int`, optional
120 Chebyshev polynomial order for fit in y direction.
121
122 Returns
123 -------
124 psf_array : `np.ndarray`
125 Record array with "psf_size", "psf_e1", "psf_e2".
126 """
128 r, d in zip(ra, dec)]
129 pixels = ccd_row.getWcs().skyToPixel(pts)
130
131 ctrl = ChebyshevBoundedFieldControl()
132 ctrl.orderX = orderx
133 ctrl.orderY = ordery
134 ctrl.triangular = False
135
136 bbox = ccd_row.getBBox()
137 xSteps = np.linspace(bbox.getMinX(), bbox.getMaxX(), nx)
138 ySteps = np.linspace(bbox.getMinY(), bbox.getMaxY(), ny)
139 x = np.tile(xSteps, nx)
140 y = np.repeat(ySteps, ny)
141
142 psf_size = np.zeros(x.size)
143 psf_e1 = np.zeros(x.size)
144 psf_e2 = np.zeros(x.size)
145 psf_area = np.zeros(x.size)
146
147 psf = ccd_row.getPsf()
148 for i in range(x.size):
150 psf_size[i] = shape.getDeterminantRadius()
151 ixx = shape.getIxx()
152 iyy = shape.getIyy()
153 ixy = shape.getIxy()
154
155 psf_e1[i] = (ixx - iyy)/(ixx + iyy + 2.*psf_size[i]**2.)
156 psf_e2[i] = (2.*ixy)/(ixx + iyy + 2.*psf_size[i]**2.)
157
159 psf_area[i] = np.sum(im.array)/np.sum(im.array**2.)
160
161 pixel_x = np.array([pix.getX() for pix in pixels])
162 pixel_y = np.array([pix.getY() for pix in pixels])
163
164 psf_array = np.zeros(pixel_x.size, dtype=[("psf_size", "f8"),
165 ("psf_e1", "f8"),
166 ("psf_e2", "f8"),
167 ("psf_area", "f8")])
168
169
170 good = np.isfinite(psf_size)
171 x = x[good]
172 y = y[good]
173
174 cheb_size = ChebyshevBoundedField.fit(
lsst.geom.Box2I(bbox), x, y, psf_size[good], ctrl)
175 psf_array["psf_size"] = cheb_size.evaluate(pixel_x, pixel_y)
176 cheb_e1 = ChebyshevBoundedField.fit(
lsst.geom.Box2I(bbox), x, y, psf_e1[good], ctrl)
177 psf_array["psf_e1"] = cheb_e1.evaluate(pixel_x, pixel_y)
178 cheb_e2 = ChebyshevBoundedField.fit(
lsst.geom.Box2I(bbox), x, y, psf_e2[good], ctrl)
179 psf_array["psf_e2"] = cheb_e2.evaluate(pixel_x, pixel_y)
180 cheb_area = ChebyshevBoundedField.fit(
lsst.geom.Box2I(bbox), x, y, psf_area[good], ctrl)
181 psf_array["psf_area"] = cheb_area.evaluate(pixel_x, pixel_y)
182
183 return psf_array
184
185
An integer coordinate rectangle.
Point in an unspecified spherical coordinate system.