matplotlib  1.4.3
About: matplotlib is a python 2D plotting library which produces publication quality figures in a variety of hardcopy formats and interactive environments across platforms.
  Fossies Dox: matplotlib-1.4.3.tar.gz  ("inofficial" and yet experimental doxygen-generated source code documentation)  

colorbar.py
Go to the documentation of this file.
1 '''
2 Colorbar toolkit with two classes and a function:
3 
4  :class:`ColorbarBase`
5  the base class with full colorbar drawing functionality.
6  It can be used as-is to make a colorbar for a given colormap;
7  a mappable object (e.g., image) is not needed.
8 
9  :class:`Colorbar`
10  the derived class for use with images or contour plots.
11 
12  :func:`make_axes`
13  a function for resizing an axes and adding a second axes
14  suitable for a colorbar
15 
16 The :meth:`~matplotlib.figure.Figure.colorbar` method uses :func:`make_axes`
17 and :class:`Colorbar`; the :func:`~matplotlib.pyplot.colorbar` function
18 is a thin wrapper over :meth:`~matplotlib.figure.Figure.colorbar`.
19 
20 '''
21 from __future__ import (absolute_import, division, print_function,
22  unicode_literals)
23 
24 import six
25 from six.moves import xrange, zip
26 
27 import warnings
28 
29 import numpy as np
30 
31 import matplotlib as mpl
32 import matplotlib.artist as martist
33 import matplotlib.cbook as cbook
34 import matplotlib.collections as collections
35 import matplotlib.colors as colors
36 import matplotlib.contour as contour
37 import matplotlib.cm as cm
38 import matplotlib.gridspec as gridspec
39 import matplotlib.patches as mpatches
40 import matplotlib.path as mpath
41 import matplotlib.ticker as ticker
42 import matplotlib.transforms as mtrans
43 
44 from matplotlib import docstring
45 
46 make_axes_kw_doc = '''
47 
48  ============= ====================================================
49  Property Description
50  ============= ====================================================
51  *orientation* vertical or horizontal
52  *fraction* 0.15; fraction of original axes to use for colorbar
53  *pad* 0.05 if vertical, 0.15 if horizontal; fraction
54  of original axes between colorbar and new image axes
55  *shrink* 1.0; fraction by which to shrink the colorbar
56  *aspect* 20; ratio of long to short dimensions
57  *anchor* (0.0, 0.5) if vertical; (0.5, 1.0) if horizontal;
58  the anchor point of the colorbar axes
59  *panchor* (1.0, 0.5) if vertical; (0.5, 0.0) if horizontal;
60  the anchor point of the colorbar parent axes. If
61  False, the parent axes' anchor will be unchanged
62  ============= ====================================================
63 
64 '''
65 
66 colormap_kw_doc = '''
67 
68  ============ ====================================================
69  Property Description
70  ============ ====================================================
71  *extend* [ 'neither' | 'both' | 'min' | 'max' ]
72  If not 'neither', make pointed end(s) for out-of-
73  range values. These are set for a given colormap
74  using the colormap set_under and set_over methods.
75  *extendfrac* [ *None* | 'auto' | length | lengths ]
76  If set to *None*, both the minimum and maximum
77  triangular colorbar extensions with have a length of
78  5% of the interior colorbar length (this is the
79  default setting). If set to 'auto', makes the
80  triangular colorbar extensions the same lengths as
81  the interior boxes (when *spacing* is set to
82  'uniform') or the same lengths as the respective
83  adjacent interior boxes (when *spacing* is set to
84  'proportional'). If a scalar, indicates the length
85  of both the minimum and maximum triangular colorbar
86  extensions as a fraction of the interior colorbar
87  length. A two-element sequence of fractions may also
88  be given, indicating the lengths of the minimum and
89  maximum colorbar extensions respectively as a
90  fraction of the interior colorbar length.
91  *extendrect* [ *False* | *True* ]
92  If *False* the minimum and maximum colorbar extensions
93  will be triangular (the default). If *True* the
94  extensions will be rectangular.
95  *spacing* [ 'uniform' | 'proportional' ]
96  Uniform spacing gives each discrete color the same
97  space; proportional makes the space proportional to
98  the data interval.
99  *ticks* [ None | list of ticks | Locator object ]
100  If None, ticks are determined automatically from the
101  input.
102  *format* [ None | format string | Formatter object ]
103  If None, the
104  :class:`~matplotlib.ticker.ScalarFormatter` is used.
105  If a format string is given, e.g., '%.3f', that is
106  used. An alternative
107  :class:`~matplotlib.ticker.Formatter` object may be
108  given instead.
109  *drawedges* [ False | True ] If true, draw lines at color
110  boundaries.
111  ============ ====================================================
112 
113  The following will probably be useful only in the context of
114  indexed colors (that is, when the mappable has norm=NoNorm()),
115  or other unusual circumstances.
116 
117  ============ ===================================================
118  Property Description
119  ============ ===================================================
120  *boundaries* None or a sequence
121  *values* None or a sequence which must be of length 1 less
122  than the sequence of *boundaries*. For each region
123  delimited by adjacent entries in *boundaries*, the
124  color mapped to the corresponding value in values
125  will be used.
126  ============ ===================================================
127 
128 '''
129 
130 colorbar_doc = '''
131 
132 Add a colorbar to a plot.
133 
134 Function signatures for the :mod:`~matplotlib.pyplot` interface; all
135 but the first are also method signatures for the
136 :meth:`~matplotlib.figure.Figure.colorbar` method::
137 
138  colorbar(**kwargs)
139  colorbar(mappable, **kwargs)
140  colorbar(mappable, cax=cax, **kwargs)
141  colorbar(mappable, ax=ax, **kwargs)
142 
143 arguments:
144 
145  *mappable*
146  the :class:`~matplotlib.image.Image`,
147  :class:`~matplotlib.contour.ContourSet`, etc. to
148  which the colorbar applies; this argument is mandatory for the
149  :meth:`~matplotlib.figure.Figure.colorbar` method but optional for the
150  :func:`~matplotlib.pyplot.colorbar` function, which sets the
151  default to the current image.
152 
153 keyword arguments:
154 
155  *cax*
156  None | axes object into which the colorbar will be drawn
157  *ax*
158  None | parent axes object(s) from which space for a new
159  colorbar axes will be stolen. If a list of axes is given
160  they will all be resized to make room for the colorbar axes.
161  *use_gridspec*
162  False | If *cax* is None, a new *cax* is created as an instance of
163  Axes. If *ax* is an instance of Subplot and *use_gridspec* is True,
164  *cax* is created as an instance of Subplot using the
165  grid_spec module.
166 
167 
168 Additional keyword arguments are of two kinds:
169 
170  axes properties:
171 %s
172  colorbar properties:
173 %s
174 
175 If *mappable* is a :class:`~matplotlib.contours.ContourSet`, its *extend*
176 kwarg is included automatically.
177 
178 Note that the *shrink* kwarg provides a simple way to keep a vertical
179 colorbar, for example, from being taller than the axes of the mappable
180 to which the colorbar is attached; but it is a manual method requiring
181 some trial and error. If the colorbar is too tall (or a horizontal
182 colorbar is too wide) use a smaller value of *shrink*.
183 
184 For more precise control, you can manually specify the positions of
185 the axes objects in which the mappable and the colorbar are drawn. In
186 this case, do not use any of the axes properties kwargs.
187 
188 It is known that some vector graphics viewer (svg and pdf) renders white gaps
189 between segments of the colorbar. This is due to bugs in the viewers not
190 matplotlib. As a workaround the colorbar can be rendered with overlapping
191 segments::
192 
193  cbar = colorbar()
194  cbar.solids.set_edgecolor("face")
195  draw()
196 
197 However this has negative consequences in other circumstances. Particularly
198 with semi transparent images (alpha < 1) and colorbar extensions and is not
199 enabled by default see (issue #1188).
200 
201 returns:
202  :class:`~matplotlib.colorbar.Colorbar` instance; see also its base class,
203  :class:`~matplotlib.colorbar.ColorbarBase`. Call the
204  :meth:`~matplotlib.colorbar.ColorbarBase.set_label` method
205  to label the colorbar.
206 
207 ''' % (make_axes_kw_doc, colormap_kw_doc)
208 
209 docstring.interpd.update(colorbar_doc=colorbar_doc)
210 
211 
212 def _set_ticks_on_axis_warn(*args, **kw):
213  # a top level function which gets put in at the axes'
214  # set_xticks set_yticks by _patch_ax
215  warnings.warn("Use the colorbar set_ticks() method instead.")
216 
217 
219  '''
220  Draw a colorbar in an existing axes.
221 
222  This is a base class for the :class:`Colorbar` class, which is the
223  basis for the :func:`~matplotlib.pyplot.colorbar` function and the
224  :meth:`~matplotlib.figure.Figure.colorbar` method, which are the
225  usual ways of creating a colorbar.
226 
227  It is also useful by itself for showing a colormap. If the *cmap*
228  kwarg is given but *boundaries* and *values* are left as None,
229  then the colormap will be displayed on a 0-1 scale. To show the
230  under- and over-value colors, specify the *norm* as::
231 
232  colors.Normalize(clip=False)
233 
234  To show the colors versus index instead of on the 0-1 scale,
235  use::
236 
237  norm=colors.NoNorm.
238 
239  Useful attributes:
240 
241  :attr:`ax`
242  the Axes instance in which the colorbar is drawn
243 
244  :attr:`lines`
245  a list of LineCollection if lines were drawn, otherwise
246  an empty list
247 
248  :attr:`dividers`
249  a LineCollection if *drawedges* is True, otherwise None
250 
251  Useful public methods are :meth:`set_label` and :meth:`add_lines`.
252 
253  '''
254  _slice_dict = {'neither': slice(0, None),
255  'both': slice(1, -1),
256  'min': slice(1, None),
257  'max': slice(0, -1)}
258 
259  def __init__(self, ax, cmap=None,
260  norm=None,
261  alpha=None,
262  values=None,
263  boundaries=None,
264  orientation='vertical',
265  ticklocation='auto',
266  extend='neither',
267  spacing='uniform', # uniform or proportional
268  ticks=None,
269  format=None,
270  drawedges=False,
271  filled=True,
272  extendfrac=None,
273  extendrect=False,
274  label='',
275  ):
276  #: The axes that this colorbar lives in.
277  self.ax = ax
278  self._patch_ax()
279  if cmap is None:
280  cmap = cm.get_cmap()
281  if norm is None:
282  norm = colors.Normalize()
283  self.alpha = alpha
284  cm.ScalarMappable.__init__(self, cmap=cmap, norm=norm)
285  self.values = values
286  self.boundaries = boundaries
287  self.extend = extend
288  self._inside = self._slice_dict[extend]
289  self.spacing = spacing
290  self.orientation = orientation
291  self.drawedges = drawedges
292  self.filled = filled
293  self.extendfrac = extendfrac
294  self.extendrect = extendrect
295  self.solids = None
296  self.lines = list()
297  self.outline = None
298  self.patch = None
299  self.dividers = None
300 
301  if ticklocation == 'auto':
302  ticklocation = 'bottom' if orientation == 'horizontal' else 'right'
303  self.ticklocation = ticklocation
304 
305  self.set_label(label)
306  if cbook.iterable(ticks):
307  self.locator = ticker.FixedLocator(ticks, nbins=len(ticks))
308  else:
309  self.locator = ticks # Handle default in _ticker()
310  if format is None:
311  if isinstance(self.norm, colors.LogNorm):
313  else:
315  elif cbook.is_string_like(format):
316  self.formatter = ticker.FormatStrFormatter(format)
317  else:
318  self.formatter = format # Assume it is a Formatter
319  # The rest is in a method so we can recalculate when clim changes.
320  self.config_axis()
321  self.draw_all()
322 
323  def _extend_lower(self):
324  """Returns whether the lower limit is open ended."""
325  return self.extend in ('both', 'min')
326 
327  def _extend_upper(self):
328  """Returns whether the uper limit is open ended."""
329  return self.extend in ('both', 'max')
330 
331  def _patch_ax(self):
332  # bind some methods to the axes to warn users
333  # against using those methods.
334  self.ax.set_xticks = _set_ticks_on_axis_warn
335  self.ax.set_yticks = _set_ticks_on_axis_warn
336 
337  def draw_all(self):
338  '''
339  Calculate any free parameters based on the current cmap and norm,
340  and do all the drawing.
341  '''
342  self._process_values()
343  self._find_range()
344  X, Y = self._mesh()
345  C = self._values[:, np.newaxis]
346  self._config_axes(X, Y)
347  if self.filled:
348  self._add_solids(X, Y, C)
349 
350  def config_axis(self):
351  ax = self.ax
352  if self.orientation == 'vertical':
353  ax.xaxis.set_ticks([])
354  # location is either one of 'bottom' or 'top'
355  ax.yaxis.set_label_position(self.ticklocation)
356  ax.yaxis.set_ticks_position(self.ticklocation)
357  else:
358  ax.yaxis.set_ticks([])
359  # location is either one of 'left' or 'right'
360  ax.xaxis.set_label_position(self.ticklocation)
361  ax.xaxis.set_ticks_position(self.ticklocation)
362 
363  self._set_label()
364 
365  def update_ticks(self):
366  """
367  Force the update of the ticks and ticklabels. This must be
368  called whenever the tick locator and/or tick formatter changes.
369  """
370  ax = self.ax
371  ticks, ticklabels, offset_string = self._ticker()
372  if self.orientation == 'vertical':
373  ax.yaxis.set_ticks(ticks)
374  ax.set_yticklabels(ticklabels)
375  ax.yaxis.get_major_formatter().set_offset_string(offset_string)
376 
377  else:
378  ax.xaxis.set_ticks(ticks)
379  ax.set_xticklabels(ticklabels)
380  ax.xaxis.get_major_formatter().set_offset_string(offset_string)
381 
382  def set_ticks(self, ticks, update_ticks=True):
383  """
384  set tick locations. Tick locations are updated immediately unless
385  update_ticks is *False*. To manually update the ticks, call
386  *update_ticks* method explicitly.
387  """
388  if cbook.iterable(ticks):
389  self.locator = ticker.FixedLocator(ticks, nbins=len(ticks))
390  else:
391  self.locator = ticks
392 
393  if update_ticks:
394  self.update_ticks()
395 
396  def set_ticklabels(self, ticklabels, update_ticks=True):
397  """
398  set tick labels. Tick labels are updated immediately unless
399  update_ticks is *False*. To manually update the ticks, call
400  *update_ticks* method explicitly.
401  """
402  if isinstance(self.locator, ticker.FixedLocator):
403  self.formatter = ticker.FixedFormatter(ticklabels)
404  if update_ticks:
405  self.update_ticks()
406  else:
407  warnings.warn("set_ticks() must have been called.")
408 
409  def _config_axes(self, X, Y):
410  '''
411  Make an axes patch and outline.
412  '''
413  ax = self.ax
414  ax.set_frame_on(False)
415  ax.set_navigate(False)
416  xy = self._outline(X, Y)
417  ax.update_datalim(xy)
418  ax.set_xlim(*ax.dataLim.intervalx)
419  ax.set_ylim(*ax.dataLim.intervaly)
420  if self.outline is not None:
421  self.outline.remove()
422  self.outline = mpatches.Polygon(
423  xy, edgecolor=mpl.rcParams['axes.edgecolor'],
424  facecolor='none',
425  linewidth=mpl.rcParams['axes.linewidth'],
426  closed=True,
427  zorder=2)
428  ax.add_artist(self.outline)
429  self.outline.set_clip_box(None)
430  self.outline.set_clip_path(None)
431  c = mpl.rcParams['axes.facecolor']
432  if self.patch is not None:
433  self.patch.remove()
434  self.patch = mpatches.Polygon(xy, edgecolor=c,
435  facecolor=c,
436  linewidth=0.01,
437  zorder=-1)
438  ax.add_artist(self.patch)
439 
440  self.update_ticks()
441 
442  def _set_label(self):
443  if self.orientation == 'vertical':
444  self.ax.set_ylabel(self._label, **self._labelkw)
445  else:
446  self.ax.set_xlabel(self._label, **self._labelkw)
447 
448  def set_label(self, label, **kw):
449  '''
450  Label the long axis of the colorbar
451  '''
452  self._label = '%s' % (label, )
453  self._labelkw = kw
454  self._set_label()
455 
456  def _outline(self, X, Y):
457  '''
458  Return *x*, *y* arrays of colorbar bounding polygon,
459  taking orientation into account.
460  '''
461  N = X.shape[0]
462  ii = [0, 1, N - 2, N - 1, 2 * N - 1, 2 * N - 2, N + 1, N, 0]
463  x = np.take(np.ravel(np.transpose(X)), ii)
464  y = np.take(np.ravel(np.transpose(Y)), ii)
465  x = x.reshape((len(x), 1))
466  y = y.reshape((len(y), 1))
467  if self.orientation == 'horizontal':
468  return np.hstack((y, x))
469  return np.hstack((x, y))
470 
471  def _edges(self, X, Y):
472  '''
473  Return the separator line segments; helper for _add_solids.
474  '''
475  N = X.shape[0]
476  # Using the non-array form of these line segments is much
477  # simpler than making them into arrays.
478  if self.orientation == 'vertical':
479  return [list(zip(X[i], Y[i])) for i in xrange(1, N - 1)]
480  else:
481  return [list(zip(Y[i], X[i])) for i in xrange(1, N - 1)]
482 
483  def _add_solids(self, X, Y, C):
484  '''
485  Draw the colors using :meth:`~matplotlib.axes.Axes.pcolormesh`;
486  optionally add separators.
487  '''
488  if self.orientation == 'vertical':
489  args = (X, Y, C)
490  else:
491  args = (np.transpose(Y), np.transpose(X), np.transpose(C))
492  kw = dict(cmap=self.cmap,
493  norm=self.norm,
494  alpha=self.alpha,
495  edgecolors='None')
496  # Save, set, and restore hold state to keep pcolor from
497  # clearing the axes. Ordinarily this will not be needed,
498  # since the axes object should already have hold set.
499  _hold = self.ax.ishold()
500  self.ax.hold(True)
501  col = self.ax.pcolormesh(*args, **kw)
502  self.ax.hold(_hold)
503  #self.add_observer(col) # We should observe, not be observed...
504 
505  if self.solids is not None:
506  self.solids.remove()
507  self.solids = col
508  if self.dividers is not None:
509  self.dividers.remove()
510  self.dividers = None
511  if self.drawedges:
512  linewidths = (0.5 * mpl.rcParams['axes.linewidth'],)
513  self.dividers = collections.LineCollection(self._edges(X, Y),
514  colors=(mpl.rcParams['axes.edgecolor'],),
515  linewidths=linewidths)
516  self.ax.add_collection(self.dividers)
517 
518  def add_lines(self, levels, colors, linewidths, erase=True):
519  '''
520  Draw lines on the colorbar.
521 
522  *colors* and *linewidths* must be scalars or
523  sequences the same length as *levels*.
524 
525  Set *erase* to False to add lines without first
526  removing any previously added lines.
527  '''
528  y = self._locate(levels)
529  igood = (y < 1.001) & (y > -0.001)
530  y = y[igood]
531  if cbook.iterable(colors):
532  colors = np.asarray(colors)[igood]
533  if cbook.iterable(linewidths):
534  linewidths = np.asarray(linewidths)[igood]
535  N = len(y)
536  x = np.array([0.0, 1.0])
537  X, Y = np.meshgrid(x, y)
538  if self.orientation == 'vertical':
539  xy = [list(zip(X[i], Y[i])) for i in xrange(N)]
540  else:
541  xy = [list(zip(Y[i], X[i])) for i in xrange(N)]
542  col = collections.LineCollection(xy, linewidths=linewidths)
543 
544  if erase and self.lines:
545  for lc in self.lines:
546  lc.remove()
547  self.lines = []
548  self.lines.append(col)
549  col.set_color(colors)
550  self.ax.add_collection(col)
551 
552  def _ticker(self):
553  '''
554  Return the sequence of ticks (colorbar data locations),
555  ticklabels (strings), and the corresponding offset string.
556  '''
557  locator = self.locator
558  formatter = self.formatter
559  if locator is None:
560  if self.boundaries is None:
561  if isinstance(self.norm, colors.NoNorm):
562  nv = len(self._values)
563  base = 1 + int(nv / 10)
564  locator = ticker.IndexLocator(base=base, offset=0)
565  elif isinstance(self.norm, colors.BoundaryNorm):
566  b = self.norm.boundaries
567  locator = ticker.FixedLocator(b, nbins=10)
568  elif isinstance(self.norm, colors.LogNorm):
569  locator = ticker.LogLocator()
570  else:
571  locator = ticker.MaxNLocator()
572  else:
573  b = self._boundaries[self._inside]
574  locator = ticker.FixedLocator(b, nbins=10)
575  if isinstance(self.norm, colors.NoNorm):
576  intv = self._values[0], self._values[-1]
577  else:
578  intv = self.vmin, self.vmax
579  locator.create_dummy_axis(minpos=intv[0])
580  formatter.create_dummy_axis(minpos=intv[0])
581  locator.set_view_interval(*intv)
582  locator.set_data_interval(*intv)
583  formatter.set_view_interval(*intv)
584  formatter.set_data_interval(*intv)
585 
586  b = np.array(locator())
587  ticks = self._locate(b)
588  inrange = (ticks > -0.001) & (ticks < 1.001)
589  ticks = ticks[inrange]
590  b = b[inrange]
591  formatter.set_locs(b)
592  ticklabels = [formatter(t, i) for i, t in enumerate(b)]
593  offset_string = formatter.get_offset()
594  return ticks, ticklabels, offset_string
595 
596  def _process_values(self, b=None):
597  '''
598  Set the :attr:`_boundaries` and :attr:`_values` attributes
599  based on the input boundaries and values. Input boundaries
600  can be *self.boundaries* or the argument *b*.
601  '''
602  if b is None:
603  b = self.boundaries
604  if b is not None:
605  self._boundaries = np.asarray(b, dtype=float)
606  if self.values is None:
607  self._values = 0.5 * (self._boundaries[:-1]
608  + self._boundaries[1:])
609  if isinstance(self.norm, colors.NoNorm):
610  self._values = (self._values + 0.00001).astype(np.int16)
611  return
612  self._values = np.array(self.values)
613  return
614  if self.values is not None:
615  self._values = np.array(self.values)
616  if self.boundaries is None:
617  b = np.zeros(len(self.values) + 1, 'd')
618  b[1:-1] = 0.5 * (self._values[:-1] - self._values[1:])
619  b[0] = 2.0 * b[1] - b[2]
620  b[-1] = 2.0 * b[-2] - b[-3]
621  self._boundaries = b
622  return
623  self._boundaries = np.array(self.boundaries)
624  return
625  # Neither boundaries nor values are specified;
626  # make reasonable ones based on cmap and norm.
627  if isinstance(self.norm, colors.NoNorm):
628  b = self._uniform_y(self.cmap.N + 1) * self.cmap.N - 0.5
629  v = np.zeros((len(b) - 1,), dtype=np.int16)
630  v[self._inside] = np.arange(self.cmap.N, dtype=np.int16)
631  if self._extend_lower():
632  v[0] = -1
633  if self._extend_upper():
634  v[-1] = self.cmap.N
635  self._boundaries = b
636  self._values = v
637  return
638  elif isinstance(self.norm, colors.BoundaryNorm):
639  b = list(self.norm.boundaries)
640  if self._extend_lower():
641  b = [b[0] - 1] + b
642  if self._extend_upper():
643  b = b + [b[-1] + 1]
644  b = np.array(b)
645  v = np.zeros((len(b) - 1,), dtype=float)
646  bi = self.norm.boundaries
647  v[self._inside] = 0.5 * (bi[:-1] + bi[1:])
648  if self._extend_lower():
649  v[0] = b[0] - 1
650  if self._extend_upper():
651  v[-1] = b[-1] + 1
652  self._boundaries = b
653  self._values = v
654  return
655  else:
656  if not self.norm.scaled():
657  self.norm.vmin = 0
658  self.norm.vmax = 1
659 
660  self.norm.vmin, self.norm.vmax = mtrans.nonsingular(self.norm.vmin,
661  self.norm.vmax,
662  expander=0.1)
663 
664  b = self.norm.inverse(self._uniform_y(self.cmap.N + 1))
665  if self._extend_lower():
666  b[0] = b[0] - 1
667  if self._extend_upper():
668  b[-1] = b[-1] + 1
669  self._process_values(b)
670 
671  def _find_range(self):
672  '''
673  Set :attr:`vmin` and :attr:`vmax` attributes to the first and
674  last boundary excluding extended end boundaries.
675  '''
676  b = self._boundaries[self._inside]
677  self.vmin = b[0]
678  self.vmax = b[-1]
679 
680  def _central_N(self):
681  '''number of boundaries **before** extension of ends'''
682  nb = len(self._boundaries)
683  if self.extend == 'both':
684  nb -= 2
685  elif self.extend in ('min', 'max'):
686  nb -= 1
687  return nb
688 
689  def _extended_N(self):
690  '''
691  Based on the colormap and extend variable, return the
692  number of boundaries.
693  '''
694  N = self.cmap.N + 1
695  if self.extend == 'both':
696  N += 2
697  elif self.extend in ('min', 'max'):
698  N += 1
699  return N
700 
701  def _get_extension_lengths(self, frac, automin, automax, default=0.05):
702  '''
703  Get the lengths of colorbar extensions.
704 
705  A helper method for _uniform_y and _proportional_y.
706  '''
707  # Set the default value.
708  extendlength = np.array([default, default])
709  if isinstance(frac, six.string_types):
710  if frac.lower() == 'auto':
711  # Use the provided values when 'auto' is required.
712  extendlength[0] = automin
713  extendlength[1] = automax
714  else:
715  # Any other string is invalid.
716  raise ValueError('invalid value for extendfrac')
717  elif frac is not None:
718  try:
719  # Try to set min and max extension fractions directly.
720  extendlength[:] = frac
721  # If frac is a sequence contaning None then NaN may
722  # be encountered. This is an error.
723  if np.isnan(extendlength).any():
724  raise ValueError()
725  except (TypeError, ValueError):
726  # Raise an error on encountering an invalid value for frac.
727  raise ValueError('invalid value for extendfrac')
728  return extendlength
729 
730  def _uniform_y(self, N):
731  '''
732  Return colorbar data coordinates for *N* uniformly
733  spaced boundaries, plus ends if required.
734  '''
735  if self.extend == 'neither':
736  y = np.linspace(0, 1, N)
737  else:
738  automin = automax = 1. / (N - 1.)
739  extendlength = self._get_extension_lengths(self.extendfrac,
740  automin, automax,
741  default=0.05)
742  if self.extend == 'both':
743  y = np.zeros(N + 2, 'd')
744  y[0] = 0. - extendlength[0]
745  y[-1] = 1. + extendlength[1]
746  elif self.extend == 'min':
747  y = np.zeros(N + 1, 'd')
748  y[0] = 0. - extendlength[0]
749  else:
750  y = np.zeros(N + 1, 'd')
751  y[-1] = 1. + extendlength[1]
752  y[self._inside] = np.linspace(0, 1, N)
753  return y
754 
755  def _proportional_y(self):
756  '''
757  Return colorbar data coordinates for the boundaries of
758  a proportional colorbar.
759  '''
760  if isinstance(self.norm, colors.BoundaryNorm):
761  y = (self._boundaries - self._boundaries[0])
762  y = y / (self._boundaries[-1] - self._boundaries[0])
763  else:
764  y = self.norm(self._boundaries.copy())
765  if self.extend == 'min':
766  # Exclude leftmost interval of y.
767  clen = y[-1] - y[1]
768  automin = (y[2] - y[1]) / clen
769  automax = (y[-1] - y[-2]) / clen
770  elif self.extend == 'max':
771  # Exclude rightmost interval in y.
772  clen = y[-2] - y[0]
773  automin = (y[1] - y[0]) / clen
774  automax = (y[-2] - y[-3]) / clen
775  else:
776  # Exclude leftmost and rightmost intervals in y.
777  clen = y[-2] - y[1]
778  automin = (y[2] - y[1]) / clen
779  automax = (y[-2] - y[-3]) / clen
780  extendlength = self._get_extension_lengths(self.extendfrac,
781  automin, automax,
782  default=0.05)
783  if self.extend in ('both', 'min'):
784  y[0] = 0. - extendlength[0]
785  if self.extend in ('both', 'max'):
786  y[-1] = 1. + extendlength[1]
787  yi = y[self._inside]
788  norm = colors.Normalize(yi[0], yi[-1])
789  y[self._inside] = norm(yi)
790  return y
791 
792  def _mesh(self):
793  '''
794  Return X,Y, the coordinate arrays for the colorbar pcolormesh.
795  These are suitable for a vertical colorbar; swapping and
796  transposition for a horizontal colorbar are done outside
797  this function.
798  '''
799  x = np.array([0.0, 1.0])
800  if self.spacing == 'uniform':
801  y = self._uniform_y(self._central_N())
802  else:
803  y = self._proportional_y()
804  self._y = y
805  X, Y = np.meshgrid(x, y)
806  if self._extend_lower() and not self.extendrect:
807  X[0, :] = 0.5
808  if self._extend_upper() and not self.extendrect:
809  X[-1, :] = 0.5
810  return X, Y
811 
812  def _locate(self, x):
813  '''
814  Given a set of color data values, return their
815  corresponding colorbar data coordinates.
816  '''
817  if isinstance(self.norm, (colors.NoNorm, colors.BoundaryNorm)):
818  b = self._boundaries
819  xn = x
820  else:
821  # Do calculations using normalized coordinates so
822  # as to make the interpolation more accurate.
823  b = self.norm(self._boundaries, clip=False).filled()
824  xn = self.norm(x, clip=False).filled()
825 
826  # The rest is linear interpolation with extrapolation at ends.
827  ii = np.searchsorted(b, xn)
828  i0 = ii - 1
829  itop = (ii == len(b))
830  ibot = (ii == 0)
831  i0[itop] -= 1
832  ii[itop] -= 1
833  i0[ibot] += 1
834  ii[ibot] += 1
835 
836  db = np.take(b, ii) - np.take(b, i0)
837  y = self._y
838  dy = np.take(y, ii) - np.take(y, i0)
839  z = np.take(y, i0) + (xn - np.take(b, i0)) * dy / db
840  return z
841 
842  def set_alpha(self, alpha):
843  self.alpha = alpha
844 
845  def remove(self):
846  """
847  Remove this colorbar from the figure
848  """
849 
850  fig = self.ax.figure
851  fig.delaxes(self.ax)
852 
853 
855  """
856  This class connects a :class:`ColorbarBase` to a
857  :class:`~matplotlib.cm.ScalarMappable` such as a
858  :class:`~matplotlib.image.AxesImage` generated via
859  :meth:`~matplotlib.axes.Axes.imshow`.
860 
861  It is not intended to be instantiated directly; instead,
862  use :meth:`~matplotlib.figure.Figure.colorbar` or
863  :func:`~matplotlib.pyplot.colorbar` to make your colorbar.
864 
865  """
866  def __init__(self, ax, mappable, **kw):
867  # Ensure the given mappable's norm has appropriate vmin and vmax set
868  # even if mappable.draw has not yet been called.
869  mappable.autoscale_None()
870 
871  self.mappable = mappable
872  kw['cmap'] = cmap = mappable.cmap
873  kw['norm'] = norm = mappable.norm
874 
875  if isinstance(mappable, contour.ContourSet):
876  CS = mappable
877  kw['alpha'] = mappable.get_alpha()
878  kw['boundaries'] = CS._levels
879  kw['values'] = CS.cvalues
880  kw['extend'] = CS.extend
881  #kw['ticks'] = CS._levels
882  kw.setdefault('ticks', ticker.FixedLocator(CS.levels, nbins=10))
883  kw['filled'] = CS.filled
884  ColorbarBase.__init__(self, ax, **kw)
885  if not CS.filled:
886  self.add_lines(CS)
887  else:
888  if getattr(cmap, 'colorbar_extend', False) is not False:
889  kw.setdefault('extend', cmap.colorbar_extend)
890 
891  if isinstance(mappable, martist.Artist):
892  kw['alpha'] = mappable.get_alpha()
893 
894  ColorbarBase.__init__(self, ax, **kw)
895 
896  def on_mappable_changed(self, mappable):
897  """
898  Updates this colorbar to match the mappable's properties.
899 
900  Typically this is automatically registered as an event handler
901  by :func:`colorbar_factory` and should not be called manually.
902 
903  """
904  self.set_cmap(mappable.get_cmap())
905  self.set_clim(mappable.get_clim())
906  self.update_normal(mappable)
907 
908  def add_lines(self, CS, erase=True):
909  '''
910  Add the lines from a non-filled
911  :class:`~matplotlib.contour.ContourSet` to the colorbar.
912 
913  Set *erase* to False if these lines should be added to
914  any pre-existing lines.
915  '''
916  if not isinstance(CS, contour.ContourSet) or CS.filled:
917  raise ValueError('add_lines is only for a ContourSet of lines')
918  tcolors = [c[0] for c in CS.tcolors]
919  tlinewidths = [t[0] for t in CS.tlinewidths]
920  # The following was an attempt to get the colorbar lines
921  # to follow subsequent changes in the contour lines,
922  # but more work is needed: specifically, a careful
923  # look at event sequences, and at how
924  # to make one object track another automatically.
925  #tcolors = [col.get_colors()[0] for col in CS.collections]
926  #tlinewidths = [col.get_linewidth()[0] for lw in CS.collections]
927  #print 'tlinewidths:', tlinewidths
928  ColorbarBase.add_lines(self, CS.levels, tcolors, tlinewidths,
929  erase=erase)
930 
931  def update_normal(self, mappable):
932  '''
933  update solid, lines, etc. Unlike update_bruteforce, it does
934  not clear the axes. This is meant to be called when the image
935  or contour plot to which this colorbar belongs is changed.
936  '''
937  self.draw_all()
938  if isinstance(self.mappable, contour.ContourSet):
939  CS = self.mappable
940  if not CS.filled:
941  self.add_lines(CS)
942 
943  def update_bruteforce(self, mappable):
944  '''
945  Destroy and rebuild the colorbar. This is
946  intended to become obsolete, and will probably be
947  deprecated and then removed. It is not called when
948  the pyplot.colorbar function or the Figure.colorbar
949  method are used to create the colorbar.
950 
951  '''
952  # We are using an ugly brute-force method: clearing and
953  # redrawing the whole thing. The problem is that if any
954  # properties have been changed by methods other than the
955  # colorbar methods, those changes will be lost.
956  self.ax.cla()
957  # clearing the axes will delete outline, patch, solids, and lines:
958  self.outline = None
959  self.patch = None
960  self.solids = None
961  self.lines = list()
962  self.dividers = None
963  self.set_alpha(mappable.get_alpha())
964  self.cmap = mappable.cmap
965  self.norm = mappable.norm
966  self.config_axis()
967  self.draw_all()
968  if isinstance(self.mappable, contour.ContourSet):
969  CS = self.mappable
970  if not CS.filled:
971  self.add_lines(CS)
972  #if self.lines is not None:
973  # tcolors = [c[0] for c in CS.tcolors]
974  # self.lines.set_color(tcolors)
975  #Fixme? Recalculate boundaries, ticks if vmin, vmax have changed.
976  #Fixme: Some refactoring may be needed; we should not
977  # be recalculating everything if there was a simple alpha
978  # change.
979 
980  def remove(self):
981  """
982  Remove this colorbar from the figure. If the colorbar was created with
983  ``use_gridspec=True`` then restore the gridspec to its previous value.
984  """
985 
986  ColorbarBase.remove(self)
987  self.mappable.callbacksSM.disconnect(self.mappable.colorbar_cid)
988  self.mappable.colorbar = None
989  self.mappable.colorbar_cid = None
990 
991  try:
992  ax = self.mappable.axes
993  except AttributeError:
994  return
995 
996  try:
997  gs = ax.get_subplotspec().get_gridspec()
998  subplotspec = gs.get_topmost_subplotspec()
999  except AttributeError:
1000  # use_gridspec was False
1001  pos = ax.get_position(original=True)
1002  ax.set_position(pos)
1003  else:
1004  # use_gridspec was True
1005  ax.set_subplotspec(subplotspec)
1006 
1007 
1008 @docstring.Substitution(make_axes_kw_doc)
1009 def make_axes(parents, location=None, orientation=None, fraction=0.15,
1010  shrink=1.0, aspect=20, **kw):
1011  '''
1012  Resize and reposition parent axes, and return a child
1013  axes suitable for a colorbar::
1014 
1015  cax, kw = make_axes(parent, **kw)
1016 
1017  Keyword arguments may include the following (with defaults):
1018 
1019  location : [None|'left'|'right'|'top'|'bottom']
1020  The position, relative to **parents**, where the colorbar axes
1021  should be created. If None, the value will either come from the
1022  given ``orientation``, else it will default to 'right'.
1023 
1024  orientation : [None|'vertical'|'horizontal']
1025  The orientation of the colorbar. Typically, this keyword shouldn't
1026  be used, as it can be derived from the ``location`` keyword.
1027 
1028  %s
1029 
1030  Returns (cax, kw), the child axes and the reduced kw dictionary to be
1031  passed when creating the colorbar instance.
1032  '''
1033  locations = ["left", "right", "top", "bottom"]
1034  if orientation is not None and location is not None:
1035  msg = ('position and orientation are mutually exclusive. '
1036  'Consider setting the position to any of '
1037  '{0}'.format(', '.join(locations)))
1038  raise TypeError(msg)
1039 
1040  # provide a default location
1041  if location is None and orientation is None:
1042  location = 'right'
1043 
1044  # allow the user to not specify the location by specifying the
1045  # orientation instead
1046  if location is None:
1047  location = 'right' if orientation == 'vertical' else 'bottom'
1048 
1049  if location not in locations:
1050  raise ValueError('Invalid colorbar location. Must be one '
1051  'of %s' % ', '.join(locations))
1052 
1053  default_location_settings = {'left': {'anchor': (1.0, 0.5),
1054  'panchor': (0.0, 0.5),
1055  'pad': 0.10,
1056  'orientation': 'vertical'},
1057  'right': {'anchor': (0.0, 0.5),
1058  'panchor': (1.0, 0.5),
1059  'pad': 0.05,
1060  'orientation': 'vertical'},
1061  'top': {'anchor': (0.5, 0.0),
1062  'panchor': (0.5, 1.0),
1063  'pad': 0.05,
1064  'orientation': 'horizontal'},
1065  'bottom': {'anchor': (0.5, 1.0),
1066  'panchor': (0.5, 0.0),
1067  'pad': 0.15, # backwards compat
1068  'orientation': 'horizontal'},
1069  }
1070 
1071  loc_settings = default_location_settings[location]
1072 
1073  # put appropriate values into the kw dict for passing back to
1074  # the Colorbar class
1075  kw['orientation'] = loc_settings['orientation']
1076  kw['ticklocation'] = location
1077 
1078  anchor = kw.pop('anchor', loc_settings['anchor'])
1079  parent_anchor = kw.pop('panchor', loc_settings['panchor'])
1080  pad = kw.pop('pad', loc_settings['pad'])
1081 
1082  # turn parents into a list if it is not already
1083  if not isinstance(parents, (list, tuple)):
1084  parents = [parents]
1085 
1086  fig = parents[0].get_figure()
1087  if not all(fig is ax.get_figure() for ax in parents):
1088  raise ValueError('Unable to create a colorbar axes as not all '
1089  'parents share the same figure.')
1090 
1091  # take a bounding box around all of the given axes
1092  parents_bbox = mtrans.Bbox.union([ax.get_position(original=True).frozen()
1093  for ax in parents])
1094 
1095  pb = parents_bbox
1096  if location in ('left', 'right'):
1097  if location == 'left':
1098  pbcb, _, pb1 = pb.splitx(fraction, fraction + pad)
1099  else:
1100  pb1, _, pbcb = pb.splitx(1 - fraction - pad, 1 - fraction)
1101  pbcb = pbcb.shrunk(1.0, shrink).anchored(anchor, pbcb)
1102  else:
1103  if location == 'bottom':
1104  pbcb, _, pb1 = pb.splity(fraction, fraction + pad)
1105  else:
1106  pb1, _, pbcb = pb.splity(1 - fraction - pad, 1 - fraction)
1107  pbcb = pbcb.shrunk(shrink, 1.0).anchored(anchor, pbcb)
1108 
1109  # define the aspect ratio in terms of y's per x rather than x's per y
1110  aspect = 1.0 / aspect
1111 
1112  # define a transform which takes us from old axes coordinates to
1113  # new axes coordinates
1114  shrinking_trans = mtrans.BboxTransform(parents_bbox, pb1)
1115 
1116  # transform each of the axes in parents using the new transform
1117  for ax in parents:
1118  new_posn = shrinking_trans.transform(ax.get_position())
1119  new_posn = mtrans.Bbox(new_posn)
1120  ax.set_position(new_posn)
1121  if parent_anchor is not False:
1122  ax.set_anchor(parent_anchor)
1123 
1124  cax = fig.add_axes(pbcb)
1125  cax.set_aspect(aspect, anchor=anchor, adjustable='box')
1126  return cax, kw
1127 
1128 
1129 @docstring.Substitution(make_axes_kw_doc)
1130 def make_axes_gridspec(parent, **kw):
1131  '''
1132  Resize and reposition a parent axes, and return a child axes
1133  suitable for a colorbar. This function is similar to
1134  make_axes. Prmary differences are
1135 
1136  * *make_axes_gridspec* only handles the *orientation* keyword
1137  and cannot handle the "location" keyword.
1138 
1139  * *make_axes_gridspec* should only be used with a subplot parent.
1140 
1141  * *make_axes* creates an instance of Axes. *make_axes_gridspec*
1142  creates an instance of Subplot.
1143 
1144  * *make_axes* updates the position of the
1145  parent. *make_axes_gridspec* replaces the grid_spec attribute
1146  of the parent with a new one.
1147 
1148  While this function is meant to be compatible with *make_axes*,
1149  there could be some minor differences.::
1150 
1151  cax, kw = make_axes_gridspec(parent, **kw)
1152 
1153  Keyword arguments may include the following (with defaults):
1154 
1155  *orientation*
1156  'vertical' or 'horizontal'
1157 
1158  %s
1159 
1160  All but the first of these are stripped from the input kw set.
1161 
1162  Returns (cax, kw), the child axes and the reduced kw dictionary to be
1163  passed when creating the colorbar instance.
1164  '''
1165 
1166  orientation = kw.setdefault('orientation', 'vertical')
1167  kw['ticklocation'] = 'auto'
1168 
1169  fraction = kw.pop('fraction', 0.15)
1170  shrink = kw.pop('shrink', 1.0)
1171  aspect = kw.pop('aspect', 20)
1172 
1173  x1 = 1.0 - fraction
1174 
1175  # for shrinking
1176  pad_s = (1. - shrink) * 0.5
1177  wh_ratios = [pad_s, shrink, pad_s]
1178 
1179  gs_from_subplotspec = gridspec.GridSpecFromSubplotSpec
1180  if orientation == 'vertical':
1181  pad = kw.pop('pad', 0.05)
1182  wh_space = 2 * pad / (1 - pad)
1183 
1184  gs = gs_from_subplotspec(1, 2,
1185  subplot_spec=parent.get_subplotspec(),
1186  wspace=wh_space,
1187  width_ratios=[x1 - pad, fraction]
1188  )
1189 
1190  gs2 = gs_from_subplotspec(3, 1,
1191  subplot_spec=gs[1],
1192  hspace=0.,
1193  height_ratios=wh_ratios,
1194  )
1195 
1196  anchor = (0.0, 0.5)
1197  panchor = (1.0, 0.5)
1198  else:
1199  pad = kw.pop('pad', 0.15)
1200  wh_space = 2 * pad / (1 - pad)
1201 
1202  gs = gs_from_subplotspec(2, 1,
1203  subplot_spec=parent.get_subplotspec(),
1204  hspace=wh_space,
1205  height_ratios=[x1 - pad, fraction]
1206  )
1207 
1208  gs2 = gs_from_subplotspec(1, 3,
1209  subplot_spec=gs[1],
1210  wspace=0.,
1211  width_ratios=wh_ratios,
1212  )
1213 
1214  aspect = 1.0 / aspect
1215  anchor = (0.5, 1.0)
1216  panchor = (0.5, 0.0)
1217 
1218  parent.set_subplotspec(gs[0])
1219  parent.update_params()
1220  parent.set_position(parent.figbox)
1221  parent.set_anchor(panchor)
1222 
1223  fig = parent.get_figure()
1224  cax = fig.add_subplot(gs2[1])
1225  cax.set_aspect(aspect, anchor=anchor, adjustable='box')
1226  return cax, kw
1227 
1228 
1230  """
1231  A Colorbar which is created using :class:`~matplotlib.patches.Patch`
1232  rather than the default :func:`~matplotlib.axes.pcolor`.
1233 
1234  It uses a list of Patch instances instead of a
1235  :class:`~matplotlib.collections.PatchCollection` because the
1236  latter does not allow the hatch pattern to vary among the
1237  members of the collection.
1238  """
1239  def __init__(self, ax, mappable, **kw):
1240  # we do not want to override the behaviour of solids
1241  # so add a new attribute which will be a list of the
1242  # colored patches in the colorbar
1243  self.solids_patches = []
1244  Colorbar.__init__(self, ax, mappable, **kw)
1245 
1246  def _add_solids(self, X, Y, C):
1247  """
1248  Draw the colors using :class:`~matplotlib.patches.Patch`;
1249  optionally add separators.
1250  """
1251  # Save, set, and restore hold state to keep pcolor from
1252  # clearing the axes. Ordinarily this will not be needed,
1253  # since the axes object should already have hold set.
1254  _hold = self.ax.ishold()
1255  self.ax.hold(True)
1256 
1257  kw = {'alpha': self.alpha, }
1258 
1259  n_segments = len(C)
1260 
1261  # ensure there are sufficent hatches
1262  hatches = self.mappable.hatches * n_segments
1263 
1264  patches = []
1265  for i in xrange(len(X) - 1):
1266  val = C[i][0]
1267  hatch = hatches[i]
1268 
1269  xy = np.array([[X[i][0], Y[i][0]],
1270  [X[i][1], Y[i][0]],
1271  [X[i + 1][1], Y[i + 1][0]],
1272  [X[i + 1][0], Y[i + 1][1]]])
1273 
1274  if self.orientation == 'horizontal':
1275  # if horizontal swap the xs and ys
1276  xy = xy[..., ::-1]
1277 
1278  patch = mpatches.PathPatch(mpath.Path(xy),
1279  facecolor=self.cmap(self.norm(val)),
1280  hatch=hatch, linewidth=0,
1281  antialiased=False, **kw)
1282  self.ax.add_patch(patch)
1283  patches.append(patch)
1284 
1285  if self.solids_patches:
1286  for solid in self.solids_patches:
1287  solid.remove()
1288 
1289  self.solids_patches = patches
1290 
1291  if self.dividers is not None:
1292  self.dividers.remove()
1293  self.dividers = None
1294 
1295  if self.drawedges:
1296  self.dividers = collections.LineCollection(self._edges(X, Y),
1297  colors=(mpl.rcParams['axes.edgecolor'],),
1298  linewidths=(0.5 * mpl.rcParams['axes.linewidth'],))
1299  self.ax.add_collection(self.dividers)
1300 
1301  self.ax.hold(_hold)
1302 
1303 
1304 def colorbar_factory(cax, mappable, **kwargs):
1305  """
1306  Creates a colorbar on the given axes for the given mappable.
1307 
1308  Typically, for automatic colorbar placement given only a mappable use
1309  :meth:`~matplotlib.figure.Figure.colorbar`.
1310 
1311  """
1312  # if the given mappable is a contourset with any hatching, use
1313  # ColorbarPatch else use Colorbar
1314  if (isinstance(mappable, contour.ContourSet)
1315  and any([hatch is not None for hatch in mappable.hatches])):
1316  cb = ColorbarPatch(cax, mappable, **kwargs)
1317  else:
1318  cb = Colorbar(cax, mappable, **kwargs)
1319 
1320  cid = mappable.callbacksSM.connect('changed', cb.on_mappable_changed)
1321  mappable.colorbar = cb
1322  mappable.colorbar_cid = cid
1323 
1324  return cb
def __init__(self, ax, cmap=None, norm=None, alpha=None, values=None, boundaries=None, orientation='vertical', ticklocation='auto', extend='neither', spacing='uniform', ticks=None, format=None, drawedges=False, filled=True, extendfrac=None, extendrect=False, label='')
Definition: colorbar.py:275
def update_normal(self, mappable)
Definition: colorbar.py:931
def on_mappable_changed(self, mappable)
Definition: colorbar.py:896
def update_bruteforce(self, mappable)
Definition: colorbar.py:943
def _add_solids(self, X, Y, C)
Definition: colorbar.py:483
def make_axes_gridspec(parent, kw)
Definition: colorbar.py:1130
def set_cmap(self, cmap)
Definition: cm.py:301
def set_label(self, label, kw)
Definition: colorbar.py:448
def __init__(self, ax, mappable, kw)
Definition: colorbar.py:1239
def __init__(self, ax, mappable, kw)
Definition: colorbar.py:866
def make_axes(parents, location=None, orientation=None, fraction=0.15, shrink=1.0, aspect=20, kw)
Definition: colorbar.py:1010
def colorbar_factory(cax, mappable, kwargs)
Definition: colorbar.py:1304
def set_alpha(self, alpha)
Definition: colorbar.py:842
def _config_axes(self, X, Y)
Definition: colorbar.py:409