22 __all__ = [
"displayAstrometry", 
"plotAstrometry"]
 
   33 def displayAstrometry(refCat=None, sourceCat=None, distortedCentroidKey=None, bbox=None, exposure=None,
 
   34                       matches=None, frame=1, title="", pause=True):
 
   35     """Show an astrometry debug image. 
   39     refCat : `lsst.afw.table.SimpleCatalog` 
   40         reference object catalog; must have fields "centroid_x" an 
   42     sourceCat : `lsst.afw.table.SourceCatalg` 
   43         source catalog; must have field "slot_Centroid_x" and "slot_Centroid_y" 
   44     distortedCentroidKey : `lsst.afw.table.Key` 
   45         key for sourceCat with field to use for distorted positions 
   46     exposure : `lsst.afw.image.Exposure` 
   48     bbox : `lsst.geom.Box2I` 
   49         bounding box of exposure; Used if the exposure is `None` 
   50     matches : `list` of `lsst.afw.table.ReferenceMatch` 
   51         List of matched objects 
   53         frame number for display 
   57         pause for inspection of display? This is done by dropping into pdb. 
   62     - reference objects in refCat are shown as red X 
   63     - sources in sourceCat are shown as green + 
   64     - distorted sources in sourceCat (position given by distortedCentroidKey) 
   66     - matches are shown as a yellow circle around the source and a yellow line 
   67       connecting the reference object and source 
   68     - if both exposure and bbox are `None`, no image is displayed 
   71     disp = afwDisplay.getDisplay(frame=frame)
 
   73     if exposure 
is not None:
 
   74         disp.mtv(exposure, title=title)
 
   75     elif bbox 
is not None:
 
   76         disp.mtv(exposure=ExposureF(bbox), title=title)
 
   78     with disp.Buffering():
 
   79         if refCat 
is not None:
 
   80             refCentroidKey = 
Point2DKey(refCat.schema[
"centroid"])
 
   82                 rx, ry = refObj.get(refCentroidKey)
 
   83                 disp.dot(
"x", rx, ry, size=10, ctype=afwDisplay.RED)
 
   85         if sourceCat 
is not None:
 
   86             sourceCentroidKey = 
Point2DKey(sourceCat.schema[
"slot_Centroid"])
 
   87             for source 
in sourceCat:
 
   88                 sx, sy = source.get(sourceCentroidKey)
 
   89                 disp.dot(
"+", sx, sy, size=10, ctype=afwDisplay.GREEN)
 
   90                 if distortedCentroidKey 
is not None:
 
   91                     dx, dy = source.get(distortedCentroidKey)
 
   92                     disp.dot(
"o", dx, dy, size=10, ctype=afwDisplay.GREEN)
 
   93                     disp.line([(sx, sy), (dx, dy)], ctype=afwDisplay.GREEN)
 
   95         if matches 
is not None:
 
   96             refCentroidKey = 
Point2DKey(matches[0].first.schema[
"centroid"])
 
   97             sourceCentroidKey = 
Point2DKey(matches[0].second.schema[
"slot_Centroid"])
 
   98             radArr = np.ndarray(len(matches))
 
  100             for i, m 
in enumerate(matches):
 
  101                 refCentroid = m.first.get(refCentroidKey)
 
  102                 sourceCentroid = m.second.get(sourceCentroidKey)
 
  103                 radArr[i] = math.hypot(*(refCentroid - sourceCentroid))
 
  104                 sx, sy = sourceCentroid
 
  105                 disp.dot(
"o", sx, sy, size=10, ctype=afwDisplay.YELLOW)
 
  106                 disp.line([refCentroid, sourceCentroid], ctype=afwDisplay.YELLOW)
 
  108             print(
"<match radius> = %.4g +- %.4g [%d matches]" %
 
  109                   (radArr.mean(), radArr.std(), len(matches)))
 
  112         print(
"Dropping into debugger to allow inspection of display. Type 'continue' when done.")
 
  127     """Plot reference objects, sources and matches 
  131     matches : `list` of `lsst.afw.table.ReferenceMatch` 
  133     refCat : `lsst.afw.table.SimpleCatalog` 
  134         reference object catalog, or None to not plot reference objects 
  135     sourceCat : `lsst.afw.table.SourceCatalog` 
  136         source catalog, or None to not plot sources 
  138         pyplot marker for reference objects 
  140         pyplot color for reference objects 
  142         pyplot marker for sources 
  144         pyplot color for sources 
  146         color for matches; can be a constant 
  147         or a function taking one match and returning a string 
  153     - reference objects in refCat are shown as red X 
  154     - sources in sourceCat are shown as green + 
  155     - matches are shown as a yellow circle around the source and a line 
  156       connecting the reference object to the source 
  159     import matplotlib.pyplot 
