Coverage for metadetect / lsst / vis.py: 8%
164 statements
« prev ^ index » next coverage.py v7.12.0, created at 2025-12-19 01:38 -0800
« prev ^ index » next coverage.py v7.12.0, created at 2025-12-19 01:38 -0800
1import numpy as np
2from matplotlib import pyplot as mplt
3from .util import copy_mbexp
5DEFAULT_STRETCH = 1.25
6DEFAULT_Q = 7.5
7SIZE = 16
8COLOR = 'red'
9EDGECOLOR = 'white'
12def show_exp(exp, mess=None, use_mpl=False, sources=None):
13 """
14 show the image in ds9
16 Parameters
17 ----------
18 exp: Exposure
19 The image to show
20 mess: str, optional
21 A message to use as title to plot
22 """
23 import matplotlib.pyplot as mplt
24 import lsst.afw.display as afw_display
26 if use_mpl:
27 fig, axs = mplt.subplots(ncols=3)
28 image = exp.image.array
30 noise = np.sqrt(np.median(exp.variance.array))
32 noise = np.sqrt(np.median(exp.variance.array))
33 minval = 0.1 * noise
34 axs[0].imshow(np.log(image.clip(min=minval)))
36 axs[1].imshow(exp.variance.array)
37 axs[1].set_title('variance')
39 axs[2].imshow(exp.mask.array)
40 axs[2].set_title('mask')
42 if sources is not None:
43 from pprint import pprint
44 bbox = exp.getBBox()
45 pprint(exp.mask.getMaskPlaneDict())
46 axs[0].scatter(
47 sources['base_SdssCentroid_x'] - bbox.beginX,
48 sources['base_SdssCentroid_y'] - bbox.beginY,
49 color='red',
50 )
52 if mess is not None:
53 fig.suptitle(mess)
55 mplt.show()
57 else:
59 display = afw_display.getDisplay(backend='ds9')
60 display.mtv(exp)
61 display.scale('log', 'minmax')
63 prompt = 'hit enter'
64 if mess is not None:
65 prompt = '%s: (%s)' % (mess, prompt)
67 input(prompt)
70def show_mbexp(
71 mbexp, stretch=DEFAULT_STRETCH, q=DEFAULT_Q, mess=None, ax=None,
72 sources=None,
73 show=True,
74):
75 """
76 visialize a MultibandExposure
78 Parameters
79 ----------
80 mbexp: lsst.afw.image.MultibandExposure
81 MutibandExposure to visualize. Currently must be at least
82 three bands.
83 stretch: float, optional
84 The stretch parameter for
85 astropy.visualization.lupton_rgb. import AsinhMapping
86 q: float, optional
87 The Q parameter for
88 astropy.visualization.lupton_rgb. import AsinhMapping
89 mess: str, optional
90 A message to use as title to plot
91 ax: matplotlib plot axis
92 If sent use this axis for plot rather than creating a
93 new one
94 show: bool, optional
95 If set to True, show on the screen.
97 Returns
98 -------
99 The axis used for plotting
100 """
102 image = mbexp.image.array
104 if ax is None:
105 fig, ax = mplt.subplots()
107 if image.shape[0] >= 3:
108 import scarlet
109 from astropy.visualization.lupton_rgb import AsinhMapping
111 timage = image[:3, :, :].clip(min=0)
113 asinh = AsinhMapping(
114 minimum=0,
115 stretch=stretch,
116 Q=q,
117 )
119 img_rgb = scarlet.display.img_to_rgb(timage, norm=asinh)
121 ax.imshow(img_rgb)
123 else:
124 noise = np.sqrt(np.median(mbexp.variance.array))
125 if image.shape[0] == 1:
126 timage = image[0]
127 else:
128 timage = image.sum(axis=0)
130 noise = np.sqrt(np.median(mbexp.variance.array))
131 minval = 0.1 * noise
132 ax.imshow(np.log(timage.clip(min=minval)))
134 if sources is not None:
135 x, y = _extract_xy(mbexp, sources)
136 ax.scatter(
137 x, y,
138 s=SIZE, color=COLOR, edgecolor=EDGECOLOR,
139 )
141 if mess is not None:
142 ax.set_title(mess)
144 if show:
145 mplt.show()
147 return ax
150def _extract_xy(mbexp, sources):
151 if isinstance(sources, np.ndarray):
152 y = sources['row'] - sources['row0']
153 x = sources['col'] - sources['col0']
154 else:
155 bbox = mbexp.getBBox()
156 x0 = bbox.getBeginX()
157 y0 = bbox.getBeginY()
158 x = []
159 y = []
160 for source in sources[mbexp.bands[0]]:
161 peak = source.getFootprint().getPeaks()[0]
162 cen = peak.getCentroid()
163 x.append(cen.getX() - x0)
164 y.append(cen.getY() - y0)
166 return x, y
169def compare_mbexp(
170 mbexp, model, sources=None, stretch=DEFAULT_STRETCH, q=DEFAULT_Q,
171):
172 """
173 compare two MultibandExposure with residuals
175 Parameters
176 ----------
177 mbexp: lsst.afw.image.MultibandExposure
178 MutibandExposure to visualize. Currently must be at least
179 three bands.
180 model: lsst.afw.image.MultibandExposure
181 MutibandExposure to visualize. Currently must be at least
182 three bands.
183 stretch: float, optional
184 The stretch parameter for
185 astropy.visualization.lupton_rgb. import AsinhMapping
186 q: float, optional
187 The Q parameter for
188 astropy.visualization.lupton_rgb. import AsinhMapping
189 """
191 if isinstance(model, list):
192 mold = model
193 model = copy_mbexp(mbexp)
194 for iband, band in enumerate(model.bands):
195 model[band].image.array[:, :] = mold[iband]
197 fig, axs = mplt.subplots(nrows=2, ncols=2, figsize=(12, 12))
198 show_mbexp(
199 mbexp, stretch=stretch, q=q, mess='data', ax=axs[0, 0], show=False,
200 sources=sources,
201 )
202 show_mbexp(
203 model, stretch=stretch, q=q, mess='model', ax=axs[0, 1], show=False,
204 sources=sources,
205 )
206 axs[1, 1].axis('off')
208 c = copy_mbexp(mbexp)
209 c.image.array -= model.image.array
210 show_mbexp(
211 c, stretch=stretch, q=q, mess='data - model', ax=axs[1, 0], show=False,
212 sources=sources,
213 )
214 mplt.show()
217def show_three_mbexp(
218 mbexp_list,
219 labels=None,
220 stretch=DEFAULT_STRETCH, q=DEFAULT_Q, mess=None, ax=None,
221):
222 """
223 show three different MultibandExposure
225 Parameters
226 ----------
227 mbexp_list: [lsst.afw.image.MultibandExposure]
228 List of MutibandExposure to visualize. Currently must be at least
229 three bands.
230 labels: list, optional
231 Listof labels for a legend
232 stretch: float, optional
233 The stretch parameter for
234 astropy.visualization.lupton_rgb. import AsinhMapping
235 q: float, optional
236 The Q parameter for
237 astropy.visualization.lupton_rgb. import AsinhMapping
238 ax: matplotlib plot axis
239 If sent use this axis for plot rather than creating a
240 new one
241 mess: str, optional
242 A message to use as title to plot
243 """
245 assert len(mbexp_list) == 3
246 if labels is None:
247 labels = ['image 1', 'image 2', 'image 3']
248 assert len(labels) == 3
250 fig, axs = mplt.subplots(nrows=2, ncols=2, figsize=(12, 12))
251 show_mbexp(
252 mbexp_list[0], stretch=stretch, q=q, ax=axs[0, 0], show=False,
253 mess=labels[0],
254 )
255 show_mbexp(
256 mbexp_list[1], stretch=stretch, q=q, ax=axs[0, 1], show=False,
257 mess=labels[1],
258 )
259 show_mbexp(
260 mbexp_list[2], stretch=stretch, q=q, ax=axs[1, 0], show=False,
261 mess=labels[2],
262 )
263 axs[1, 1].axis('off')
265 mplt.show()
268def show_mbexp_demo(mbexp):
269 """
270 Show a few stretches, q values. Useful for choosing the stretch
271 you would like
273 Parameters
274 ----------
275 mbexp: lsst.afw.image.MultibandExposure
276 MutibandExposure to visualize. Currently must be at least
277 three bands.
278 """
279 from astropy.visualization.lupton_rgb import AsinhMapping
280 import scarlet
282 image = mbexp.image.array
284 # TODO repeat bands as needed
285 assert image.shape[0] >= 3, 'need at least 3 exposure for color'
287 # stretches = [0.1, 0.5, 1.0]
288 # qvals = [10, 20, 30] # noqa
289 stretches = [0.75, 1, 1.25]
290 qvals = [5, 7.5, 10] # noqa
292 fig, axs = mplt.subplots(len(stretches), len(qvals), figsize=(12, 12))
293 for ist, stretch in enumerate(stretches):
294 for iq, q in enumerate(Qvals): # noqa
295 asinh = AsinhMapping(
296 minimum=0,
297 stretch=stretch, Q=q,
298 )
299 img_rgb = scarlet.display.img_to_rgb(image, norm=asinh)
300 axs[ist, iq].imshow(img_rgb)
301 axs[ist, iq].set_title(f'Stretch {stretch}, Q {q}')
303 mplt.show()
306def show_multi_mbobs(mbobs):
307 """
308 Show images from a ngmix.MultiBandObsList
310 Parameters
311 ----------
312 mbobs: ngmix.MultiBandObsList
313 The data
314 """
315 import matplotlib.pyplot as mplt
317 nband = len(mbobs)
319 types = ['image', 'weight', 'bmask']
320 ntypes = len(types)
321 fig, axs = mplt.subplots(nrows=ntypes, ncols=nband)
323 for iband, obslist in enumerate(mbobs):
325 obs = obslist[0]
327 for itype, type in enumerate(types):
329 im = getattr(obs, type)
331 axs[iband, itype].imshow(im)
332 axs[iband, itype].set_title(f'band {iband} {type}')
334 mplt.show()
337def show_multi_mbexp(mbexp, sources=None):
338 """
339 Show images from a ngmix.MultiBandObsList
341 Parameters
342 ----------
343 mbexp: lsst.afw.image.MultibandExposure
344 The data
345 """
346 import matplotlib.pyplot as mplt
348 nband = len(mbexp)
350 ncols = 3
351 fig, axs = mplt.subplots(nrows=nband, ncols=ncols, squeeze=False)
353 if sources is not None:
354 x, y = _extract_xy(mbexp, sources)
356 for iband, band in enumerate(mbexp.bands):
357 exp = mbexp[band]
359 noise = np.sqrt(np.median(exp.variance.array))
360 minval = 0.1 * noise
361 axs[iband, 0].imshow(np.log(exp.image.array.clip(min=minval)))
362 axs[iband, 0].set_title(f'band {iband} image')
364 axs[iband, 1].imshow(exp.variance.array)
365 axs[iband, 1].set_title(f'band {iband} var')
367 axs[iband, 2].imshow(exp.mask.array)
368 axs[iband, 2].set_title(f'band {iband} mask')
370 if sources is not None:
371 for col in range(ncols):
372 axs[iband, col].scatter(
373 x, y,
374 s=SIZE, color=COLOR, edgecolor=EDGECOLOR,
375 )
377 mplt.show()
380def show_image_and_mask(mbexp, band=0):
381 """
382 Show images from a ngmix.MultiBandObsList
384 Parameters
385 ----------
386 mbexp: lsst.afw.image.MultibandExposure
387 The data
388 """
389 import matplotlib.pyplot as mplt
391 fig, axs = mplt.subplots(ncols=2)
392 axs[0].axis('off')
393 axs[1].axis('off')
395 bname = mbexp.bands[band]
396 exp = mbexp[bname]
398 noise = np.sqrt(np.median(exp.variance.array))
399 minval = 0.1 * noise
400 axs[0].imshow(np.log(exp.image.array.clip(min=minval)))
401 axs[1].imshow(exp.mask.array)
402 mplt.show()