Coverage for metadetect / shearpos.py: 13%
59 statements
« prev ^ index » next coverage.py v7.13.1, created at 2026-01-09 01:50 -0800
« prev ^ index » next coverage.py v7.13.1, created at 2026-01-09 01:50 -0800
1import numpy as np
2import galsim
4from ngmix.metacal import DEFAULT_STEP
6SKIP_SHEARS = ['noshear', '1p_psf', '1m_psf', '2p_psf', '2m_psf']
9def shear_positions_obs(rows, cols, shear_str, obs, step=DEFAULT_STEP):
10 """
11 unshear the input row and column positions
13 Parameters
14 ----------
15 rows: array
16 array of row values in sheared coordinates. Should be pixels
17 in the image, not in a larger system
18 cols: array
19 array of col values in sheared coordinates. Should be pixels
20 in the image, not in a larger system
21 shear_str: string
22 'noshear', '1p', '1m', '2p', '2m'
23 obs: ngmix.Observation
24 The observation data
25 step: float
26 shear step for metacal, default 0.01
28 Returns
29 -------
30 rows_sheared, cols_sheared:
31 rows and cols in the sheared coordinates
32 """
33 jac = obs.jacobian
34 dims = obs.image.shape
36 return shear_positions(
37 rows=rows, cols=cols, shear_str=shear_str, jac=jac, dims=dims,
38 step=step,
39 )
42def shear_positions(rows, cols, shear_str, jac, dims, step=DEFAULT_STEP):
43 """
44 unshear the input row and column positions
46 Parameters
47 ----------
48 rows: array
49 array of row values in sheared coordinates. Should be pixels
50 in the image, not in a larger system
51 cols: array
52 array of col values in sheared coordinates. Should be pixels
53 in the image, not in a larger system
54 shear_str: string
55 'noshear', '1p', '1m', '2p', '2m'
56 jac: ngmix.Jacobian
57 Describes the wcs
58 dims: (nrows, ncols)
59 The shape of the image data
60 step: float
61 shear step for metacal, default 0.01
63 Returns
64 -------
65 rows_sheared, cols_sheared:
66 rows and cols in the sheared coordinates
67 """
69 if shear_str in SKIP_SHEARS:
70 return rows, cols
72 shear = get_galsim_shear(shear_str, step)
74 # this is the matrix that does shearing in u, v
75 a = shear.getMatrix()
77 # we need the canonical image center in (u, v) for undoing the
78 # shearing
80 row_cen = (dims[0] - 1) / 2
81 col_cen = (dims[1] - 1) / 2
83 v_cen, u_cen = jac.get_vu(row=row_cen, col=col_cen)
85 # apply WCS to get to world coords
86 v, u = jac.get_vu(row=rows, col=cols)
88 # unshear (subtract and then add the canonical center in u, v)
89 u = np.atleast_1d(u) - u_cen
90 v = np.atleast_1d(v) - v_cen
92 pos = np.vstack((u, v))
94 out = np.dot(a, pos)
95 assert out.shape[1] == u.shape[0]
96 u_sheared = out[0, :] + u_cen
97 v_sheared = out[1, :] + v_cen
99 # undo the WCS to get to image coords
100 rows_sheared, cols_sheared = jac.get_rowcol(v=v_sheared, u=u_sheared)
102 return rows_sheared, cols_sheared
105def unshear_positions_obs(rows, cols, shear_str, obs, step=DEFAULT_STEP):
106 """
107 unshear the input row and column positions
109 Parameters
110 ----------
111 rows: array
112 array of row values in sheared coordinates
113 cols: array
114 array of col values in sheared coordinates
115 shear_str: string
116 'noshear', '1p', '1m', '2p', '2m'
117 obs: ngmix.Observation
118 The observation data
119 step: float, optional
120 shear step for metacal, default 0.01
122 Returns
123 -------
124 rows_unsheared, cols_unsheared:
125 rows and cols in the unsheared coordinates
126 """
128 jac = obs.jacobian
129 dims = obs.image.shape
131 return unshear_positions(
132 rows=rows, cols=cols, shear_str=shear_str, jac=jac, dims=dims,
133 step=step,
134 )
137def unshear_positions(rows, cols, shear_str, jac, dims, step=DEFAULT_STEP):
138 """
139 unshear the input row and column positions
141 Parameters
142 ----------
143 rows: array
144 array of row values in sheared coordinates
145 cols: array
146 array of col values in sheared coordinates
147 shear_str: string
148 'noshear', '1p', '1m', '2p', '2m'
149 jac: ngmix.Jacobian
150 Describes the wcs
151 dims: (nrows, ncols)
152 The shape of the image data
153 step: float
154 shear step for metacal, default 0.01
156 Returns
157 -------
158 rows_unsheared, cols_unsheared:
159 rows and cols in the unsheared coordinates
160 """
162 if shear_str in SKIP_SHEARS:
163 return rows, cols
165 shear = get_galsim_shear(shear_str, step)
167 # this is the matrix that undoes shearing in u, v
168 ainv = np.linalg.inv(shear.getMatrix())
170 # we need the canonical image center in (u, v) for undoing the
171 # shearing
173 row_cen = (dims[0] - 1) / 2
174 col_cen = (dims[1] - 1) / 2
176 v_cen, u_cen = jac.get_vu(row=row_cen, col=col_cen)
178 # apply WCS to get to world coords
179 v, u = jac.get_vu(row=rows, col=cols)
181 # unshear (subtract and then add the canonical center in u, v)
182 u = np.atleast_1d(u) - u_cen
183 v = np.atleast_1d(v) - v_cen
185 pos = np.vstack((u, v))
187 out = np.dot(ainv, pos)
188 assert out.shape[1] == u.shape[0]
189 u_unsheared = out[0] + u_cen
190 v_unsheared = out[1] + v_cen
192 # undo the WCS to get to image coords
193 rows_unsheared, cols_unsheared = \
194 jac.get_rowcol(v=v_unsheared, u=u_unsheared)
196 return rows_unsheared, cols_unsheared
199def get_galsim_shear(shear_str, step):
200 """
201 convert shear string to galsim Shear object
202 """
204 if shear_str == '1p':
205 shear = galsim.Shear(g1=+step, g2=0.00)
206 elif shear_str == '1m':
207 shear = galsim.Shear(g1=-step, g2=0.00)
208 elif shear_str == '2p':
209 shear = galsim.Shear(g1=0.00, g2=+step)
210 elif shear_str == '2m':
211 shear = galsim.Shear(g1=0.00, g2=-step)
212 else:
213 raise ValueError('can only convert 1p,1m,2p,2m to galsim Shear')
215 return shear