Loading [MathJax]/extensions/tex2jax.js
LSSTApplications  18.0.0+106,18.0.0+50,19.0.0,19.0.0+1,19.0.0+10,19.0.0+11,19.0.0+13,19.0.0+17,19.0.0+2,19.0.0-1-g20d9b18+6,19.0.0-1-g425ff20,19.0.0-1-g5549ca4,19.0.0-1-g580fafe+6,19.0.0-1-g6fe20d0+1,19.0.0-1-g7011481+9,19.0.0-1-g8c57eb9+6,19.0.0-1-gb5175dc+11,19.0.0-1-gdc0e4a7+9,19.0.0-1-ge272bc4+6,19.0.0-1-ge3aa853,19.0.0-10-g448f008b,19.0.0-12-g6990b2c,19.0.0-2-g0d9f9cd+11,19.0.0-2-g3d9e4fb2+11,19.0.0-2-g5037de4,19.0.0-2-gb96a1c4+3,19.0.0-2-gd955cfd+15,19.0.0-3-g2d13df8,19.0.0-3-g6f3c7dc,19.0.0-4-g725f80e+11,19.0.0-4-ga671dab3b+1,19.0.0-4-gad373c5+3,19.0.0-5-ga2acb9c+2,19.0.0-5-gfe96e6c+2,w.2020.01
LSSTDataManagementBasePackage
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
matplotlib.py
Go to the documentation of this file.
1 #
2 # LSST Data Management System
3 # Copyright 2008, 2009, 2010, 2015 LSST Corporation.
4 #
5 # This product includes software developed by the
6 # LSST Project (http://www.lsst.org/).
7 #
8 # This program is free software: you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation, either version 3 of the License, or
11 # (at your option) any later version.
12 #
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
17 #
18 # You should have received a copy of the LSST License Statement and
19 # the GNU General Public License along with this program. If not,
20 # see <http://www.lsstcorp.org/LegalNotices/>.
21 #
22 
23 #
24 # \file
25 # \brief Definitions to talk to matplotlib from python using the "afwDisplay"
26 # interface
27 
28 import math
29 import sys
30 import unicodedata
31 import warnings
32 
33 import matplotlib.pyplot as pyplot
34 import matplotlib.cbook
35 import matplotlib.colors as mpColors
36 from matplotlib.blocking_input import BlockingInput
37 
38 import numpy as np
39 import numpy.ma as ma
40 
41 import lsst.afw.display as afwDisplay
42 import lsst.afw.math as afwMath
43 import lsst.afw.display.rgb as afwRgb
44 import lsst.afw.display.interface as interface
45 import lsst.afw.display.virtualDevice as virtualDevice
46 import lsst.afw.display.ds9Regions as ds9Regions
47 import lsst.afw.image as afwImage
48 
49 import lsst.afw.geom as afwGeom
50 
51 #
52 # Set the list of backends which support _getEvent and thus interact()
53 #
54 try:
55  interactiveBackends
56 except NameError:
57  # List of backends that support `interact`
58  interactiveBackends = [
59  "Qt4Agg",
60  "Qt5Agg",
61  ]
62 
63 try:
64  matplotlibCtypes
65 except NameError:
66  matplotlibCtypes = {
67  afwDisplay.GREEN: "#00FF00",
68  }
69 
70  def mapCtype(ctype):
71  """Map the ctype to a potentially different ctype
72 
73  Specifically, if matplotlibCtypes[ctype] exists, use it instead
74 
75  This is used e.g. to map "green" to a brighter shade
76  """
77  return matplotlibCtypes[ctype] if ctype in matplotlibCtypes else ctype
78 
79 
80 class DisplayImpl(virtualDevice.DisplayImpl):
81  """Provide a matplotlib backend for afwDisplay
82 
83  Recommended backends in notebooks are:
84  %matplotlib notebook
85  or
86  %matplotlib ipympl
87  or
88  %matplotlib qt
89  %gui qt
90  or
91  %matplotlib inline
92  or
93  %matplotlib osx
94 
95  Apparently only qt supports Display.interact(); the list of interactive
96  backends is given by lsst.display.matplotlib.interactiveBackends
97  """
98  def __init__(self, display, verbose=False,
99  interpretMaskBits=True, mtvOrigin=afwImage.PARENT, fastMaskDisplay=True,
100  reopenPlot=False, *args, **kwargs):
101  """
102  Initialise a matplotlib display
103 
104  @param fastMaskDisplay If True, only show the first bitplane
105  that's set in each pixel
106  (e.g. if (SATURATED & DETECTED), ignore
107  DETECTED)
108  Not really what we want, but a bit faster
109  @param interpretMaskBits Interpret the mask value under the cursor
110  @param mtvOrigin Display pixel coordinates with LOCAL origin
111  (bottom left == 0,0 not XY0)
112  @param reopenPlot If true, close the plot before opening it.
113  (useful with e.g. %ipympl)
114  """
115  virtualDevice.DisplayImpl.__init__(self, display, verbose)
116 
117  if reopenPlot:
118  pyplot.close(display.frame)
119  self._figure = pyplot.figure(display.frame)
120  self._display = display
121  self._maskTransparency = {None: 0.7}
122  self._interpretMaskBits = interpretMaskBits # interpret mask bits in mtv
123  self._fastMaskDisplay = fastMaskDisplay
124  self._mtvOrigin = mtvOrigin
125  self._mappable = None
126  self._image_colormap = pyplot.cm.gray
127  #
128  self.__alpha = unicodedata.lookup("GREEK SMALL LETTER alpha") # used in cursor display string
129  self.__delta = unicodedata.lookup("GREEK SMALL LETTER delta") # used in cursor display string
130  #
131  # Support self._scale()
132  #
133  self._scaleArgs = dict()
134  self._normalize = None
135  #
136  # Support self._erase(), reporting pixel/mask values, and
137  # zscale/minmax; set in mtv
138  #
139  self._i_setImage(None)
140  #
141  # Ignore warnings due to BlockingKeyInput
142  #
143  if not verbose:
144  warnings.filterwarnings("ignore", category=matplotlib.cbook.mplDeprecation)
145 
146  def _close(self):
147  """!Close the display, cleaning up any allocated resources"""
148  self._image = None
149  self._mask = None
150  self._wcs = None
151  self._figure.gca().format_coord = None # keeps a copy of _wcs
152 
153  def _show(self):
154  """Put the plot at the top of the window stacking order"""
155 
156  try:
157  self._figure.canvas._tkcanvas._root().lift() # tk
158  except AttributeError:
159  pass
160 
161  try:
162  self._figure.canvas.manager.window.raise_() # os/x
163  except AttributeError:
164  pass
165 
166  try:
167  self._figure.canvas.raise_() # qt[45]
168  except AttributeError:
169  pass
170 
171  #
172  # Extensions to the API
173  #
174  def savefig(self, *args, **kwargs):
175  """Defer to figure.savefig()"""
176  self._figure.savefig(*args, **kwargs)
177 
178  def show_colorbar(self, show=True):
179  """Show (or hide) the colour bar"""
180  if show:
181  if self._mappable:
182  self._figure.colorbar(self._mappable)
183 
184  def wait(self, prompt="[c(ontinue) p(db)] :", allowPdb=True):
185  """Wait for keyboard input
186 
187  @param prompt `str`
188  The prompt string.
189  @param allowPdb `bool`
190  If true, entering a 'p' or 'pdb' puts you into pdb
191 
192  Returns the string you entered
193 
194  Useful when plotting from a programme that exits such as a processCcd
195  Any key except 'p' continues; 'p' puts you into pdb (unless allowPdb
196  is False)
197  """
198  while True:
199  s = input(prompt)
200  if allowPdb and s in ("p", "pdb"):
201  import pdb
202  pdb.set_trace()
203  continue
204 
205  return s
206  #
207  # Defined API
208  #
209 
210  def _setMaskTransparency(self, transparency, maskplane):
211  """Specify mask transparency (percent)"""
212 
213  self._maskTransparency[maskplane] = 0.01*transparency
214 
215  def _getMaskTransparency(self, maskplane=None):
216  """Return the current mask transparency"""
217  return self._maskTransparency[maskplane if maskplane in self._maskTransparency else None]
218 
219  def _mtv(self, image, mask=None, wcs=None, title=""):
220  """Display an Image and/or Mask on a matplotlib display
221  """
222  title = str(title) if title else ""
223 
224  #
225  # Save a reference to the image as it makes erase() easy and permits
226  # printing cursor values and minmax/zscale stretches. We also save XY0
227  #
228  self._i_setImage(image, mask, wcs)
229 
230  # We need to know the pixel values to support e.g. 'zscale' and
231  # 'minmax', so do the scaling now
232  if self._scaleArgs.get('algorithm'): # someone called self.scale()
233  self._i_scale(self._scaleArgs['algorithm'], self._scaleArgs['minval'], self._scaleArgs['maxval'],
234  self._scaleArgs['unit'], *self._scaleArgs['args'], **self._scaleArgs['kwargs'])
235 
236  self._figure.clf() # calling erase() calls _mtv
237 
238  self._i_mtv(image, wcs, title, False)
239  ax = self._figure.gca()
240 
241  if mask:
242  self._i_mtv(mask, wcs, title, True)
243 
244  if title:
245  ax.set_title(title)
246 
247  self._title = title
248 
249  def format_coord(x, y, wcs=self._wcs, x0=self._xy0[0], y0=self._xy0[1],
250  origin=afwImage.PARENT, bbox=self._image.getBBox(afwImage.PARENT)):
251 
252  fmt = '(%1.2f, %1.2f)'
253  if self._mtvOrigin == afwImage.PARENT:
254  msg = fmt % (x, y)
255  else:
256  msg = (fmt + "L") % (x - x0, y - y0)
257 
258  col = int(x + 0.5)
259  row = int(y + 0.5)
260  if bbox.contains(afwGeom.PointI(col, row)):
261  if wcs is not None:
262  ra, dec = wcs.pixelToSky(x, y)
263  msg += r" (%s, %s): (%9.4f, %9.4f)" % (self.__alpha, self.__delta, ra, dec)
264 
265  msg += ' %1.3f' % (self._image[col, row])
266  if self._mask:
267  val = self._mask[col, row]
268  if self._interpretMaskBits:
269  msg += " [%s]" % self._mask.interpret(val)
270  else:
271  msg += " 0x%x" % val
272 
273  return msg
274 
275  ax.format_coord = format_coord
276  # Stop images from reporting their value as we've already printed it
277  # nicely
278  from matplotlib.image import AxesImage
279  for a in ax.mouseover_set:
280  if isinstance(a, AxesImage):
281  a.get_cursor_data = lambda ev: None # disabled
282 
283  self._figure.tight_layout()
284  self._figure.canvas.draw_idle()
285 
286  def _i_mtv(self, data, wcs, title, isMask):
287  """Internal routine to display an Image or Mask on a DS9 display"""
288 
289  title = str(title) if title else ""
290  dataArr = data.getArray()
291 
292  if isMask:
293  maskPlanes = data.getMaskPlaneDict()
294  nMaskPlanes = max(maskPlanes.values()) + 1
295 
296  planes = {} # build inverse dictionary
297  for key in maskPlanes:
298  planes[maskPlanes[key]] = key
299 
300  planeList = range(nMaskPlanes)
301 
302  maskArr = np.zeros_like(dataArr, dtype=np.int32)
303 
304  colorNames = ['black']
305  colorGenerator = self.display.maskColorGenerator(omitBW=True)
306  for p in planeList:
307  color = self.display.getMaskPlaneColor(planes[p]) if p in planes else None
308 
309  if not color: # none was specified
310  color = next(colorGenerator)
311  elif color.lower() == afwDisplay.IGNORE:
312  color = 'black' # we'll set alpha = 0 anyway
313 
314  colorNames.append(color)
315  #
316  # Convert those colours to RGBA so we can have per-mask-plane
317  # transparency and build a colour map
318  #
319  # Pixels equal to 0 don't get set (as no bits are set), so leave
320  # them transparent and start our colours at [1] --
321  # hence "i + 1" below
322  #
323  colors = mpColors.to_rgba_array(colorNames)
324  alphaChannel = 3 # the alpha channel; the A in RGBA
325  colors[0][alphaChannel] = 0.0 # it's black anyway
326  for i, p in enumerate(planeList):
327  if colorNames[i + 1] == 'black':
328  alpha = 0.0
329  else:
330  alpha = 1 - self._getMaskTransparency(planes[p] if p in planes else None)
331 
332  colors[i + 1][alphaChannel] = alpha
333 
334  cmap = mpColors.ListedColormap(colors)
335  norm = mpColors.NoNorm()
336  else:
337  cmap = self._image_colormap
338  norm = self._normalize
339 
340  ax = self._figure.gca()
341  bbox = data.getBBox()
342  extent = (bbox.getBeginX() - 0.5, bbox.getEndX() - 0.5,
343  bbox.getBeginY() - 0.5, bbox.getEndY() - 0.5)
344 
345  with pyplot.rc_context(dict(interactive=False)):
346  if isMask:
347  for i, p in reversed(list(enumerate(planeList))):
348  if colors[i + 1][alphaChannel] == 0: # colors[0] is reserved
349  continue
350 
351  bitIsSet = (dataArr & (1 << p)) != 0
352  if bitIsSet.sum() == 0:
353  continue
354 
355  maskArr[bitIsSet] = i + 1 # + 1 as we set colorNames[0] to black
356 
357  if not self._fastMaskDisplay: # we draw each bitplane separately
358  ax.imshow(maskArr, origin='lower', interpolation='nearest',
359  extent=extent, cmap=cmap, norm=norm)
360  maskArr[:] = 0
361 
362  if self._fastMaskDisplay: # we only draw the lowest bitplane
363  ax.imshow(maskArr, origin='lower', interpolation='nearest',
364  extent=extent, cmap=cmap, norm=norm)
365  else:
366  mappable = ax.imshow(dataArr, origin='lower', interpolation='nearest',
367  extent=extent, cmap=cmap, norm=norm)
368  self._mappable = mappable
369 
370  self._figure.canvas.draw_idle()
371 
372  def _i_setImage(self, image, mask=None, wcs=None):
373  """Save the current image, mask, wcs, and XY0"""
374  self._image = image
375  self._mask = mask
376  self._wcs = wcs
377  self._xy0 = self._image.getXY0() if self._image else (0, 0)
378 
379  self._zoomfac = 1.0
380  if self._image is None:
381  self._width, self._height = 0, 0
382  else:
383  self._width, self._height = self._image.getDimensions()
384 
385  self._xcen = 0.5*self._width
386  self._ycen = 0.5*self._height
387 
388  def _setImageColormap(self, cmap):
389  """Set the colormap used for the image
390 
391  cmap should be either the name of an attribute of pyplot.cm or an
392  mpColors.Colormap (e.g. "gray" or pyplot.cm.gray)
393 
394  """
395  if not isinstance(cmap, mpColors.Colormap):
396  cmap = getattr(pyplot.cm, cmap)
397 
398  self._image_colormap = cmap
399 
400  #
401  # Graphics commands
402  #
403 
404  def _buffer(self, enable=True):
405  if enable:
406  pyplot.ioff()
407  else:
408  pyplot.ion()
409  self._figure.show()
410 
411  def _flush(self):
412  pass
413 
414  def _erase(self):
415  """Erase the display"""
416  #
417  # Rather than erase only the glyphs we'll redraw the image.
418  #
419  # This isn't a great solution.
420  #
421  self._figure.clf()
422 
423  if self._image:
424  zoomfac = self._zoomfac
425  xcen = self._xcen
426  ycen = self._ycen
427 
428  self._mtv(self._image, mask=self._mask, wcs=self._wcs, title=self._title)
429 
430  self._xcen = xcen
431  self._ycen = ycen
432  self._zoom(zoomfac)
433 
434  self._figure.canvas.draw_idle()
435 
436  def _dot(self, symb, c, r, size, ctype,
437  fontFamily="helvetica", textAngle=None):
438  """Draw a symbol at (col,row) = (c,r) [0-based coordinates]
439  Possible values are:
440  + Draw a +
441  x Draw an x
442  * Draw a *
443  o Draw a circle
444  @:Mxx,Mxy,Myy Draw an ellipse with moments
445  (Mxx, Mxy, Myy) (argument size is ignored)
446  An afwGeom.ellipses.Axes Draw the ellipse (argument size is
447  ignored)
448 
449  Any other value is interpreted as a string to be drawn. Strings obey the
450  fontFamily (which may be extended with other characteristics, e.g.
451  "times bold italic". Text will be drawn rotated by textAngle
452  (textAngle is ignored otherwise).
453  """
454  if not ctype:
455  ctype = afwDisplay.GREEN
456 
457  axis = self._figure.gca()
458  x0, y0 = self._xy0
459 
460  if isinstance(symb, afwGeom.ellipses.Axes):
461  from matplotlib.patches import Ellipse
462 
463  # Following matplotlib.patches.Ellipse documentation 'width' and
464  # 'height' are diameters while 'angle' is rotation in degrees
465  # (anti-clockwise)
466  axis.add_artist(Ellipse((c + x0, r + y0), height=2*symb.getA(), width=2*symb.getB(),
467  angle=90.0 + math.degrees(symb.getTheta()),
468  edgecolor=mapCtype(ctype), facecolor='none'))
469  elif symb == 'o':
470  from matplotlib.patches import CirclePolygon as Circle
471 
472  axis.add_artist(Circle((c + x0, r + y0), radius=size, color=mapCtype(ctype), fill=False))
473  else:
474  from matplotlib.lines import Line2D
475 
476  for ds9Cmd in ds9Regions.dot(symb, c + x0, r + y0, size, fontFamily="helvetica", textAngle=None):
477  tmp = ds9Cmd.split('#')
478  cmd = tmp.pop(0).split()
479 
480  cmd, args = cmd[0], cmd[1:]
481 
482  if cmd == "line":
483  args = np.array(args).astype(float) - 1.0
484 
485  x = np.empty(len(args)//2)
486  y = np.empty_like(x)
487  i = np.arange(len(args), dtype=int)
488  x = args[i%2 == 0]
489  y = args[i%2 == 1]
490 
491  axis.add_line(Line2D(x, y, color=mapCtype(ctype)))
492  elif cmd == "text":
493  x, y = np.array(args[0:2]).astype(float) - 1.0
494  axis.text(x, y, symb, color=mapCtype(ctype),
495  horizontalalignment='center', verticalalignment='center')
496  else:
497  raise RuntimeError(ds9Cmd)
498 
499  def _drawLines(self, points, ctype):
500  """Connect the points, a list of (col,row)
501  Ctype is the name of a colour (e.g. 'red')"""
502 
503  from matplotlib.lines import Line2D
504 
505  if not ctype:
506  ctype = afwDisplay.GREEN
507 
508  points = np.array(points)
509  x = points[:, 0] + self._xy0[0]
510  y = points[:, 1] + self._xy0[1]
511 
512  self._figure.gca().add_line(Line2D(x, y, color=mapCtype(ctype)))
513 
514  def _scale(self, algorithm, minval, maxval, unit, *args, **kwargs):
515  """
516  Set gray scale
517  """
518  self._scaleArgs['algorithm'] = algorithm
519  self._scaleArgs['minval'] = minval
520  self._scaleArgs['maxval'] = maxval
521  self._scaleArgs['unit'] = unit
522  self._scaleArgs['args'] = args
523  self._scaleArgs['kwargs'] = kwargs
524 
525  try:
526  self._i_scale(algorithm, minval, maxval, unit, *args, **kwargs)
527  except (AttributeError, RuntimeError):
528  # Unable to access self._image; we'll try again when we run mtv
529  pass
530 
531  def _i_scale(self, algorithm, minval, maxval, unit, *args, **kwargs):
532  if minval == "minmax":
533  if self._image is None:
534  raise RuntimeError("You may only use minmax if an image is loaded into the display")
535 
536  stats = afwMath.makeStatistics(self._image, afwMath.MIN | afwMath.MAX)
537  minval = stats.getValue(afwMath.MIN)
538  maxval = stats.getValue(afwMath.MAX)
539 
540  if algorithm is None:
541  self._normalize = None
542  elif algorithm == "asinh":
543  if minval == "zscale":
544  if self._image is None:
545  raise RuntimeError("You may only use zscale if an image is loaded into the display")
546 
547  self._normalize = AsinhZScaleNormalize(image=self._image, Q=kwargs.get("Q", 8.0))
548  else:
549  self._normalize = AsinhNormalize(minimum=minval,
550  dataRange=maxval - minval, Q=kwargs.get("Q", 8.0))
551  elif algorithm == "linear":
552  if minval == "zscale":
553  if self._image is None:
554  raise RuntimeError("You may only use zscale if an image is loaded into the display")
555 
556  self._normalize = ZScaleNormalize(image=self._image,
557  nSamples=kwargs.get("nSamples", 1000),
558  contrast=kwargs.get("contrast", 0.25))
559  else:
560  self._normalize = LinearNormalize(minimum=minval, maximum=maxval)
561  else:
562  raise RuntimeError("Unsupported stretch algorithm \"%s\"" % algorithm)
563  #
564  # Zoom and Pan
565  #
566 
567  def _zoom(self, zoomfac):
568  """Zoom by specified amount"""
569 
570  self._zoomfac = zoomfac
571 
572  x0, y0 = self._xy0
573 
574  size = min(self._width, self._height)
575  if size < self._zoomfac: # avoid min == max
576  size = self._zoomfac
577  xmin, xmax = self._xcen + x0 + size/self._zoomfac*np.array([-1, 1])
578  ymin, ymax = self._ycen + y0 + size/self._zoomfac*np.array([-1, 1])
579 
580  ax = self._figure.gca()
581 
582  tb = self._figure.canvas.toolbar
583  if tb is not None: # It's None for e.g. %matplotlib inline in jupyter
584  tb.push_current() # save the current zoom in the view stack
585 
586  ax.set_xlim(xmin, xmax)
587  ax.set_ylim(ymin, ymax)
588  ax.set_aspect('equal', 'datalim')
589 
590  self._figure.canvas.draw_idle()
591 
592  def _pan(self, colc, rowc):
593  """Pan to (colc, rowc)"""
594 
595  self._xcen = colc
596  self._ycen = rowc
597 
598  self._zoom(self._zoomfac)
599 
600  def _getEvent(self, timeout=-1):
601  """Listen for a key press, returning (key, x, y)"""
602 
603  mpBackend = matplotlib.get_backend()
604  if mpBackend not in interactiveBackends:
605  print("The %s matplotlib backend doesn't support display._getEvent()" %
606  (matplotlib.get_backend(),), file=sys.stderr)
607  return interface.Event('q')
608 
609  blocking_input = BlockingKeyInput(self._figure)
610  return blocking_input(timeout=timeout)
611 
612 # -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
613 
614 
615 class BlockingKeyInput(BlockingInput):
616  """
617  Callable class to retrieve a single keyboard click
618  """
619  def __init__(self, fig):
620  r"""Create a BlockingKeyInput
621 
622  \param fig The figure to monitor for keyboard events
623  """
624  BlockingInput.__init__(self, fig=fig, eventslist=('key_press_event',))
625 
626  def post_event(self):
627  """
628  Return the event containing the key and (x, y)
629  """
630  try:
631  event = self.events[-1]
632  except IndexError:
633  # details of the event to pass back to the display
634  self.ev = None
635  else:
636  self.ev = interface.Event(event.key, event.xdata, event.ydata)
637 
638  def __call__(self, timeout=-1):
639  """
640  Blocking call to retrieve a single key click
641  Returns key or None if timeout
642  """
643  self.ev = None
644 
645  BlockingInput.__call__(self, n=1, timeout=timeout)
646 
647  return self.ev
648 
649 # -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
650 
651 
652 class Normalize(mpColors.Normalize):
653  """Class to support stretches for mtv()"""
654 
655  def __call__(self, value, clip=None):
656  """
657  Return a MaskedArray with value mapped to [0, 255]
658 
659  @param value Input pixel value or array to be mapped
660  """
661  if isinstance(value, np.ndarray):
662  data = value
663  else:
664  data = value.data
665 
666  data = data - self.mapping.minimum[0]
667  return ma.array(data*self.mapping.mapIntensityToUint8(data)/255.0)
668 
669 
671  """Provide an asinh stretch for mtv()"""
672  def __init__(self, minimum=0, dataRange=1, Q=8):
673  """Initialise an object able to carry out an asinh mapping
674 
675  @param minimum Minimum pixel value (default: 0)
676  @param dataRange Range of values for stretch if Q=0; roughly the
677  linear part (default: 1)
678  @param Q Softening parameter (default: 8)
679 
680  See Lupton et al., PASP 116, 133
681  """
682  Normalize.__init__(self)
683 
684  # The object used to perform the desired mapping
685  self.mapping = afwRgb.AsinhMapping(minimum, dataRange, Q)
686 
687 
689  """Provide an asinh stretch using zscale to set limits for mtv()"""
690  def __init__(self, image=None, Q=8):
691  """Initialise an object able to carry out an asinh mapping
692 
693  @param image image to use estimate minimum and dataRange using zscale
694  (see AsinhNormalize)
695  @param Q Softening parameter (default: 8)
696 
697  See Lupton et al., PASP 116, 133
698  """
699  Normalize.__init__(self)
700 
701  # The object used to perform the desired mapping
702  self.mapping = afwRgb.AsinhZScaleMapping(image, Q)
703 
704 
706  """Provide a zscale stretch for mtv()"""
707  def __init__(self, image=None, nSamples=1000, contrast=0.25):
708  """Initialise an object able to carry out a zscale mapping
709 
710  @param image to be used to estimate the stretch
711  @param nSamples Number of data points to use (default: 1000)
712  @param contrast Control the range of pixels to display around the
713  median (default: 0.25)
714  """
715 
716  Normalize.__init__(self)
717 
718  # The object used to perform the desired mapping
719  self.mapping = afwRgb.ZScaleMapping(image, nSamples, contrast)
720 
721 
723  """Provide a linear stretch for mtv()"""
724  def __init__(self, minimum=0, maximum=1):
725  """Initialise an object able to carry out a linear mapping
726 
727  @param minimum Minimum value to display
728  @param maximum Maximum value to display
729  """
730 
731  Normalize.__init__(self)
732 
733  # The object used to perform the desired mapping
734  self.mapping = afwRgb.LinearMapping(minimum, maximum)
def __init__(self, minimum=0, maximum=1)
Definition: matplotlib.py:724
def _i_mtv(self, data, wcs, title, isMask)
Definition: matplotlib.py:286
def __init__(self, display, verbose=False, interpretMaskBits=True, mtvOrigin=afwImage.PARENT, fastMaskDisplay=True, reopenPlot=False, args, kwargs)
Definition: matplotlib.py:100
def _i_scale(self, algorithm, minval, maxval, unit, args, kwargs)
Definition: matplotlib.py:531
int min
Statistics makeStatistics(lsst::afw::math::MaskedVector< EntryT > const &mv, std::vector< WeightPixel > const &vweights, int const flags, StatisticsControl const &sctrl=StatisticsControl())
The makeStatistics() overload to handle lsst::afw::math::MaskedVector<>
Definition: Statistics.h:520
def show(frame=None)
Definition: ds9.py:89
int max
def getMaskPlaneColor(name, frame=None)
Definition: ds9.py:77
def _i_setImage(self, image, mask=None, wcs=None)
Definition: matplotlib.py:372
def wait(self, prompt="[c(ontinue) p(db)] :", allowPdb=True)
Definition: matplotlib.py:184
def __init__(self, image=None, nSamples=1000, contrast=0.25)
Definition: matplotlib.py:707
Backwards-compatibility support for depersisting the old Calib (FluxMag0/FluxMag0Err) objects...
def _getMaskTransparency(self, maskplane=None)
Definition: matplotlib.py:215
def __init__(self, minimum=0, dataRange=1, Q=8)
Definition: matplotlib.py:672
def __call__(self, value, clip=None)
Definition: matplotlib.py:655
daf::base::PropertyList * list
Definition: fits.cc:903