LSST Applications  21.0.0-147-g0e635eb1+1acddb5be5,22.0.0+052faf71bd,22.0.0+1ea9a8b2b2,22.0.0+6312710a6c,22.0.0+729191ecac,22.0.0+7589c3a021,22.0.0+9f079a9461,22.0.1-1-g7d6de66+b8044ec9de,22.0.1-1-g87000a6+536b1ee016,22.0.1-1-g8e32f31+6312710a6c,22.0.1-10-gd060f87+016f7cdc03,22.0.1-12-g9c3108e+df145f6f68,22.0.1-16-g314fa6d+c825727ab8,22.0.1-19-g93a5c75+d23f2fb6d8,22.0.1-19-gb93eaa13+aab3ef7709,22.0.1-2-g8ef0a89+b8044ec9de,22.0.1-2-g92698f7+9f079a9461,22.0.1-2-ga9b0f51+052faf71bd,22.0.1-2-gac51dbf+052faf71bd,22.0.1-2-gb66926d+6312710a6c,22.0.1-2-gcb770ba+09e3807989,22.0.1-20-g32debb5+b8044ec9de,22.0.1-23-gc2439a9a+fb0756638e,22.0.1-3-g496fd5d+09117f784f,22.0.1-3-g59f966b+1e6ba2c031,22.0.1-3-g849a1b8+f8b568069f,22.0.1-3-gaaec9c0+c5c846a8b1,22.0.1-32-g5ddfab5d3+60ce4897b0,22.0.1-4-g037fbe1+64e601228d,22.0.1-4-g8623105+b8044ec9de,22.0.1-5-g096abc9+d18c45d440,22.0.1-5-g15c806e+57f5c03693,22.0.1-7-gba73697+57f5c03693,master-g6e05de7fdc+c1283a92b8,master-g72cdda8301+729191ecac,w.2021.39
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