tricontour.py 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. import numpy as np
  2. from matplotlib.contour import ContourSet
  3. from matplotlib.tri.triangulation import Triangulation
  4. class TriContourSet(ContourSet):
  5. """
  6. Create and store a set of contour lines or filled regions for
  7. a triangular grid.
  8. User-callable method: clabel
  9. Useful attributes:
  10. ax:
  11. the axes object in which the contours are drawn
  12. collections:
  13. a silent_list of LineCollections or PolyCollections
  14. levels:
  15. contour levels
  16. layers:
  17. same as levels for line contours; half-way between
  18. levels for filled contours. See _process_colors method.
  19. """
  20. def __init__(self, ax, *args, **kwargs):
  21. """
  22. Draw triangular grid contour lines or filled regions,
  23. depending on whether keyword arg 'filled' is False
  24. (default) or True.
  25. The first argument of the initializer must be an axes
  26. object. The remaining arguments and keyword arguments
  27. are described in the docstring of `tricontour`.
  28. """
  29. ContourSet.__init__(self, ax, *args, **kwargs)
  30. def _process_args(self, *args, **kwargs):
  31. """
  32. Process args and kwargs.
  33. """
  34. if isinstance(args[0], TriContourSet):
  35. C = args[0].cppContourGenerator
  36. if self.levels is None:
  37. self.levels = args[0].levels
  38. else:
  39. from matplotlib import _tri
  40. tri, z = self._contour_args(args, kwargs)
  41. C = _tri.TriContourGenerator(tri.get_cpp_triangulation(), z)
  42. self._mins = [tri.x.min(), tri.y.min()]
  43. self._maxs = [tri.x.max(), tri.y.max()]
  44. self.cppContourGenerator = C
  45. return kwargs
  46. def _get_allsegs_and_allkinds(self):
  47. """
  48. Create and return allsegs and allkinds by calling underlying C code.
  49. """
  50. allsegs = []
  51. if self.filled:
  52. lowers, uppers = self._get_lowers_and_uppers()
  53. allkinds = []
  54. for lower, upper in zip(lowers, uppers):
  55. segs, kinds = self.cppContourGenerator.create_filled_contour(
  56. lower, upper)
  57. allsegs.append([segs])
  58. allkinds.append([kinds])
  59. else:
  60. allkinds = None
  61. for level in self.levels:
  62. segs = self.cppContourGenerator.create_contour(level)
  63. allsegs.append(segs)
  64. return allsegs, allkinds
  65. def _contour_args(self, args, kwargs):
  66. if self.filled:
  67. fn = 'contourf'
  68. else:
  69. fn = 'contour'
  70. tri, args, kwargs = Triangulation.get_from_args_and_kwargs(*args,
  71. **kwargs)
  72. z = np.ma.asarray(args[0])
  73. if z.shape != tri.x.shape:
  74. raise ValueError('z array must have same length as triangulation x'
  75. ' and y arrays')
  76. # z values must be finite, only need to check points that are included
  77. # in the triangulation.
  78. z_check = z[np.unique(tri.get_masked_triangles())]
  79. if np.ma.is_masked(z_check):
  80. raise ValueError('z must not contain masked points within the '
  81. 'triangulation')
  82. if not np.isfinite(z_check).all():
  83. raise ValueError('z array must not contain non-finite values '
  84. 'within the triangulation')
  85. z = np.ma.masked_invalid(z, copy=False)
  86. self.zmax = float(z_check.max())
  87. self.zmin = float(z_check.min())
  88. if self.logscale and self.zmin <= 0:
  89. raise ValueError('Cannot %s log of negative values.' % fn)
  90. self._contour_level_args(z, args[1:])
  91. return (tri, z)
  92. def tricontour(ax, *args, **kwargs):
  93. """
  94. Draw contours on an unstructured triangular grid.
  95. `.tricontour` and `.tricontourf` draw contour lines and filled contours,
  96. respectively. Except as noted, function signatures and return values are
  97. the same for both versions.
  98. The triangulation can be specified in one of two ways; either ::
  99. tricontour(triangulation, ...)
  100. where *triangulation* is a `matplotlib.tri.Triangulation` object, or ::
  101. tricontour(x, y, ...)
  102. tricontour(x, y, triangles, ...)
  103. tricontour(x, y, triangles=triangles, ...)
  104. tricontour(x, y, mask=mask, ...)
  105. tricontour(x, y, triangles, mask=mask, ...)
  106. in which case a `.Triangulation` object will be created. See that class'
  107. docstring for an explanation of these cases.
  108. The remaining arguments may be::
  109. tricontour(..., Z)
  110. where *Z* is the array of values to contour, one per point in the
  111. triangulation. The level values are chosen automatically.
  112. ::
  113. tricontour(..., Z, N)
  114. contour up to *N+1* automatically chosen contour levels (*N* intervals).
  115. ::
  116. tricontour(..., Z, V)
  117. draw contour lines at the values specified in sequence *V*,
  118. which must be in increasing order.
  119. ::
  120. tricontourf(..., Z, V)
  121. fill the (len(*V*)-1) regions between the values in *V*,
  122. which must be in increasing order.
  123. ::
  124. tricontour(Z, **kwargs)
  125. Use keyword args to control colors, linewidth, origin, cmap ... see
  126. below for more details.
  127. `.tricontour(...)` returns a `~matplotlib.contour.TriContourSet` object.
  128. Optional keyword arguments:
  129. *colors*: [ *None* | string | (mpl_colors) ]
  130. If *None*, the colormap specified by cmap will be used.
  131. If a string, like 'r' or 'red', all levels will be plotted in this
  132. color.
  133. If a tuple of matplotlib color args (string, float, rgb, etc),
  134. different levels will be plotted in different colors in the order
  135. specified.
  136. *alpha*: float
  137. The alpha blending value
  138. *cmap*: [ *None* | Colormap ]
  139. A cm :class:`~matplotlib.colors.Colormap` instance or
  140. *None*. If *cmap* is *None* and *colors* is *None*, a
  141. default Colormap is used.
  142. *norm*: [ *None* | Normalize ]
  143. A :class:`matplotlib.colors.Normalize` instance for
  144. scaling data values to colors. If *norm* is *None* and
  145. *colors* is *None*, the default linear scaling is used.
  146. *levels* [level0, level1, ..., leveln]
  147. A list of floating point numbers indicating the level
  148. curves to draw, in increasing order; e.g., to draw just
  149. the zero contour pass ``levels=[0]``
  150. *origin*: [ *None* | 'upper' | 'lower' | 'image' ]
  151. If *None*, the first value of *Z* will correspond to the
  152. lower left corner, location (0, 0). If 'image', the rc
  153. value for ``image.origin`` will be used.
  154. This keyword is not active if *X* and *Y* are specified in
  155. the call to contour.
  156. *extent*: [ *None* | (x0, x1, y0, y1) ]
  157. If *origin* is not *None*, then *extent* is interpreted as
  158. in :func:`matplotlib.pyplot.imshow`: it gives the outer
  159. pixel boundaries. In this case, the position of Z[0, 0]
  160. is the center of the pixel, not a corner. If *origin* is
  161. *None*, then (*x0*, *y0*) is the position of Z[0, 0], and
  162. (*x1*, *y1*) is the position of Z[-1,-1].
  163. This keyword is not active if *X* and *Y* are specified in
  164. the call to contour.
  165. *locator*: [ *None* | ticker.Locator subclass ]
  166. If *locator* is None, the default
  167. :class:`~matplotlib.ticker.MaxNLocator` is used. The
  168. locator is used to determine the contour levels if they
  169. are not given explicitly via the *V* argument.
  170. *extend*: [ 'neither' | 'both' | 'min' | 'max' ]
  171. Unless this is 'neither', contour levels are automatically
  172. added to one or both ends of the range so that all data
  173. are included. These added ranges are then mapped to the
  174. special colormap values which default to the ends of the
  175. colormap range, but can be set via
  176. :meth:`matplotlib.colors.Colormap.set_under` and
  177. :meth:`matplotlib.colors.Colormap.set_over` methods.
  178. *xunits*, *yunits*: [ *None* | registered units ]
  179. Override axis units by specifying an instance of a
  180. :class:`matplotlib.units.ConversionInterface`.
  181. tricontour-only keyword arguments:
  182. *linewidths*: [ *None* | number | tuple of numbers ]
  183. If *linewidths* is *None*, defaults to rc:`lines.linewidth`.
  184. If a number, all levels will be plotted with this linewidth.
  185. If a tuple, different levels will be plotted with different
  186. linewidths in the order specified
  187. *linestyles*: [ *None* | 'solid' | 'dashed' | 'dashdot' | 'dotted' ]
  188. If *linestyles* is *None*, the 'solid' is used.
  189. *linestyles* can also be an iterable of the above strings
  190. specifying a set of linestyles to be used. If this
  191. iterable is shorter than the number of contour levels
  192. it will be repeated as necessary.
  193. If contour is using a monochrome colormap and the contour
  194. level is less than 0, then the linestyle specified
  195. in :rc:`contour.negative_linestyle` will be used.
  196. tricontourf-only keyword arguments:
  197. *antialiased*: bool
  198. enable antialiasing
  199. Note: `.tricontourf` fills intervals that are closed at the top; that is,
  200. for boundaries *z1* and *z2*, the filled region is::
  201. z1 < Z <= z2
  202. except for the lowest interval, which is closed on both sides (i.e. it
  203. includes the lowest value).
  204. """
  205. kwargs['filled'] = False
  206. return TriContourSet(ax, *args, **kwargs)
  207. def tricontourf(ax, *args, **kwargs):
  208. kwargs['filled'] = True
  209. return TriContourSet(ax, *args, **kwargs)
  210. tricontourf.__doc__ = tricontour.__doc__