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