LSST Applications  21.0.0-172-gfb10e10a+18fedfabac,22.0.0+297cba6710,22.0.0+80564b0ff1,22.0.0+8d77f4f51a,22.0.0+a28f4c53b1,22.0.0+dcf3732eb2,22.0.1-1-g7d6de66+2a20fdde0d,22.0.1-1-g8e32f31+297cba6710,22.0.1-1-geca5380+7fa3b7d9b6,22.0.1-12-g44dc1dc+2a20fdde0d,22.0.1-15-g6a90155+515f58c32b,22.0.1-16-g9282f48+790f5f2caa,22.0.1-2-g92698f7+dcf3732eb2,22.0.1-2-ga9b0f51+7fa3b7d9b6,22.0.1-2-gd1925c9+bf4f0e694f,22.0.1-24-g1ad7a390+a9625a72a8,22.0.1-25-g5bf6245+3ad8ecd50b,22.0.1-25-gb120d7b+8b5510f75f,22.0.1-27-g97737f7+2a20fdde0d,22.0.1-32-gf62ce7b1+aa4237961e,22.0.1-4-g0b3f228+2a20fdde0d,22.0.1-4-g243d05b+871c1b8305,22.0.1-4-g3a563be+32dcf1063f,22.0.1-4-g44f2e3d+9e4ab0f4fa,22.0.1-42-gca6935d93+ba5e5ca3eb,22.0.1-5-g15c806e+85460ae5f3,22.0.1-5-g58711c4+611d128589,22.0.1-5-g75bb458+99c117b92f,22.0.1-6-g1c63a23+7fa3b7d9b6,22.0.1-6-g50866e6+84ff5a128b,22.0.1-6-g8d3140d+720564cf76,22.0.1-6-gd805d02+cc5644f571,22.0.1-8-ge5750ce+85460ae5f3,master-g6e05de7fdc+babf819c66,master-g99da0e417a+8d77f4f51a,w.2021.48
LSST Data Management Base Package
genDistortedImage.py
Go to the documentation of this file.
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 #
22 
23 __all__ = ["noDistort", "linearXDistort", "quadraticDistortX",
24  "cubicDistortX", "manyTermX", "crossTerms1",
25  "crossTerms2", "crossTerms3", "quadraticDistort",
26  "T2DistortX", "T2DistortX"]
27 
28 
29 import math
30 
31 import lsst.afw.table as afwTable
32 
33 
34 def noDistort(src):
35  """Do no distortion. Used for sanity checking
36 
37  Parameters
38  ----------
39  src : `lsst.afw.table.SourceRecord`
40  Input record
41 
42  Returns
43  -------
44  out : `lsst.afw.table.SourceRecord`
45  Copy of input record.
46  """
47 
48  out = src.table.copyRecord(src)
49  return out
50 
51 
52 def linearXDistort(src, frac=.001):
53  """Increase the x value in a Source object by frac. E.g
54  src.x = 1000 --> 1001 if frac=.001
55 
56  Parameters
57  ----------
58  src : `lsst.afw.table.SourceRecord`
59  A Source object
60  frac : `float`
61  How much to change X by
62 
63  Returns
64  -------
65  out : `lsst.afw.table.SourceRecord`
66  A deep copy of src, with the value of x changed
67  """
68 
69  out = src.table.copyRecord(src)
70  out.set(out.table.getCentroidSlot().getMeasKey().getX(), out.getX()*(1+frac))
71  return out
72 
73 
74 def quadraticDistortX(src, frac=1e-6):
75  """Distort image by terms with power <=2
76  i.e y, y^2, x, xy, x^2
77 
78  Parameters
79  ----------
80  src : `lsst.afw.table.SourceRecord`
81  A Source object
82  frac : `float`
83  How much to change X by
84 
85  Returns
86  -------
87  out : `lsst.afw.table.SourceRecord`
88  A deep copy of src, with the value of x changed
89  """
90 
91  out = src.table.copyRecord(src)
92  x = out.getX()
93  y = out.getY()
94  val = x**2
95 
96  out.set(out.table.getCentroidSlot().getMeasKey().getX(), x + val*frac)
97  out.set(out.table.getCentroidSlot().getMeasKey().getY(), y)
98  return out
99 
100 
101 def cubicDistortX(src, frac=1e-9):
102  """Distort image by terms with power <=2
103  i.e y, y^2, x, xy, x^2
104 
105  Parameters
106  ----------
107  src : `lsst.afw.table.SourceRecord`
108  A Source object
109  frac : `float`
110  How much to change X by
111 
112  Returns
113  -------
114  out : `lsst.afw.table.SourceRecord`
115  A deep copy of src, with the value of x changed
116  """
117 
118  out = src.table.copyRecord(src)
119  x = out.getX()
120  y = out.getY()
121  val = x**3
122 
123  out.set(out.table.getCentroidSlot().getMeasKey().getX(), x + val*frac)
124  out.set(out.table.getCentroidSlot().getMeasKey().getY(), y)
125  return out
126 
127 
128 def manyTermX(src, frac=1e-9):
129  """Distort image by multiple powers of x, 'x**3 - 2*x**2 + 4*x - 9'.
130 
131  Parameters
132  ----------
133  src : `lsst.afw.table.SourceRecord`
134  A Source object
135  frac : `float`
136  How much to change X by
137 
138  Returns
139  -------
140  out : `lsst.afw.table.SourceRecord`
141  A deep copy of src, with the value of x changed
142  """
143 
144  out = src.table.copyRecord(src)
145  x = out.getX()
146  y = out.getY()
147  val = x**3 - 2*x**2 + 4*x - 9
148 
149  out.set(out.table.getCentroidSlot().getMeasKey().getX(), x + val*frac)
150  out.set(out.table.getCentroidSlot().getMeasKey().getY(), y)
151  return out
152 
153 
154 def linearYDistort(src, frac=.001):
155  """Increase the y value in a Source object by frac. E.g
156  src.x = 1000 --> 1001 if frac=.001
157 
158  Parameters
159  ----------
160  src : `lsst.afw.table.SourceRecord`
161  A Source object
162  frac : `float`
163  How much to change Y by
164 
165  Returns
166  -------
167  out : `lsst.afw.table.SourceRecord`
168  A deep copy of src, with the value of Y changed
169  """
170 
171  out = src.table.copyRecord(src)
172  out.set(out.table.getCentroidSlot().getMeasKey().getY(), out.getY()*(1+frac))
173  return out
174 
175 
176 def quadraticDistortY(src, frac=1e-6):
177  """Distort image by terms with power <=2
178  i.e y, y^2, x, xy, x^2
179 
180  Parameters
181  ----------
182  src : `lsst.afw.table.SourceRecord`
183  A Source object
184  frac : `float`
185  How much to change Y by
186 
187  Returns
188  -------
189  out : `lsst.afw.table.SourceRecord`
190  A deep copy of src, with the value of Y changed
191  """
192 
193  out = src.table.copyRecord(src)
194  x = out.getX()
195  y = out.getY()
196  val = y**2
197 
198  out.set(out.table.getCentroidSlot().getMeasKey().getX(), x)
199  out.set(out.table.getCentroidSlot().getMeasKey().getY(), y + val*frac)
200  return out
201 
202 
203 def cubicDistortY(src, frac=1e-9):
204  """Distort image by terms with power <=2
205  i.e y, y^2, x, xy, x^2
206 
207  Parameters
208  ----------
209  src : `lsst.afw.table.SourceRecord`
210  A Source object
211  frac : `float`
212  How much to change Y by
213 
214  Returns
215  -------
216  out : `lsst.afw.table.SourceRecord`
217  A deep copy of src, with the value of Y changed
218  """
219 
220  out = src.table.copyRecord(src)
221  x = out.getX()
222  y = out.getY()
223  val = x**3
224 
225  out.set(out.table.getCentroidSlot().getMeasKey().getX(), x)
226  out.set(out.table.getCentroidSlot().getMeasKey().getY(), y + val*frac)
227  return out
228 
229 
230 def manyTermY(src, frac=1e-9):
231  """Distort image by multiple terms of Y, 'y**3 - 2*y**2 + 4*y - 9'.
232 
233  Parameters
234  ----------
235  src : `lsst.afw.table.SourceRecord`
236  A Source object
237  frac : `float`
238  How much to change Y by
239 
240  Returns
241  -------
242  out : `lsst.afw.table.SourceRecord`
243  A deep copy of src, with the value of Y changed
244  """
245  out = src.table.copyRecord(src)
246  x = out.getX()
247  y = out.getY()
248  val = y**3 - 2*y**2 + 4*y - 9
249 
250  out.set(out.table.getCentroidSlot().getMeasKey().getX(), x)
251  out.set(out.table.getCentroidSlot().getMeasKey().getY(), y + val*frac)
252  return out
253 
254 
255 def crossTerms1(src, frac=1e-11):
256  """Distort image Y by X, leaving X unchanged, 'x**3 - 2*x**2'.
257 
258  Parameters
259  ----------
260  src : `lsst.afw.table.SourceRecord`
261  A Source object
262  frac : `float`
263  How much to change Y by
264 
265  Returns
266  -------
267  out : `lsst.afw.table.SourceRecord`
268  A deep copy of src, with the value of Y changed
269  """
270  out = src.table.copyRecord(src)
271  x = out.getX()
272  y = out.getY()
273  val = x**3 - 2*x**2 # + 4*x - 9
274 
275  out.set(out.table.getCentroidSlot().getMeasKey().getX(), x)
276  out.set(out.table.getCentroidSlot().getMeasKey().getY(), y + val*frac)
277  return out
278 
279 
280 def crossTerms2(src, frac=1e-11):
281  """Distort image X by Y, leaving Y unchanged, 'y**3 - 2*y**2 + 4*y - 9'.
282 
283  Parameters
284  ----------
285  src : `lsst.afw.table.SourceRecord`
286  A Source object
287  frac : `float`
288  How much to change X by
289 
290  Returns
291  -------
292  out : `lsst.afw.table.SourceRecord`
293  A deep copy of src, with the value of X changed
294  """
295  out = src.table.copyRecord(src)
296  x = out.getX()
297  y = out.getY()
298  val = y**3 - 2*y**2 + 4*y - 9
299 
300  out.set(out.table.getCentroidSlot().getMeasKey().getX(), x + val*frac)
301  out.set(out.table.getCentroidSlot().getMeasKey().getY(), y)
302  return out
303 
304 
305 def crossTerms3(src, frac=1e-9):
306  """Distort image X and Y , 'dx=x**3 - 2*x**2 + 4*x - 9',
307  'dy=y**3 - 2*y**2 + 4*y - 9'.
308 
309  Parameters
310  ----------
311  src : `lsst.afw.table.SourceRecord`
312  A Source object
313  frac : `float`
314  How much to change X and Y by
315 
316  Returns
317  -------
318  out : `lsst.afw.table.SourceRecord`
319  A deep copy of src, with the value of X and Y changed
320  """
321  out = src.table.copyRecord(src)
322  x = out.getX()
323  y = out.getY()
324  valx = x**3 - 2*x**2 + 4*x - 9
325  valy = y**3 - 2*y**2 + 4*y - 9
326 
327  out.set(out.table.getCentroidSlot().getMeasKey().getX(), x + valy*frac)
328  out.set(out.table.getCentroidSlot().getMeasKey().getY(), y + valx*frac)
329  return out
330 
331 
332 def quadraticDistort(src, frac=1e-6):
333  """Distort image by terms with power <=2
334  i.e y, y^2, x, xy, x^2
335 
336  Parameters
337  ----------
338  src : `lsst.afw.table.SourceRecord`
339  A Source object
340  frac : `float`
341  How much to change X
342 
343  Returns
344  -------
345  out : `lsst.afw.table.SourceRecord`
346  A deep copy of src, with the value of X
347  """
348 
349  out = src.table.copyRecord(src)
350  x = out.getX()
351  y = out.getY()
352  val = y + 2*y**2
353  val += 3*x + 4*x*y
354  val += x**2
355 
356  out.set(out.table.getCentroidSlot().getMeasKey().getX(), x + val*frac)
357  out.set(out.table.getCentroidSlot().getMeasKey().getY(), y)
358  return out
359 
360 
361 def T2DistortX(src, frac=1e-6):
362  """Distort image by a 2nd order Cheby polynomial
363 
364  Parameters
365  ----------
366  src : `lsst.afw.table.SourceRecord`
367  A Source object
368  frac : `float`
369  How much to change X
370 
371  Returns
372  -------
373  out : `lsst.afw.table.SourceRecord`
374  A deep copy of src, with the value of X
375  """
376 
377  out = src.table.copyRecord(src)
378  x = src.getX()
379  val = 2*(x**2) - 1
380  out.set(out.table.getCentroidSlot().getMeasKey().getX(), x + frac*val)
381  return out
382 
383 
384 def distortList(srcList, function):
385  """Create a copy of srcList, and apply function to distort the
386  values of x and y.
387 
388  Parameters
389  ----------
390  srcList : `list` of `lsst.afw.table.SourceRecord`
391  Input list of source to distort.
392  function : `callable`
393  A function that does a deep copy of a single Source
394 
395  Returns
396  -------
397  out : `lsst.afw.table.SourceCatalog`
398  Output catalog with distorted positions.
399  """
400 
401  out = afwTable.SourceCatalog(srcList.table)
402  out.reserve(len(srcList))
403 
404  for src in srcList:
405  out.append(function(src))
406 
407  maxDiff = 0
408  for i in range(len(srcList)):
409  s = srcList[i]
410  o = out[i]
411 
412  x1, y1 = s.getX(), s.getY()
413  x2, y2 = o.getX(), o.getY()
414 
415  diff = math.hypot(x1-x2, y1-y2)
416  maxDiff = max(diff, maxDiff)
417 
418  print("Max deviation is %e pixels" % (maxDiff))
419 
420  return out
int max