24     "WHITE", 
"BLACK", 
"RED", 
"GREEN", 
"BLUE", 
"CYAN", 
"MAGENTA", 
"YELLOW", 
"ORANGE", 
"IGNORE",
 
   25     "Display", 
"Event", 
"noop_callback", 
"h_callback",
 
   26     "setDefaultBackend", 
"getDefaultBackend",
 
   27     "setDefaultFrame", 
"getDefaultFrame", 
"incrDefaultFrame",
 
   28     "setDefaultMaskTransparency", 
"setDefaultMaskPlaneColor",
 
   29     "getDisplay", 
"delAllDisplays",
 
   56 def _makeDisplayImpl(display, backend, *args, **kwargs):
 
   57     """Return the ``DisplayImpl`` for the named backend 
   62         Name of device. Should be importable, either absolutely or relative to lsst.display 
   66         Arguments passed to DisplayImpl.__init__ 
   68         Keywords arguments passed to DisplayImpl.__init__ 
   75          import lsst.afw.display as afwDisplay 
   76          display = afwDisplay.Display(display=1, backend="ds9") 
   80          _makeDisplayImpl(..., "ds9", 1) 
   81     and import the ds9 implementation of ``DisplayImpl`` from `lsst.display.ds9` 
   85     for dt 
in (f
"lsst.display.{backend}", backend, f
".{backend}", f
"lsst.afw.display.{backend}"):
 
   89         if dt.startswith(
"."):
 
   90             impargs[
"package"] = 
"lsst.display" 
   92             _disp = importlib.import_module(dt, **impargs)
 
   94         except (ImportError, SystemError) 
as e:
 
  100     if not _disp 
or not hasattr(_disp.DisplayImpl, 
"_show"):
 
  106                 "Could not load the requested backend: {}".
format(backend))
 
  109         _impl = _disp.DisplayImpl(display, *args, **kwargs)
 
  110         if not hasattr(_impl, 
"frame"):
 
  111             _impl.frame = display.frame
 
  119     """Create an object able to display images and overplot glyphs 
  124         An identifier for the display 
  126         The backend to use (defaults to value set by setDefaultBackend()) 
  128         Arguments to pass to the backend 
  130         Arguments to pass to the backend 
  133     _defaultBackend = 
None 
  135     _defaultMaskPlaneColor = dict(
 
  142         DETECTED_NEGATIVE=CYAN,
 
  149     _defaultMaskTransparency = {}
 
  150     _defaultImageColormap = 
"gray" 
  152     def __init__(self, frame=None, backend=None, *args, **kwargs):
 
  157             if Display._defaultBackend 
is None:
 
  163             backend = Display._defaultBackend
 
  166         self.
_impl = _makeDisplayImpl(self, backend, *args, **kwargs)
 
  177         for ik 
in range(ord(
'a'), ord(
'z') + 1):
 
  182         for k 
in (
'Return', 
'Shift_L', 
'Shift_R'):
 
  185         for k 
in (
'q', 
'Escape'):
 
  188         def _h_callback(k, x, y):
 
  193                 print(
"   %-6s %s" % (k, doc.split(
"\n")[0] 
if doc 
else "???"))
 
  197         Display._displays[frame] = self
 
  200         """Support for python's with statement 
  205         """Support for python's with statement 
  213         """Return the attribute of ``self._impl``, or ``._impl`` if it is requested 
  218             name of the attribute requested 
  223             the attribute of self._impl for the requested name 
  227             return object.__getattr__(self, name)
 
  229         if not (hasattr(self, 
"_impl") 
and self.
_impl):
 
  230             raise AttributeError(
"Device has no _impl attached")
 
  233             return getattr(self.
_impl, name)
 
  234         except AttributeError:
 
  235             raise AttributeError(
 
  236                 f
"Device {self.name} has no attribute \"{name}\"")
 
  239         if getattr(self, 
"_impl", 
None) 
is not None:
 
  244         if self.
frame in Display._displays:
 
  245             del Display._displays[self.
frame]
 
  249         """The backend's verbosity 
  251         return self.
_impl.verbose
 
  256             self.
_impl.verbose = value
 
  259         return f
"Display[{self.frame}]" 
  267             _makeDisplayImpl(
None, backend)
 
  268         except Exception 
as e:
 
  270                 f
"Unable to set backend to {backend}: \"{e}\"")
 
  272         Display._defaultBackend = backend
 
  276         return Display._defaultBackend
 
  280         """Set the default frame for display 
  282         Display._defaultFrame = frame
 
  286         """Get the default frame for display 
  288         return Display._defaultFrame
 
  292         """Increment the default frame for display 
  294         Display._defaultFrame += 1
 
  295         return Display._defaultFrame
 
  299         if hasattr(maskPlaneTransparency, 
"copy"):
 
  300             maskPlaneTransparency = maskPlaneTransparency.copy()
 
  302         Display._defaultMaskTransparency = maskPlaneTransparency
 
  306         """Set the default mapping from mask plane names to colors 
  310         name : `str` or `dict` 
  311             name of mask plane, or a dict mapping names to colors 
  312             If name is `None`, use the hard-coded default dictionary 
  314             Desired color, or `None` if name is a dict 
  318             name = Display._defaultMaskPlaneColor
 
  320         if isinstance(name, dict):
 
  322             for k, v 
