23 "WHITE",
"BLACK",
"RED",
"GREEN",
"BLUE",
"CYAN",
"MAGENTA",
"YELLOW",
"ORANGE",
"IGNORE",
24 "Display",
"Event",
"noop_callback",
"h_callback",
25 "setDefaultBackend",
"getDefaultBackend",
26 "setDefaultFrame",
"getDefaultFrame",
"incrDefaultFrame",
27 "setDefaultMaskTransparency",
"setDefaultMaskPlaneColor",
28 "getDisplay",
"delAllDisplays",
38logger = logging.getLogger(__name__)
54 """Return the ``DisplayImpl`` for the named backend
59 Name of device. Should be importable, either absolutely or relative to lsst.display
63 Arguments passed to DisplayImpl.__init__
65 Keywords arguments passed to DisplayImpl.__init__
73 import lsst.afw.display as afwDisplay
74 display = afwDisplay.Display(backend="ds9")
80 _makeDisplayImpl(..., "ds9", 1)
82 and import the ds9 implementation of ``DisplayImpl`` from `lsst.display.ds9`
86 candidateBackends = (f
"lsst.display.{backend}", backend, f
".{backend}", f
"lsst.afw.display.{backend}")
87 for dt
in candidateBackends:
91 if dt.startswith(
"."):
92 impargs[
"package"] =
"lsst.display"
94 _disp = importlib.import_module(dt, **impargs)
97 if hasattr(_disp,
"DisplayImpl"):
101 except (ImportError, SystemError)
as e:
107 if not _disp
or not hasattr(_disp.DisplayImpl,
"_show"):
109 e = ImportError(f
"Could not load the requested backend: {backend} "
110 f
"(tried {', '.join(candidateBackends)}, but none worked).")
117 _impl = _disp.DisplayImpl(display, *args, **kwargs)
118 if not hasattr(_impl,
"frame"):
119 _impl.frame = display.frame
127 """Create an object able to display images and overplot glyphs.
132 An identifier for the display.
134 The backend to use (defaults to value set by setDefaultBackend()).
136 Arguments to pass to the backend.
139 _defaultBackend =
None
141 _defaultMaskPlaneColor = dict(
148 DETECTED_NEGATIVE=CYAN,
155 _defaultMaskTransparency = {}
156 _defaultImageColormap =
"gray"
158 def __init__(self, frame=None, backend=None, **kwargs):
163 if Display._defaultBackend
is None:
169 backend = Display._defaultBackend
183 for ik
in range(ord(
'a'), ord(
'z') + 1):
188 for k
in (
'Return',
'Shift_L',
'Shift_R'):
191 for k
in (
'q',
'Escape'):
194 def _h_callback(k, x, y):
199 print(
" %-6s %s" % (k, doc.split(
"\n")[0]
if doc
else "???"))
203 Display._displays[frame] = self
206 """Support for python's with statement.
211 """Support for python's with statement.
219 """Return the attribute of ``self._impl``, or ``._impl`` if it is
225 name of the attribute requested.
230 the attribute of self._impl for the requested name.
234 return object.__getattr__(self, name)
236 if not (hasattr(self,
"_impl")
and self.
_impl):
237 raise AttributeError(
"Device has no _impl attached")
240 return getattr(self.
_impl, name)
241 except AttributeError:
242 raise AttributeError(
243 f
"Device {self.name} has no attribute \"{name}\"")
246 if getattr(self,
"_impl",
None)
is not None:
251 if self.
frame in Display._displays:
252 del Display._displays[self.
frame]
256 """The backend's verbosity.
258 return self.
_impl.verbose
263 self.
_impl.verbose = value
266 return f
"Display[{self.frame}]"
274 except Exception
as e:
276 f
"Unable to set backend to {backend}: \"{e}\"")
278 Display._defaultBackend = backend
282 return Display._defaultBackend
286 """Set the default frame for display.
288 Display._defaultFrame = frame
292 """Get the default frame for display.
294 return Display._defaultFrame
298 """Increment the default frame for display.
300 Display._defaultFrame += 1
301 return Display._defaultFrame
305 if hasattr(maskPlaneTransparency,
"copy"):
306 maskPlaneTransparency = maskPlaneTransparency.copy()
308 Display._defaultMaskTransparency = maskPlaneTransparency
312 """Set the default mapping from mask plane names to colors.
316 name : `str` or `dict`
317 Name of mask plane, or a dict mapping names to colors
318 If name is `None`, use the hard-coded default dictionary.
320 Desired color, or `None` if name is a dict.
324 name = Display._defaultMaskPlaneColor
326 if isinstance(name, dict):
328 for k, v
in name.items():
332 Display._defaultMaskPlaneColor[name] = color
336 """Set the default colormap for images.
341 Name of colormap, as interpreted by the backend.
345 The only colormaps that all backends are required to honor
346 (if they pay any attention to setImageColormap) are "gray" and "grey".
349 Display._defaultImageColormap = cmap
352 """Set the colormap to use for images.
357 Name of colormap, as interpreted by the backend.
361 The only colormaps that all backends are required to honor
362 (if they pay any attention to setImageColormap) are "gray" and "grey".
365 self.
_impl._setImageColormap(cmap)
368 def getDisplay(frame=None, backend=None, create=True, verbose=False, **kwargs):
369 """Return a specific `Display`, creating it if need be.
374 The desired frame (`None` => use defaultFrame
375 (see `~Display.setDefaultFrame`)).
377 create the specified frame using this backend (or the default if
378 `None`) if it doesn't already exist. If ``backend == ""``, it's an
379 error to specify a non-existent ``frame``.
381 create the display if it doesn't already exist.
383 Allow backend to be chatty.
385 keyword arguments passed to `Display` constructor.
389 frame = Display._defaultFrame
391 if frame
not in Display._displays:
393 raise RuntimeError(f
"Frame {frame} does not exist")
395 Display._displays[frame] =
Display(
396 frame, backend, verbose=verbose, **kwargs)
398 Display._displays[frame].verbose = verbose
399 return Display._displays[frame]
403 """Delete and close all known displays.
405 for disp
in list(Display._displays.values()):
407 Display._displays = {}
410 """A generator for "standard" colors.
415 Don't include `BLACK` and `WHITE`.
422 colorGenerator = interface.maskColorGenerator(omitBW=True)
424 print(p, next(colorGenerator))
426 _maskColors = [WHITE, BLACK, RED, GREEN,
427 BLUE, CYAN, MAGENTA, YELLOW, ORANGE]
432 color = _maskColors[i%len(_maskColors)]
433 if omitBW
and color
in (BLACK, WHITE):
439 """Request that mask plane name be displayed as color.
443 name : `str` or `dict`
444 Name of mask plane or a dictionary of name -> colorName.
446 The name of the color to use (must be `None` if ``name`` is a
449 Colors may be specified as any X11-compliant string (e.g.
450 `"orchid"`), or by one of the following constants in
451 `lsst.afw.display` : `BLACK`, `WHITE`, `RED`, `BLUE`,
452 `GREEN`, `CYAN`, `MAGENTA`, `YELLOW`.
454 If the color is "ignore" (or `IGNORE`) then that mask plane is not
457 The advantage of using the symbolic names is that the python
458 interpreter can detect typos.
460 if isinstance(name, dict):
462 for k, v
in name.items():
469 """Return the color associated with the specified mask plane name.
474 Desired mask plane; if `None`, return entire dict.
487 """Specify display's mask transparency (percent); or `None` to not set
488 it when loading masks.
490 if isinstance(transparency, dict):
492 for k, v
in transparency.items():
496 if transparency
is not None and (transparency < 0
or transparency > 100):
498 "Mask transparency should be in the range [0, 100]; clipping", file=sys.stderr)
504 if transparency
is not None:
505 self.
_impl._setMaskTransparency(transparency, name)
508 """Return the current display's mask transparency.
510 return self.
_impl._getMaskTransparency(name)
513 """Uniconify and Raise display.
517 Throws an exception if frame doesn't exit.
519 return self.
_impl._show()
521 def __addMissingMaskPlanes(self, mask):
522 """Assign colours to any missing mask planes found in mask.
524 maskPlanes = mask.getMaskPlaneDict()
525 nMaskPlanes =
max(maskPlanes.values()) + 1
529 for key
in maskPlanes:
530 planes[maskPlanes[key]] = key
533 for p
in range(nMaskPlanes):
538 def image(self, data, title="", wcs=None):
539 """Display an image on a display, with semi-transparent masks
540 overlaid, if available.
544 data : `lsst.afw.image.Exposure` or `lsst.afw.image.MaskedImage` or `lsst.afw.image.Image`
545 Image to display; Exposure and MaskedImage will show transparent
547 title : `str`, optional
548 Title for the display window.
549 wcs : `lsst.afw.geom.SkyWcs`, optional
550 World Coordinate System to align an `~lsst.afw.image.MaskedImage`
551 or `~lsst.afw.image.Image` to; raise an exception if ``data``
552 is an `~lsst.afw.image.Exposure`.
557 Raised if an Exposure is passed with a non-None wcs when the
558 ``wcs`` kwarg is also non-None.
560 Raised if data is an incompatible type.
562 if hasattr(data,
"getXY0"):
563 self.
_xy0 = data.getXY0()
570 raise RuntimeError(
"You may not specify a wcs with an Exposure")
571 data, wcs = data.getMaskedImage(), data.wcs
580 self.
_xy0 = data.getXY0()
583 self.
_impl._mtv(data,
None, wcs, title)
589 self.
_impl._mtv(afwImage.ImageI(data.array), data, wcs, title)
593 self.
_impl._mtv(data.image, data.mask, wcs, title)
595 raise TypeError(f
"Unsupported type {data!r}")
597 def mtv(self, data, title="", wcs=None):
598 """Display an image on a display, with semi-transparent masks
599 overlaid, if available.
603 Historical note: the name "mtv" comes from Jim Gunn's forth imageprocessing
604 system, Mirella (named after Mirella Freni); The "m" stands for Mirella.
606 self.
image(data, title, wcs)
609 """Context manager for buffering repeated display commands.
615 self.
_impl._buffer(
True)
618 self.
_impl._buffer(
False)
622 """Return a context manager that will buffer repeated display
623 commands, to e.g. speed up displaying points.
629 with display.Buffering():
630 display.dot("+", xc, yc)
635 """Flush any buffering that may be provided by the backend.
640 """Erase the specified display frame.
645 """Draw the sources from a catalog at their pixel centroid positions
646 as given by `~lsst.afw.table.Catalog.getX()` and
647 `~lsst.afw.table.Catalog.getY()`.
649 See `dot` for an explanation of ``symbol`` and available args/kwargs,
650 which are passed to `dot`.
654 catalog : `lsst.afw.table.Catalog`
655 Catalog to display centroids for. Must have valid `slot_Centroid`.
657 if not catalog.getCentroidSlot().
isValid():
658 raise RuntimeError(
"Catalog must have a valid `slot_Centroid` defined to get X/Y positions.")
662 self.
dot(symbol, pt.getX(), pt.getY(), **kwargs)
664 def dot(self, symb, c, r, size=2, ctype=None, origin=afwImage.PARENT, **kwargs):
665 """Draw a symbol onto the specified display frame.
681 Draw an ellipse with moments (Mxx, Mxy, Myy) (argument size is ignored)
682 `lsst.afw.geom.ellipses.BaseCore`
683 Draw the ellipse (argument size is ignored). N.b. objects
684 derived from `~lsst.afw.geom.ellipses.BaseCore` include
685 `~lsst.afw.geom.ellipses.Axes` and `~lsst.afw.geom.ellipses.Quadrupole`.
687 Interpreted as a string to be drawn.
689 The column and row where the symbol is drawn [0-based coordinates].
691 Size of symbol, in pixels.
693 The desired color, either e.g. `lsst.afw.display.RED` or a color name known to X11
694 origin : `lsst.afw.image.ImageOrigin`
695 Coordinate system for the given positions.
697 Extra keyword arguments to backend.
699 if isinstance(symb, int):
702 if origin == afwImage.PARENT
and self.
_xy0 is not None:
707 if isinstance(symb, afwGeom.ellipses.BaseCore)
or re.search(
r"^@:", symb):
709 mat = re.search(
r"^@:([^,]+),([^,]+),([^,]+)", symb)
714 mxx, mxy, myy = [float(_)
for _
in mat.groups()]
717 symb = afwGeom.ellipses.Axes(symb)
719 self.
_impl._dot(symb, c, r, size, ctype, **kwargs)
721 def line(self, points, origin=afwImage.PARENT, symbs=False, ctype=None, size=0.5):
722 """Draw a set of symbols or connect points
728 origin : `lsst.afw.image.ImageOrigin`
729 Coordinate system for the given positions.
730 symbs : `bool` or sequence
731 If ``symbs`` is `True`, draw points at the specified points using
732 the desired symbol, otherwise connect the dots.
734 If ``symbs`` supports indexing (which includes a string -- caveat
735 emptor) the elements are used to label the points.
737 ``ctype`` is the name of a color (e.g. 'red').
739 Size of points to create if `symbs` is passed.
745 symbs = len(points)*list(symbs)
747 for i, xy
in enumerate(points):
748 self.
dot(symbs[i], *xy, size=size, ctype=ctype)
751 if origin == afwImage.PARENT
and self.
_xy0 is not None:
753 _points = list(points)
754 for i, p
in enumerate(points):
755 _points[i] = (p[0] - x0, p[1] - y0)
758 self.
_impl._drawLines(points, ctype)
760 def scale(self, algorithm, min, max=None, unit=None, **kwargs):
761 """Set the range of the scaling from DN in the image to the image
767 Desired scaling (e.g. "linear" or "asinh").
769 Minimum value, or "minmax" or "zscale".
771 Maximum value (must be `None` for minmax|zscale).
773 Units for min and max (e.g. Percent, Absolute, Sigma; `None` if
776 Optional keyword arguments to the backend.
778 if min
in (
"minmax",
"zscale"):
779 assert max
is None, f
"You may not specify \"{min}\" and max"
780 assert unit
is None, f
"You may not specify \"{min}\" and unit"
782 raise RuntimeError(
"Please specify max")
784 self.
_impl._scale(algorithm, min, max, unit, **kwargs)
786 def zoom(self, zoomfac=None, colc=None, rowc=None, origin=afwImage.PARENT):
787 """Zoom frame by specified amount, optionally panning also
789 if (rowc
and colc
is None)
or (colc
and rowc
is None):
791 "Please specify row and column center to pan about")
794 if origin == afwImage.PARENT
and self.
_xy0 is not None:
799 self.
_impl._pan(colc, rowc)
801 if zoomfac
is None and rowc
is None:
804 if zoomfac
is not None:
805 self.
_impl._zoom(zoomfac)
807 def pan(self, colc=None, rowc=None, origin=afwImage.PARENT):
808 """Pan to a location.
813 Coordinates to pan to.
814 origin : `lsst.afw.image.ImageOrigin`
815 Coordinate system for the given positions.
821 self.
zoom(
None, colc, rowc, origin)
824 """Enter an interactive loop, listening for key presses or equivalent
825 UI actions in the display and firing callbacks.
827 Exit with ``q``, ``CR``, ``ESC``, or any equivalent UI action provided
828 in the display. The loop may also be exited by returning `True` from a
829 user-provided callback function.
831 interactFinished =
False
833 while not interactFinished:
834 ev = self.
_impl._getEvent()
837 k, x, y = ev.k, ev.x, ev.y
840 logger.warning(
"No callback registered for %s", k)
843 interactFinished = self.
_callbacks[k](k, x, y)
846 "Display._callbacks['%s'](%s,%s,%s) failed.", k, x, y)
849 """Set the callback for a key.
851 Backend displays may provide an equivalent graphical UI action, but
852 must make the associated key letter visible in the UI in some way.
857 The key to assign the callback to.
859 The callback assigned to ``k``.
861 Do not raise if ``k`` is already in use.
866 The callback previously assigned to ``k``.
873 f
"Key '{k}' is already in use by display, so I can't add a callback for it")
876 self.
_callbacks[k] = func
if func
else noop_callback
883 """Return all callback keys
888 If `True` only return keys that do something
891 not (onlyActive
and func == noop_callback)])
898 """A class to handle events such as key presses in image display windows.
901 def __init__(self, k, x=float(
'nan'), y=float(
'nan')):
907 return f
"{self.k} ({self.x:.2f}, {self.y:.2f}"
926 print(
"Enter q or <ESC> to leave interactive mode, h for this help, or a letter to fire a callback")
934 Display.setDefaultBackend(backend)
938 return Display.getDefaultBackend()
942 return Display.setDefaultFrame(frame)
946 """Get the default frame for display.
948 return Display.getDefaultFrame()
952 """Increment the default frame for display.
954 return Display.incrDefaultFrame()
958 return Display.setDefaultMaskTransparency(maskPlaneTransparency)
962 """Set the default mapping from mask plane names to colors.
966 name : `str` or `dict`
967 Name of mask plane, or a dict mapping names to colors.
968 If ``name`` is `None`, use the hard-coded default dictionary.
970 Desired color, or `None` if ``name`` is a dict.
973 return Display.setDefaultMaskPlaneColor(name, color)
976def getDisplay(frame=None, backend=None, create=True, verbose=False, **kwargs):
977 """Return a specific `Display`, creating it if need be.
982 Desired frame (`None` => use defaultFrame (see `setDefaultFrame`)).
984 Create the specified frame using this backend (or the default if
985 `None`) if it doesn't already exist. If ``backend == ""``, it's an
986 error to specify a non-existent ``frame``.
988 Create the display if it doesn't already exist.
990 Allow backend to be chatty.
992 Keyword arguments passed to `Display` constructor.
999 return Display.getDisplay(frame, backend, create, verbose, **kwargs)
1003 """Delete and close all known displays.
1005 return Display.delAllDisplays()
std::vector< SchemaItem< Flag > > * items
mtv(self, data, title="", wcs=None)
setMaskTransparency(self, transparency=None, name=None)
image(self, data, title="", wcs=None)
getDisplay(frame=None, backend=None, create=True, verbose=False, **kwargs)
getActiveCallbackKeys(self, onlyActive=True)
setDefaultBackend(backend)
centroids(self, catalog, *symbol="o", **kwargs)
dot(self, symb, c, r, size=2, ctype=None, origin=afwImage.PARENT, **kwargs)
getMaskPlaneColor(self, name=None)
setDefaultImageColormap(cmap)
line(self, points, origin=afwImage.PARENT, symbs=False, ctype=None, size=0.5)
scale(self, algorithm, min, max=None, unit=None, **kwargs)
__init__(self, frame=None, backend=None, **kwargs)
setDefaultMaskTransparency(maskPlaneTransparency={})
pan(self, colc=None, rowc=None, origin=afwImage.PARENT)
getMaskTransparency(self, name=None)
setCallback(self, k, func=None, noRaise=False)
setMaskPlaneColor(self, name, color=None)
setDefaultMaskPlaneColor(name=None, color=None)
__addMissingMaskPlanes(self, mask)
maskColorGenerator(self, omitBW=True)
zoom(self, zoomfac=None, colc=None, rowc=None, origin=afwImage.PARENT)
setImageColormap(self, cmap)
__init__(self, k, x=float('nan'), y=float('nan'))
An ellipse core with quadrupole moments as parameters.
A container for an Image and its associated metadata.
A class to contain the data, WCS, and other information needed to describe an image of the sky.
A class to represent a 2-dimensional array of pixels.
Represent a 2-dimensional array of bitmask pixels.
A class to manipulate images, masks, and variance as a single object.
setDefaultMaskTransparency(maskPlaneTransparency={})
getDisplay(frame=None, backend=None, create=True, verbose=False, **kwargs)
setDefaultMaskPlaneColor(name=None, color=None)
_makeDisplayImpl(display, backend, *args, **kwargs)
setDefaultBackend(backend)
std::shared_ptr< SkyWcs > makeSkyWcs(daf::base::PropertySet &metadata, bool strip=false)
Construct a SkyWcs from FITS keywords.