as plt
 
  160     refSchema = matches[0][0].schema
 
  161     refCentroidKey = 
Point2DKey(refSchema[
"centroid"])
 
  162     srcSchema = matches[0][1].schema
 
  163     srcCentroidKey = 
Point2DKey(srcSchema[
"slot_Centroid"])
 
  165     if refCat 
is not None:
 
  166         refXArr, refYArr = 
list(zip(*[ref.get(refCentroidKey) 
for ref 
in refCat]))
 
  167         plt.plot(refXArr, refYArr, marker=refMarker, color=refColor, linestyle=
"")
 
  169     if sourceCat 
is not None:
 
  170         srcXArr, srcYArr = 
list(zip(*[src.get(srcCentroidKey) 
for src 
in sourceCat]))
 
  171         plt.plot(srcXArr, srcYArr, marker=sourceMarker, color=sourceColor, linestyle=
"")
 
  173     def makeLineSegmentData(refXYArr, srcXYArr, colorArr):
 
  174         """Make a list of line segement data 
  176         This is used to draw line segements between ref and src positions in the specified color 
  180         The returned data has the format: 
  181          [(refX0, srcX0), (refY0, srcY0), color0, (refX1, srcX1), (refY1, srcY1), color1,...] 
  183         if len(refXYArr) != len(srcXYArr):
 
  184             raise RuntimeError(
"len(refXYArr) = %d != %d = len(srcXYArr)" %
 
  185                                (len(refXYArr), len(srcXYArr)))
 
  186         if len(refXYArr) != len(colorArr):
 
  187             raise RuntimeError(
"len(refXYArr) = %d != %d = len(colorArr)" %
 
  188                                (len(refXYArr), len(colorArr)))
 
  190         refXArr, refYArr = 
list(zip(*refXYArr))
 
  191         srcXArr, srcYArr = 
list(zip(*srcXYArr))
 
  192         refSrcXArr = 
list(zip(refXArr, srcXArr))
 
  193         refSrcYArr = 
list(zip(refYArr, srcYArr))
 
  195         for xycolor 
in zip(refSrcXArr, refSrcYArr, colorArr):
 
  200     refXYArr, srcXYArr = \
 
  201         list(zip(*[(match[0].get(refCentroidKey), match[1].get(srcCentroidKey)) 
for match 
in matches]))
 
  203     def plotSourceCircles(matches, color):
 
  204         srcXYArr = [match[1].get(srcCentroidKey) 
for match 
in matches]
 
  205         srcXArr, srcYArr = 
list(zip(*srcXYArr))
 
  206         plt.plot(srcXArr, srcYArr, 
"o", mec=color, mfc=
"none", ms=10,)
 
  208     if callable(matchColor):
 
  210         matchColorArr = [matchColor(match) 
for match 
in matches]
 
  213         matchColorSet = 
set(matchColorArr)
 
  214         for color 
in matchColorSet:
 
  215             subMatches = [match 
for match 
in matches 
if matchColor(match) == color]
 
  216             plotSourceCircles(subMatches, color=color)
 
  218         matchColorArr = [matchColor]*len(refXYArr)
 
  219         plotSourceCircles(matches, color=matchColor)
 
  221     lineSegData = makeLineSegmentData(refXYArr, srcXYArr, matchColorArr)
 
  222     plt.plot(*lineSegData)