in name.items():
 
  328         Display._defaultMaskPlaneColor[name] = color
 
  332         """Set the default colormap for images 
  337             Name of colormap, as interpreted by the backend 
  341         The only colormaps that all backends are required to honor 
  342         (if they pay any attention to setImageColormap) are "gray" and "grey" 
  345         Display._defaultImageColormap = cmap
 
  348         """Set the colormap to use for images 
  353             Name of colormap, as interpreted by the backend 
  357         The only colormaps that all backends are required to honor 
  358         (if they pay any attention to setImageColormap) are "gray" and "grey" 
  361         self.
_impl._setImageColormap(cmap)
 
  364     def getDisplay(frame=None, backend=None, create=True, verbose=False, *args, **kwargs):
 
  365         """Return a specific `Display`, creating it if need be 
  370             The desired frame (`None` => use defaultFrame (see `~Display.setDefaultFrame`)) 
  372             create the specified frame using this backend (or the default if 
  373             `None`) if it doesn't already exist. If ``backend == ""``, it's an 
  374             error to specify a non-existent ``frame``. 
  376             create the display if it doesn't already exist. 
  378             Allow backend to be chatty 
  380             arguments passed to `Display` constructor 
  382             keyword arguments passed to `Display` constructor 
  386             frame = Display._defaultFrame
 
  388         if frame 
not in Display._displays:
 
  390                 raise RuntimeError(f
"Frame {frame} does not exist")
 
  392             Display._displays[frame] = 
Display(
 
  393                 frame, backend, verbose=verbose, *args, **kwargs)
 
  395         Display._displays[frame].verbose = verbose
 
  396         return Display._displays[frame]
 
  400         """Delete and close all known displays 
  402         for disp 
in list(Display._displays.values()):
 
  404         Display._displays = {}
 
  407         """A generator for "standard" colors 
  412             Don't include `BLACK` and `WHITE` 
  419            colorGenerator = interface.maskColorGenerator(omitBW=True) 
  421                print p, next(colorGenerator) 
  423         _maskColors = [WHITE, BLACK, RED, GREEN,
 
  424                        BLUE, CYAN, MAGENTA, YELLOW, ORANGE]
 
  429             color = _maskColors[i%len(_maskColors)]
 
  430             if omitBW 
and color 
in (BLACK, WHITE):
 
  436         """Request that mask plane name be displayed as color 
  440         name : `str` or `dict` 
  441             Name of mask plane or a dictionary of name -> colorName 
  443             The name of the color to use (must be `None` if ``name`` is a `dict`) 
  445             Colors may be specified as any X11-compliant string (e.g. `"orchid"`), or by one 
  446             of the following constants in `lsst.afw.display` : `BLACK`, `WHITE`, `RED`, `BLUE`, 
  447             `GREEN`, `CYAN`, `MAGENTA`, `YELLOW`. 
  449             If the color is "ignore" (or `IGNORE`) then that mask plane is not displayed 
  451             The advantage of using the symbolic names is that the python interpreter can detect typos. 
  454         if isinstance(name, dict):
 
  456             for k, v 
in name.items():
 
  463         """Return the color associated with the specified mask plane name 
  468             Desired mask plane; if `None`, return entire dict 
  477         """Specify display's mask transparency (percent); or `None` to not set it when loading masks 
  480         if isinstance(transparency, dict):
 
  482             for k, v 
in transparency.items():
 
  486         if transparency 
is not None and (transparency < 0 
or transparency > 100):
 
  488                 "Mask transparency should be in the range [0, 100]; clipping", file=sys.stderr)
 
  494         if transparency 
is not None:
 
  495             self.
_impl._setMaskTransparency(transparency, name)
 
  498         """Return the current display's mask transparency 
  501         return self.
_impl._getMaskTransparency(name)
 
  504         """Uniconify and Raise display. 
  508         Throws an exception if frame doesn't exit 
  510         return self.
