34 "WHITE",
"BLACK",
"RED",
"GREEN",
"BLUE",
"CYAN",
"MAGENTA",
"YELLOW",
"ORANGE",
35 "Display",
"Event",
"noop_callback",
"h_callback",
36 "setDefaultBackend",
"getDefaultBackend",
37 "setDefaultFrame",
"getDefaultFrame",
"incrDefaultFrame",
38 "setDefaultMaskTransparency",
"setDefaultMaskPlaneColor",
39 "getDisplay",
"delAllDisplays",
58 """!Return the DisplayImpl for the named backend
60 \param backend Name of device. Should be importable, either absolutely or relative to lsst.display
61 \param frame Identifier for this instance of the backend
62 \param args Arguments passed to DisplayImpl.__init__
63 \param kwrgs Keywords arguments passed to DisplayImpl.__init__
66 import lsst.afw.display as afwDisplay
67 display = afwDisplay.Display("ds9", frame=1)
69 _makeDisplayImpl(..., "ds9", 1)
70 and import the ds9 implementation of DisplayImpl from lsst.display.ds9
73 for dt
in (backend,
".%s" % backend,
"lsst.afw.display.%s" % backend):
75 _disp = importlib.import_module(dt, package=
"lsst.display")
77 except ImportError
as e:
83 return _disp.DisplayImpl(display, *args, **kwargs)
89 _defaultBackend =
None
91 _defaultMaskPlaneColor = dict(
98 DETECTED_NEGATIVE=CYAN,
105 _defaultMaskTransparency = {}
107 def __init__(self, frame, backend=None, *args, **kwargs):
108 """!Create an object able to display images and overplot glyphs
110 \param frame An identifier for the display
111 \param backend The backend to use (defaults to value set by setDefaultBackend())
112 \param args Arguments to pass to the backend
113 \param kwargs Arguments to pass to the backend
116 if Display._defaultBackend
is None:
122 backend = Display._defaultBackend
134 for ik
in range(ord(
'a'), ord(
'z') + 1):
139 for k
in (
'Return',
'Shift_L',
'Shift_R'):
142 for k
in (
'q',
'Escape'):
145 def _h_callback(k, x, y):
148 for k
in sorted(self._callbacks.keys()):
150 print " %-6s %s" % (k, doc.split(
"\n")[0]
if doc
else "???")
155 """!Support for python's with statement"""
159 """!Support for python's with statement"""
170 if self.
frame in Display._displays:
171 del Display._displays[self.
frame]
175 """!The backend's verbosity"""
176 return self._impl.verbose
181 self._impl.verbose = value
184 return "Display[%s]" % (self.
frame)
193 except Exception
as e:
194 raise RuntimeError(
"Unable to set backend to %s: \"%s\"" % (backend, e))
196 Display._defaultBackend = backend
200 return Display._defaultBackend
204 """Set the default frame for display"""
205 Display._defaultFrame = frame
209 """Get the default frame for display"""
210 return Display._defaultFrame
214 """Increment the default frame for display"""
215 Display._defaultFrame += 1
216 return Display._defaultFrame
220 if hasattr(maskPlaneTransparency,
"copy"):
221 maskPlaneTransparency = maskPlaneTransparency.copy()
223 Display._defaultMaskTransparency = maskPlaneTransparency
227 """!Set the default mapping from mask plane names to colours
228 \param name name of mask plane, or a dict mapping names to colours
229 \param color Desired color, or None if name is a dict
231 If name is None, use the hard-coded default dictionary
235 name = Display._defaultMaskPlaneColor
237 if isinstance(name, dict):
239 for k, v
in name.items():
245 Display._defaultMaskPlaneColor[name] = color
248 def getDisplay(frame=None, backend=None, create=True, verbose=False, *args, **kwargs):
249 """!Return the Display indexed by frame, creating it if needs be
251 \param frame The desired frame (None => use defaultFrame (see setDefaultFrame))
252 \param backend create the specified frame using this backend (or the default if None) \
253 if it doesn't already exist. If backend == "", it's an error to specify a non-existent frame
254 \param create create the display if it doesn't already exist.
255 \param verbose Allow backend to be chatty
256 \param args arguments passed to Display constructor
257 \param kwargs keyword arguments passed to Display constructor
261 frame = Display._defaultFrame
263 if not frame
in Display._displays:
265 raise RuntimeError(
"Frame %s does not exist" % frame)
267 Display._displays[frame] =
Display(frame, backend, verbose=verbose, *args, **kwargs)
269 Display._displays[frame].verbose = verbose
270 return Display._displays[frame]
274 """!Delete and close all known display
276 for disp
in Display._displays.values():
278 Display._displays = {}
281 """!A generator for "standard" colours
283 \param omitBW Don't include Black and White
286 colorGenerator = interface.maskColorGenerator(omitBW=True)
288 print p, next(colorGenerator)
290 _maskColors = [WHITE, BLACK, RED, GREEN, BLUE, CYAN, MAGENTA, YELLOW, ORANGE]
295 color = _maskColors[i%len(_maskColors)]
296 if omitBW
and color
in (BLACK, WHITE):
302 """!Request that mask plane name be displayed as color
304 \param name Name of mask plane or a dictionary of name -> colourName
305 \param color The name of the colour to use (must be None if name is a dict)
307 Colours may be specified as any X11-compliant string (e.g. <tt>"orchid"</tt>), or by one
308 of the following constants defined in \c afwDisplay: \c BLACK, \c WHITE, \c RED, \c BLUE,
309 \c GREEN, \c CYAN, \c MAGENTA, \c YELLOW.
311 The advantage of using the symbolic names is that the python interpreter can detect typos.
315 if isinstance(name, dict):
317 for k, v
in name.items():
324 """!Return the colour associated with the specified mask plane name"""
326 return self._maskPlaneColors.get(name)
329 """!Specify display's mask transparency (percent); or None to not set it when loading masks"""
331 if isinstance(transparency, dict):
333 for k, v
in transparency.items():
337 if transparency
is not None and (transparency < 0
or transparency > 100):
338 print >> sys.stderr,
"Mask transparency should be in the range [0, 100]; clipping"
344 if transparency
is not None:
345 self._impl._setMaskTransparency(transparency, name)
348 """!Return the current display's mask transparency"""
350 self._impl._getMaskTransparency(name)
353 """!Uniconify and Raise display. N.b. throws an exception if frame doesn't exit"""
356 def mtv(self, data, title="", wcs=None):
357 """!Display an Image or Mask on a DISPLAY display
359 Historical note: the name "mtv" comes from Jim Gunn's forth imageprocessing
360 system, Mirella (named after Mirella Freni); The "m" stands for Mirella.
362 if hasattr(data,
"getXY0"):
363 self.
_xy0 = data.getXY0()
367 if re.search(
"::Exposure<", repr(data)):
369 raise RuntimeError,
"You may not specify a wcs with an Exposure"
370 data, wcs = data.getMaskedImage(), data.getWcs()
371 elif re.search(
"::DecoratedImage<", repr(data)):
373 self.
_xy0 = data.getXY0()
375 if re.search(
"::Image<", repr(data)):
376 self._impl._mtv(data,
None, wcs, title)
377 elif re.search(
"::Mask<", repr(data)):
382 self._impl._mtv(afwImage.ImageU(data.getArray()), data, wcs, title)
383 elif re.search(
"::MaskedImage<", repr(data)):
384 self._impl._mtv(data.getImage(), data.getMask(
True), wcs, title)
386 raise RuntimeError,
"Unsupported type %s" % repr(data)
391 """A class intended to be used with python's with statement"""
395 self._impl._buffer(
True)
397 self._impl._buffer(
False)
401 """Return a class intended to be used with python's with statement
403 with display.Buffering():
404 display.dot("+", xc, yc)
409 """!Flush the buffers"""
413 """!Erase the specified DISPLAY frame
417 def dot(self, symb, c, r, size=2, ctype=None, origin=afwImage.PARENT, *args, **kwargs):
418 """!Draw a symbol onto the specified DISPLAY frame at (col,row) = (c,r) [0-based coordinates]
425 @:Mxx,Mxy,Myy Draw an ellipse with moments (Mxx, Mxy, Myy) (argument size is ignored)
426 An object derived from afwGeom.ellipses.BaseCore Draw the ellipse (argument size is ignored)
427 Any other value is interpreted as a string to be drawn. Strings obey the fontFamily (which may be extended
428 with other characteristics, e.g. "times bold italic". Text will be drawn rotated by textAngle (textAngle is
431 N.b. objects derived from BaseCore include Axes and Quadrupole.
433 if isinstance(symb, int):
436 if origin == afwImage.PARENT
and self.
_xy0 is not None:
441 if isinstance(symb, afwGeom.ellipses.BaseCore)
or re.search(
r"^@:", symb):
443 mat = re.search(
r"^@:([^,]+),([^,]+),([^,]+)", symb)
448 mxx, mxy, myy = [float(_)
for _
in mat.groups()]
449 symb = afwGeom.ellipses.Quadrupole(mxx, myy, mxy)
451 symb = afwGeom.ellipses.Axes(symb)
453 self._impl._dot(symb, c, r, size, ctype, **kwargs)
455 def line(self, points, origin=afwImage.PARENT, symbs=False, ctype=None, size=0.5):
456 """!Draw a set of symbols or connect the points, a list of (col,row)
457 If symbs is True, draw points at the specified points using the desired symbol,
458 otherwise connect the dots. Ctype is the name of a colour (e.g. 'red')
460 If symbs supports indexing (which includes a string -- caveat emptor) the elements are used to label the points
466 symbs = len(points)*list(symbs)
468 for i, xy
in enumerate(points):
469 self.
dot(symbs[i], *xy, size=size, ctype=ctype)
472 if origin == afwImage.PARENT
and self.
_xy0 is not None:
474 _points = list(points)
475 for i, p
in enumerate(points):
476 _points[i] = (p[0] - x0, p[1] - y0)
479 self._impl._drawLines(points, ctype)
483 def scale(self, algorithm, min, max=None, unit=None, *args, **kwargs):
484 """!Set the range of the scaling from DN in the image to the image display
485 \param algorithm Desired scaling (e.g. "linear" or "asinh")
486 \param min Minimum value, or "minmax" or "zscale"
487 \param max Maximum value (must be None for minmax|zscale)
488 \param unit Units for min and max (e.g. Percent, Absolute, Sigma; None if min==minmax|zscale)
489 \param *args Optional arguments
490 \param **kwargs Optional keyword arguments
492 if min
in (
"minmax",
"zscale"):
493 assert max ==
None,
"You may not specify \"%s\" and max" % min
494 assert unit ==
None,
"You may not specify \"%s\" and unit" % min
496 raise RuntimeError(
"Please specify max")
498 self._impl._scale(algorithm, min, max, unit, *args, **kwargs)
502 def zoom(self, zoomfac=None, colc=None, rowc=None, origin=afwImage.PARENT):
503 """!Zoom frame by specified amount, optionally panning also"""
505 if (rowc
and colc
is None)
or (colc
and rowc
is None):
506 raise RuntimeError,
"Please specify row and column center to pan about"
509 if origin == afwImage.PARENT
and self.
_xy0 is not None:
514 self._impl._pan(colc, rowc)
516 if zoomfac ==
None and rowc ==
None:
519 if zoomfac
is not None:
520 self._impl._zoom(zoomfac)
522 def pan(self, colc=None, rowc=None, origin=afwImage.PARENT):
523 """!Pan to (rowc, colc); see also zoom"""
525 self.
zoom(
None, colc, rowc, origin)
528 """!Enter an interactive loop, listening for key presses in display and firing callbacks.
530 Exit with q, \c CR, or \c ESC
534 ev = self._impl._getEvent()
537 k, x, y = ev.k, ev.x, ev.y
540 if self.callbacks[k](k, x, y):
543 print >> sys.stderr,
"No callback is registered for %s" % k
545 print >> sys.stderr,
"Display.callbacks[%s](%s, %s, %s) failed: %s" % \
549 """!Set the callback for key k to be func, returning the old callback
556 "Key '%s' is already in use by display, so I can't add a callback for it" % k)
558 ofunc = self._callbacks.get(k)
559 self.
_callbacks[k] = func
if func
else noop_callback
561 self._impl._setCallback(k, self.
_callbacks[k])
566 """!Return all callback keys
567 \param onlyActive If true only return keys that do something
570 return sorted([k
for k, func
in self._callbacks.items()
if
571 not (onlyActive
and func == noop_callback)])
578 """!A class to handle events such as key presses in image display windows"""
579 def __init__(self, k, x=float(
'nan'), y=float(
'nan')):
585 return "%s (%.2f, %.2f)" % (self.
k, self.
x, self.
y)
590 """!Callback function: arguments key, x, y"""
594 print "Enter q or <ESC> to leave interactive mode, h for this help, or a letter to fire a callback"
604 Display.setDefaultBackend(backend)
607 return Display.getDefaultBackend()
610 return Display.setDefaultFrame(frame)
613 """Get the default frame for display"""
614 return Display.getDefaultFrame()
617 """Increment the default frame for display"""
618 return Display.incrDefaultFrame()
621 return Display.setDefaultMaskTransparency(maskPlaneTransparency)
624 """!Set the default mapping from mask plane names to colours
625 \param name name of mask plane, or a dict mapping names to colours
626 \param color Desired color, or None if name is a dict
628 If name is None, use the hard-coded default dictionary
631 return Display.setDefaultMaskPlaneColor(name, color)
633 def getDisplay(frame=None, backend=None, create=True, verbose=False, *args, **kwargs):
634 """!Return the Display indexed by frame, creating it if needs be
636 See Display.getDisplay
638 \param frame The desired frame (None => use defaultFrame (see setDefaultFrame))
639 \param backend create the specified frame using this backend (or the default if None) \
640 if it doesn't already exist. If backend == "", it's an error to specify a non-existent frame
641 \param create create the display if it doesn't already exist.
642 \param verbose Allow backend to be chatty
643 \param args arguments passed to Display constructor
644 \param kwargs keyword arguments passed to Display constructor
647 return Display.getDisplay(frame, backend, create, verbose, *args, **kwargs)
650 """!Delete and close all known display
652 return Display.delAllDisplays()
def getMaskTransparency
Return the current display's mask transparency.
def getDisplay
Return the Display indexed by frame, creating it if needs be.
def setMaskTransparency
Specify display's mask transparency (percent); or None to not set it when loading masks...
def interact
Enter an interactive loop, listening for key presses in display and firing callbacks.
def setMaskPlaneColor
Request that mask plane name be displayed as color.
def zoom
Zoom frame by specified amount, optionally panning also.
def setDefaultMaskTransparency
def delAllDisplays
Delete and close all known display.
def mtv
Display an Image or Mask on a DISPLAY display.
def __enter__
Support for python's with statement.
def pan
Pan to (rowc, colc); see also zoom.
def verbose
The backend's verbosity.
def __init__
Create an object able to display images and overplot glyphs.
def getMaskPlaneColor
Return the colour associated with the specified mask plane name.
A class to handle events such as key presses in image display windows.
def setDefaultMaskTransparency
def dot
Draw a symbol onto the specified DISPLAY frame at (col,row) = (c,r) [0-based coordinates].
def _makeDisplayImpl
Return the DisplayImpl for the named backend.
Wcs::Ptr makeWcs(coord::Coord const &crval, geom::Point2D const &crpix, double CD11, double CD12, double CD21, double CD22)
Create a Wcs object from crval, crpix, CD, using CD elements (useful from python) ...
def scale
Set the range of the scaling from DN in the image to the image display.
def delAllDisplays
Delete and close all known display.
def show
Uniconify and Raise display.
def line
Draw a set of symbols or connect the points, a list of (col,row) If symbs is True, draw points at the specified points using the desired symbol, otherwise connect the dots.
def setCallback
Set the callback for key k to be func, returning the old callback.
def erase
Erase the specified DISPLAY frame.
def getDisplay
Return the Display indexed by frame, creating it if needs be.
def flush
Flush the buffers.
def __exit__
Support for python's with statement.
def getActiveCallbackKeys
Return all callback keys.
def noop_callback
Callback function: arguments key, x, y.
def maskColorGenerator
A generator for "standard" colours.
def setDefaultMaskPlaneColor
Set the default mapping from mask plane names to colours.
def setDefaultMaskPlaneColor
Set the default mapping from mask plane names to colours.