LSSTApplications  11.0-13-gbb96280,12.1+18,12.1+7,12.1-1-g14f38d3+72,12.1-1-g16c0db7+5,12.1-1-g5961e7a+84,12.1-1-ge22e12b+23,12.1-11-g06625e2+4,12.1-11-g0d7f63b+4,12.1-19-gd507bfc,12.1-2-g7dda0ab+38,12.1-2-gc0bc6ab+81,12.1-21-g6ffe579+2,12.1-21-gbdb6c2a+4,12.1-24-g941c398+5,12.1-3-g57f6835+7,12.1-3-gf0736f3,12.1-37-g3ddd237,12.1-4-gf46015e+5,12.1-5-g06c326c+20,12.1-5-g648ee80+3,12.1-5-gc2189d7+4,12.1-6-ga608fc0+1,12.1-7-g3349e2a+5,12.1-7-gfd75620+9,12.1-9-g577b946+5,12.1-9-gc4df26a+10
LSSTDataManagementBasePackage
display.py
Go to the documentation of this file.
1 #
2 # LSST Data Management System
3 # Copyright 2008-2016 AURA/LSST.
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 from __future__ import absolute_import, division, print_function
23 from builtins import zip
24 import math
25 
26 import numpy as np
27 
28 import lsst.afw.display as afwDisplay
29 from lsst.afw.image import ExposureF
30 from lsst.afw.table import Point2DKey
31 
32 __all__ = ["displayAstrometry", "plotAstrometry"]
33 
34 
35 def displayAstrometry(refCat=None, sourceCat=None, distortedCentroidKey=None, bbox=None, exposure=None,
36  matches=None, frame=1, title="", pause=True):
37  """Show an astrometry debug image
38 
39  - reference objects in refCat are shown as red X
40  - sources in sourceCat are shown as green +
41  - distorted sources in sourceCat (position given by distortedCentroidKey) are shown as green o
42  - matches are shown as a yellow circle around the source and a yellow line
43  connecting the reference object and source
44  - if both exposure and bbox are None, no image is displayed
45 
46  @param[in] refCat reference object catalog; must have fields "centroid_x" and "centroid_y"
47  @param[in] sourceCat source catalog; must have field "slot_Centroid_x" and "slot_Centroid_y"
48  @param[in] distortedCentroidKey key for sourceCat with field to use for distorted positions, or None
49  @param[in] exposure exposure to display, or None for a blank exposure
50  @param[in] bbox bounding box of exposure; used if exposure is None for a blank image
51  @param[in] matches list of matches (an lsst.afw.table.ReferenceMatchVector), or None
52  @param[in] frame frame number for ds9 display
53  @param[in] title title for ds9 display
54  @param[in] pause pause for inspection of display? This is done by dropping into pdb.
55  """
56  disp = afwDisplay.getDisplay(frame)
57 
58  if exposure is not None:
59  disp.mtv(exposure, title=title)
60  elif bbox is not None:
61  disp.mtv(exposure=ExposureF(bbox), title=title)
62 
63  with disp.Buffering():
64  if refCat is not None:
65  refCentroidKey = Point2DKey(refCat.schema["centroid"])
66  for refObj in refCat:
67  rx, ry = refObj.get(refCentroidKey)
68  disp.dot("x", rx, ry, size=10, ctype=afwDisplay.RED)
69 
70  if sourceCat is not None:
71  sourceCentroidKey = Point2DKey(sourceCat.schema["slot_Centroid"])
72  for source in sourceCat:
73  sx, sy = source.get(sourceCentroidKey)
74  disp.dot("+", sx, sy, size=10, ctype=afwDisplay.GREEN)
75  if distortedCentroidKey is not None:
76  dx, dy = source.get(distortedCentroidKey)
77  disp.dot("o", dx, dy, size=10, ctype=afwDisplay.GREEN)
78  disp.line([(sx, sy), (dx, dy)], ctype=afwDisplay.GREEN)
79 
80  if matches is not None:
81  refCentroidKey = Point2DKey(matches[0].first.schema["centroid"])
82  sourceCentroidKey = Point2DKey(matches[0].second.schema["slot_Centroid"])
83  radArr = np.ndarray(len(matches))
84 
85  for i, m in enumerate(matches):
86  refCentroid = m.first.get(refCentroidKey)
87  sourceCentroid = m.second.get(sourceCentroidKey)
88  radArr[i] = math.hypot(*(refCentroid - sourceCentroid))
89  sx, sy = sourceCentroid
90  disp.dot("o", sx, sy, size=10, ctype=afwDisplay.YELLOW)
91  disp.line([refCentroid, sourceCentroid], ctype=afwDisplay.YELLOW)
92 
93  print("<match radius> = %.4g +- %.4g [%d matches]" %
94  (radArr.mean(), radArr.std(), len(matches)))
95 
96  if pause:
97  print("Dropping into debugger to allow inspection of display. Type 'continue' when done.")
98  import pdb
99  pdb.set_trace()
100 
101 
102 def plotAstrometry(
103  matches,
104  refCat=None,
105  sourceCat=None,
106  refMarker="x",
107  refColor="r",
108  sourceMarker="+",
109  sourceColor="g",
110  matchColor="y"
111 ):
112  """Plot reference objects, sources and matches
113 
114  By default:
115  - reference objects in refCat are shown as red X
116  - sources in sourceCat are shown as green +
117  - matches are shown as a yellow circle around the source and a line
118  connecting the reference object to the source
119 
120  @param[in] matches list of matches
121  @param[in] refCat reference object catalog, or None to not plot reference objects
122  @param[in] sourceCat source catalog, or None to not plot sources
123  @param[in] refMarker pyplot marker for reference objects
124  @param[in] refColor pyplot color for reference objects
125  @param[in] sourceMarker pyplot marker for sources
126  @param[in] sourceColor pyplot color for sources
127  @param[in] matchColor color for matches; can be a constant
128  or a function taking one match and returning a string
129  """
130  # delay importing plt to give users a chance to set the backend before calling this function
131  import matplotlib.pyplot as plt
132  refSchema = matches[0][0].schema
133  refCentroidKey = Point2DKey(refSchema["centroid"])
134  srcSchema = matches[0][1].schema
135  srcCentroidKey = Point2DKey(srcSchema["slot_Centroid"])
136 
137  if refCat is not None:
138  refXArr, refYArr = list(zip(*[ref.get(refCentroidKey) for ref in refCat]))
139  plt.plot(refXArr, refYArr, marker=refMarker, color=refColor, linestyle="")
140 
141  if sourceCat is not None:
142  srcXArr, srcYArr = list(zip(*[src.get(srcCentroidKey) for src in sourceCat]))
143  plt.plot(srcXArr, srcYArr, marker=sourceMarker, color=sourceColor, linestyle="")
144 
145  def makeLineSegmentData(refXYArr, srcXYArr, colorArr):
146  """Make a list of line segement data
147 
148  This is used to draw line segements between ref and src positions in the specified color
149 
150  The returned data has the format:
151  [(refX0, srcX0), (refY0, srcY0), color0, (refX1, srcX1), (refY1, srcY1), color1,...]
152  """
153  if len(refXYArr) != len(srcXYArr):
154  raise RuntimeError("len(refXYArr) = %d != %d = len(srcXYArr)" %
155  (len(refXYArr), len(srcXYArr)))
156  if len(refXYArr) != len(colorArr):
157  raise RuntimeError("len(refXYArr) = %d != %d = len(colorArr)" %
158  (len(refXYArr), len(colorArr)))
159 
160  refXArr, refYArr = list(zip(*refXYArr))
161  srcXArr, srcYArr = list(zip(*srcXYArr))
162  refSrcXArr = list(zip(refXArr, srcXArr))
163  refSrcYArr = list(zip(refYArr, srcYArr))
164  dataList = []
165  for xycolor in zip(refSrcXArr, refSrcYArr, colorArr):
166  for val in xycolor:
167  dataList.append(val)
168  return dataList
169 
170  refXYArr, srcXYArr = \
171  list(zip(*[(match[0].get(refCentroidKey), match[1].get(srcCentroidKey)) for match in matches]))
172 
173  def plotSourceCircles(matches, color):
174  srcXYArr = [match[1].get(srcCentroidKey) for match in matches]
175  srcXArr, srcYArr = list(zip(*srcXYArr))
176  plt.plot(srcXArr, srcYArr, "o", mec=color, mfc="none", ms=10,)
177 
178  if callable(matchColor):
179  # different matches have different colors
180  matchColorArr = [matchColor(match) for match in matches]
181 
182  # plot circles for each color separately
183  matchColorSet = set(matchColorArr)
184  for color in matchColorSet:
185  subMatches = [match for match in matches if matchColor(match) == color]
186  plotSourceCircles(subMatches, color=color)
187  else:
188  matchColorArr = [matchColor]*len(refXYArr)
189  plotSourceCircles(matches, color=matchColor)
190 
191  lineSegData = makeLineSegmentData(refXYArr, srcXYArr, matchColorArr)
192  plt.plot(*lineSegData)
193 
194  plt.show()
PointKey< double > Point2DKey
Definition: aggregates.h:111