_impl._show()
 
  512     def mtv(self, data, title="", wcs=None):
 
  513         """Display an `~lsst.afw.image.Image` or `~lsst.afw.image.Mask` on a display 
  517         Historical note: the name "mtv" comes from Jim Gunn's forth imageprocessing 
  518         system, Mirella (named after Mirella Freni); The "m" stands for Mirella. 
  520         if hasattr(data, 
"getXY0"):
 
  521             self.
_xy0 = data.getXY0()
 
  529                     "You may not specify a wcs with an Exposure")
 
  530             data, wcs = data.getMaskedImage(), data.getWcs()
 
  538             self.
_xy0 = data.getXY0()   
 
  541             self.
_impl._mtv(data, 
None, wcs, title)
 
  548             self.
_impl._mtv(afwImage.ImageI(data.getArray()), data, wcs, title)
 
  551             self.
_impl._mtv(data.getImage(), data.getMask(), wcs, title)
 
  553             raise RuntimeError(f
"Unsupported type {data!r}")
 
  559         """A class intended to be used with python's with statement 
  566             self.
_impl._buffer(
True)
 
  569             self.
_impl._buffer(
False)
 
  573         """Return a class intended to be used with python's with statement 
  579            with display.Buffering(): 
  580                display.dot("+", xc, yc) 
  590         """Erase the specified display frame 
  594     def dot(self, symb, c, r, size=2, ctype=None, origin=afwImage.PARENT, *args, **kwargs):
 
  595         """Draw a symbol onto the specified display frame 
  611                     Draw an ellipse with moments (Mxx, Mxy, Myy) (argument size is ignored) 
  612                 `lsst.afw.geom.ellipses.BaseCore` 
  613                     Draw the ellipse (argument size is ignored). N.b. objects 
  614                     derived from `~lsst.afw.geom.ellipses.BaseCore` include 
  615                     `~lsst.afw.geom.ellipses.Axes` and `~lsst.afw.geom.ellipses.Quadrupole`. 
  617                     Interpreted as a string to be drawn. 
  619             The column and row where the symbol is drawn [0-based coordinates] 
  621             Size of symbol, in pixels 
  623             The desired color, either e.g. `lsst.afw.display.RED` or a color name known to X11 
  624         origin : `lsst.afw.image.ImageOrigin` 
  625             Coordinate system for the given positions. 
  627             Extra arguments to backend 
  629             Extra keyword arguments to backend 
  631         if isinstance(symb, int):
 
  634         if origin == afwImage.PARENT 
and self.
_xy0 is not None:
 
  639         if isinstance(symb, afwGeom.ellipses.BaseCore) 
or re.search(
r"^@:", symb):
 
  641                 mat = re.search(
r"^@:([^,]+),([^,]+),([^,]+)", symb)
 
  646                     mxx, mxy, myy = [float(_) 
for _ 
in mat.groups()]
 
  649             symb = afwGeom.ellipses.Axes(symb)
 
  651         self.
_impl._dot(symb, c, r, size, ctype, **kwargs)
 
  653     def line(self, points, origin=afwImage.PARENT, symbs=False, ctype=None, size=0.5):
 
  654         """Draw a set of symbols or connect points 
  660         origin : `lsst.afw.image.ImageOrigin` 
  661             Coordinate system for the given positions. 
  662         symbs : `bool` or sequence 
  663             If ``symbs`` is `True`, draw points at the specified points using the desired symbol, 
  664             otherwise connect the dots. 
  666             If ``symbs`` supports indexing (which includes a string -- caveat emptor) the 
  667             elements are used to label the points 
  669             ``ctype`` is the name of a color (e.g. 'red') 
  676                 symbs = len(points)*
list(symbs)
 
  678             for i, xy 
in enumerate(points):
 
  679                 self.
dot(symbs[i], *xy, size=size, ctype=ctype)
 
  682                 if origin == afwImage.PARENT 
and self.
_xy0 is not None:
 
  684                     _points = 
list(points)  
 
  685                     for i, p 
in enumerate(points):
 
  686                         _points[i] = (p[0] - x0, p[1] - y0)
 
  689                 self.
