LSST Applications 24.1.5,g02d81e74bb+fa3a7a026e,g180d380827+a53a32eff8,g2079a07aa2+86d27d4dc4,g2305ad1205+c0501b3732,g295015adf3+7d3e92f0ec,g2bbee38e9b+0e5473021a,g337abbeb29+0e5473021a,g33d1c0ed96+0e5473021a,g3a166c0a6a+0e5473021a,g3ddfee87b4+5dd1654d75,g48712c4677+3bf1020dcb,g487adcacf7+065c13d9cf,g50ff169b8f+96c6868917,g52b1c1532d+585e252eca,g591dd9f2cf+d7ac436cfb,g5a732f18d5+53520f316c,g64a986408d+fa3a7a026e,g858d7b2824+fa3a7a026e,g8a8a8dda67+585e252eca,g99cad8db69+a5a909b84f,g9ddcbc5298+9a081db1e4,ga1e77700b3+15fc3df1f7,ga8c6da7877+4cf350ccb2,gb0e22166c9+60f28cb32d,gba4ed39666+c2a2e4ac27,gbb8dafda3b+f991a0b59f,gc120e1dc64+9ccbfdb8be,gc28159a63d+0e5473021a,gcf0d15dbbd+5dd1654d75,gd96a1ce819+42fd0ee607,gdaeeff99f8+f9a426f77a,ge6526c86ff+0d71447b4b,ge79ae78c31+0e5473021a,gee10cc3b42+585e252eca,gff1a9f87cc+fa3a7a026e
LSST Data Management Base Package
Loading...
Searching...
No Matches
display.py
Go to the documentation of this file.
1# This file is part of meas_astrom.
2#
3# Developed for the LSST Data Management System.
4# This product includes software developed by the LSST Project
5# (https://www.lsst.org).
6# See the COPYRIGHT file at the top-level directory of this distribution
7# for details of code ownership.
8#
9# This program is free software: you can redistribute it and/or modify
10# it under the terms of the GNU General Public License as published by
11# the Free Software Foundation, either version 3 of the License, or
12# (at your option) any later version.
13#
14# This program is distributed in the hope that it will be useful,
15# but WITHOUT ANY WARRANTY; without even the implied warranty of
16# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17# GNU General Public License for more details.
18#
19# You should have received a copy of the GNU General Public License
20# along with this program. If not, see <https://www.gnu.org/licenses/>.
21
22__all__ = ["displayAstrometry", "plotAstrometry"]
23
24import math
25
26import numpy as np
27
28import lsst.afw.display as afwDisplay
29from lsst.afw.image import ExposureF
30from lsst.afw.table import Point2DKey
31
32
33def 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.
36
37 Parameters
38 ----------
39 refCat : `lsst.afw.table.SimpleCatalog`
40 reference object catalog; must have fields "centroid_x" an
41 "centroid_y"
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`
47 exposure to display
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
52 frame : `int`
53 frame number for display
54 title : `str`
55 title for display
56 pause : `bool`
57 pause for inspection of display? This is done by dropping into pdb.
58
59 Notes
60 -----
61
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)
65 are shown as green o
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
69
70 """
71 disp = afwDisplay.getDisplay(frame=frame)
72
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)
77
78 with disp.Buffering():
79 if refCat is not None:
80 refCentroidKey = Point2DKey(refCat.schema["centroid"])
81 for refObj in refCat:
82 rx, ry = refObj.get(refCentroidKey)
83 disp.dot("x", rx, ry, size=10, ctype=afwDisplay.RED)
84
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)
94
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))
99
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)
107
108 print("<match radius> = %.4g +- %.4g [%d matches]" %
109 (radArr.mean(), radArr.std(), len(matches)))
110
111 if pause:
112 print("Dropping into debugger to allow inspection of display. Type 'continue' when done.")
113 import pdb
114 pdb.set_trace()
115
116
118 matches,
119 refCat=None,
120 sourceCat=None,
121 refMarker="x",
122 refColor="r",
123 sourceMarker="+",
124 sourceColor="g",
125 matchColor="y"
126):
127 """Plot reference objects, sources and matches
128
129 Parameters
130 ----------
131 matches : `list` of `lsst.afw.table.ReferenceMatch`
132 list of matches
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
137 refMarker : `str`
138 pyplot marker for reference objects
139 refColor : `str`
140 pyplot color for reference objects
141 sourceMarker : `str`
142 pyplot marker for sources
143 sourceColor : `str`
144 pyplot color for sources
145 matchColor : `str`
146 color for matches; can be a constant
147 or a function taking one match and returning a string
148
149 Notes
150 -----
151 By default:
152
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
157 """
158 # delay importing plt to give users a chance to set the backend before calling this function
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"])
164
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="")
168
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="")
172
173 def makeLineSegmentData(refXYArr, srcXYArr, colorArr):
174 """Make a list of line segement data
175
176 This is used to draw line segements between ref and src positions in the specified color
177
178 Notes
179 -----
180 The returned data has the format:
181 [(refX0, srcX0), (refY0, srcY0), color0, (refX1, srcX1), (refY1, srcY1), color1,...]
182 """
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)))
189
190 refXArr, refYArr = list(zip(*refXYArr))
191 srcXArr, srcYArr = list(zip(*srcXYArr))
192 refSrcXArr = list(zip(refXArr, srcXArr))
193 refSrcYArr = list(zip(refYArr, srcYArr))
194 dataList = []
195 for xycolor in zip(refSrcXArr, refSrcYArr, colorArr):
196 for val in xycolor:
197 dataList.append(val)
198 return dataList
199
200 refXYArr, srcXYArr = \
201 list(zip(*[(match[0].get(refCentroidKey), match[1].get(srcCentroidKey)) for match in matches]))
202
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,)
207
208 if callable(matchColor):
209 # different matches have different colors
210 matchColorArr = [matchColor(match) for match in matches]
211
212 # plot circles for each color separately
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)
217 else:
218 matchColorArr = [matchColor]*len(refXYArr)
219 plotSourceCircles(matches, color=matchColor)
220
221 lineSegData = makeLineSegmentData(refXYArr, srcXYArr, matchColorArr)
222 plt.plot(*lineSegData)
223
224 plt.show()
daf::base::PropertySet * set
Definition fits.cc:931
displayAstrometry(refCat=None, sourceCat=None, distortedCentroidKey=None, bbox=None, exposure=None, matches=None, frame=1, title="", pause=True)
Definition display.py:34
plotAstrometry(matches, refCat=None, sourceCat=None, refMarker="x", refColor="r", sourceMarker="+", sourceColor="g", matchColor="y")
Definition display.py:126