_impl._drawLines(points, ctype)
 
  694     def scale(self, algorithm, min, max=None, unit=None, *args, **kwargs):
 
  695         """Set the range of the scaling from DN in the image to the image display 
  700             Desired scaling (e.g. "linear" or "asinh") 
  702             Minimum value, or "minmax" or "zscale" 
  704             Maximum value (must be `None` for minmax|zscale) 
  706             Units for min and max (e.g. Percent, Absolute, Sigma; `None` if min==minmax|zscale) 
  708             Optional arguments to the backend 
  710             Optional keyword arguments to the backend 
  712         if min 
in (
"minmax", 
"zscale"):
 
  713             assert max 
is None, f
"You may not specify \"{min}\" and max" 
  714             assert unit 
is None, f
"You may not specify \"{min}\" and unit" 
  716             raise RuntimeError(
"Please specify max")
 
  718         self.
_impl._scale(algorithm, min, max, unit, *args, **kwargs)
 
  723     def zoom(self, zoomfac=None, colc=None, rowc=None, origin=afwImage.PARENT):
 
  724         """Zoom frame by specified amount, optionally panning also 
  727         if (rowc 
and colc 
is None) 
or (colc 
and rowc 
is None):
 
  729                 "Please specify row and column center to pan about")
 
  732             if origin == afwImage.PARENT 
and self.
_xy0 is not None:
 
  737             self.
_impl._pan(colc, rowc)
 
  739         if zoomfac 
is None and rowc 
is None:
 
  742         if zoomfac 
is not None:
 
  743             self.
_impl._zoom(zoomfac)
 
  745     def pan(self, colc=None, rowc=None, origin=afwImage.PARENT):
 
  751             the coordinates to pan to 
  752         origin : `lsst.afw.image.ImageOrigin` 
  753             Coordinate system for the given positions. 
  760         self.
zoom(
None, colc, rowc, origin)
 
  763         """Enter an interactive loop, listening for key presses in display and firing callbacks. 
  765         Exit with ``q``, ``CR``, ``ESC``, or any other callback function that returns a `True` value. 
  767         interactFinished = 
False 
  769         while not interactFinished:
 
  770             ev = self.
_impl._getEvent()
 
  773             k, x, y = ev.k, ev.x, ev.y      
 
  776                 logger.warn(
"No callback registered for {0}".
format(k))
 
  779                     interactFinished = self.
_callbacks[k](k, x, y)
 
  780                 except Exception 
as e:
 
  782                         "Display._callbacks['{0}']({0},{1},{2}) failed: {3}".
format(k, x, y, e))
 
  785         """Set the callback for a key 
  790             The key to assign the callback to 
  792             The callback assigned to ``k`` 
  798             The callback previously assigned to ``k``. 
  805                 f
"Key '{k}' is already in use by display, so I can't add a callback for it")
 
  808         self.
_callbacks[k] = func 
if func 
else noop_callback
 
  815         """Return all callback keys 
  820             If `True` only return keys that do something 
  824                        not (onlyActive 
and func == noop_callback)])
 
  832     """A class to handle events such as key presses in image display windows 
  835     def __init__(self, k, x=float(
'nan'), y=float(
'nan')):
 
  841         return f
"{self.k} ({self.x:.2f}, {self.y:.2f}" 
  860     print(
"Enter q or <ESC> to leave interactive mode, h for this help, or a letter to fire a callback")
 
  871     Display.setDefaultBackend(backend)
 
  875     return Display.getDefaultBackend()
 
  879     return Display.setDefaultFrame(frame)
 
  883     """Get the default frame for display 
  885     return Display.getDefaultFrame()
 
  889     """Increment the default frame for display 
  891     return Display.incrDefaultFrame()
 
  895     return Display.setDefaultMaskTransparency(maskPlaneTransparency)
 
  899     """Set the default mapping from mask plane names to colors 
  903     name : `str` or `dict` 
  904         name of mask plane, or a dict mapping names to colors. 
  905         If ``name`` is `None`, use the hard-coded default dictionary 
  907         Desired color, or `None` if ``name`` is a dict 
  910     return Display.setDefaultMaskPlaneColor(name, color)
 
  913 def getDisplay(frame=None, backend=None, create=True, verbose=False, *args, **kwargs):
 
  914     """Return a specific `Display`, creating it if need be 
  919         The desired frame (`None` => use defaultFrame (see `setDefaultFrame`)) 
  921         Create the specified frame using this backend (or the default if 
  922         `None`) if it doesn't already exist. If ``backend == ""``, it's an 
  923         error to specify a non-existent ``frame``. 
  925         Create the display if it doesn't already exist. 
  927         Allow backend to be chatty 
  929         arguments passed to `Display` constructor 
  931         keyword arguments passed to `Display` constructor 
  938     return Display.getDisplay(frame, backend, create, verbose, *args, **kwargs)
 
  942     """Delete and close all known displays 
  944     return Display.delAllDisplays()