1import numpy as np
2
3from matplotlib import _docstring
4from matplotlib.contour import ContourSet
5from matplotlib.tri._triangulation import Triangulation
6
7
8@_docstring.dedent_interpd
9class TriContourSet(ContourSet):
10 """
11 Create and store a set of contour lines or filled regions for
12 a triangular grid.
13
14 This class is typically not instantiated directly by the user but by
15 `~.Axes.tricontour` and `~.Axes.tricontourf`.
16
17 %(contour_set_attributes)s
18 """
19 def __init__(self, ax, *args, **kwargs):
20 """
21 Draw triangular grid contour lines or filled regions,
22 depending on whether keyword arg *filled* is False
23 (default) or True.
24
25 The first argument of the initializer must be an `~.axes.Axes`
26 object. The remaining arguments and keyword arguments
27 are described in the docstring of `~.Axes.tricontour`.
28 """
29 super().__init__(ax, *args, **kwargs)
30
31 def _process_args(self, *args, **kwargs):
32 """
33 Process args and kwargs.
34 """
35 if isinstance(args[0], TriContourSet):
36 C = args[0]._contour_generator
37 if self.levels is None:
38 self.levels = args[0].levels
39 self.zmin = args[0].zmin
40 self.zmax = args[0].zmax
41 self._mins = args[0]._mins
42 self._maxs = args[0]._maxs
43 else:
44 from matplotlib import _tri
45 tri, z = self._contour_args(args, kwargs)
46 C = _tri.TriContourGenerator(tri.get_cpp_triangulation(), z)
47 self._mins = [tri.x.min(), tri.y.min()]
48 self._maxs = [tri.x.max(), tri.y.max()]
49
50 self._contour_generator = C
51 return kwargs
52
53 def _contour_args(self, args, kwargs):
54 tri, args, kwargs = Triangulation.get_from_args_and_kwargs(*args,
55 **kwargs)
56 z, *args = args
57 z = np.ma.asarray(z)
58 if z.shape != tri.x.shape:
59 raise ValueError('z array must have same length as triangulation x'
60 ' and y arrays')
61
62 # z values must be finite, only need to check points that are included
63 # in the triangulation.
64 z_check = z[np.unique(tri.get_masked_triangles())]
65 if np.ma.is_masked(z_check):
66 raise ValueError('z must not contain masked points within the '
67 'triangulation')
68 if not np.isfinite(z_check).all():
69 raise ValueError('z array must not contain non-finite values '
70 'within the triangulation')
71
72 z = np.ma.masked_invalid(z, copy=False)
73 self.zmax = float(z_check.max())
74 self.zmin = float(z_check.min())
75 if self.logscale and self.zmin <= 0:
76 func = 'contourf' if self.filled else 'contour'
77 raise ValueError(f'Cannot {func} log of negative values.')
78 self._process_contour_level_args(args, z.dtype)
79 return (tri, z)
80
81
82_docstring.interpd.update(_tricontour_doc="""
83Draw contour %%(type)s on an unstructured triangular grid.
84
85Call signatures::
86
87 %%(func)s(triangulation, z, [levels], ...)
88 %%(func)s(x, y, z, [levels], *, [triangles=triangles], [mask=mask], ...)
89
90The triangular grid can be specified either by passing a `.Triangulation`
91object as the first parameter, or by passing the points *x*, *y* and
92optionally the *triangles* and a *mask*. See `.Triangulation` for an
93explanation of these parameters. If neither of *triangulation* or
94*triangles* are given, the triangulation is calculated on the fly.
95
96It is possible to pass *triangles* positionally, i.e.
97``%%(func)s(x, y, triangles, z, ...)``. However, this is discouraged. For more
98clarity, pass *triangles* via keyword argument.
99
100Parameters
101----------
102triangulation : `.Triangulation`, optional
103 An already created triangular grid.
104
105x, y, triangles, mask
106 Parameters defining the triangular grid. See `.Triangulation`.
107 This is mutually exclusive with specifying *triangulation*.
108
109z : array-like
110 The height values over which the contour is drawn. Color-mapping is
111 controlled by *cmap*, *norm*, *vmin*, and *vmax*.
112
113 .. note::
114 All values in *z* must be finite. Hence, nan and inf values must
115 either be removed or `~.Triangulation.set_mask` be used.
116
117levels : int or array-like, optional
118 Determines the number and positions of the contour lines / regions.
119
120 If an int *n*, use `~matplotlib.ticker.MaxNLocator`, which tries to
121 automatically choose no more than *n+1* "nice" contour levels between
122 between minimum and maximum numeric values of *Z*.
123
124 If array-like, draw contour lines at the specified levels. The values must
125 be in increasing order.
126
127Returns
128-------
129`~matplotlib.tri.TriContourSet`
130
131Other Parameters
132----------------
133colors : :mpltype:`color` or list of :mpltype:`color`, optional
134 The colors of the levels, i.e., the contour %%(type)s.
135
136 The sequence is cycled for the levels in ascending order. If the sequence
137 is shorter than the number of levels, it is repeated.
138
139 As a shortcut, single color strings may be used in place of one-element
140 lists, i.e. ``'red'`` instead of ``['red']`` to color all levels with the
141 same color. This shortcut does only work for color strings, not for other
142 ways of specifying colors.
143
144 By default (value *None*), the colormap specified by *cmap* will be used.
145
146alpha : float, default: 1
147 The alpha blending value, between 0 (transparent) and 1 (opaque).
148
149%(cmap_doc)s
150
151 This parameter is ignored if *colors* is set.
152
153%(norm_doc)s
154
155 This parameter is ignored if *colors* is set.
156
157%(vmin_vmax_doc)s
158
159 If *vmin* or *vmax* are not given, the default color scaling is based on
160 *levels*.
161
162 This parameter is ignored if *colors* is set.
163
164origin : {*None*, 'upper', 'lower', 'image'}, default: None
165 Determines the orientation and exact position of *z* by specifying the
166 position of ``z[0, 0]``. This is only relevant, if *X*, *Y* are not given.
167
168 - *None*: ``z[0, 0]`` is at X=0, Y=0 in the lower left corner.
169 - 'lower': ``z[0, 0]`` is at X=0.5, Y=0.5 in the lower left corner.
170 - 'upper': ``z[0, 0]`` is at X=N+0.5, Y=0.5 in the upper left corner.
171 - 'image': Use the value from :rc:`image.origin`.
172
173extent : (x0, x1, y0, y1), optional
174 If *origin* is not *None*, then *extent* is interpreted as in `.imshow`: it
175 gives the outer pixel boundaries. In this case, the position of z[0, 0] is
176 the center of the pixel, not a corner. If *origin* is *None*, then
177 (*x0*, *y0*) is the position of z[0, 0], and (*x1*, *y1*) is the position
178 of z[-1, -1].
179
180 This argument is ignored if *X* and *Y* are specified in the call to
181 contour.
182
183locator : ticker.Locator subclass, optional
184 The locator is used to determine the contour levels if they are not given
185 explicitly via *levels*.
186 Defaults to `~.ticker.MaxNLocator`.
187
188extend : {'neither', 'both', 'min', 'max'}, default: 'neither'
189 Determines the ``%%(func)s``-coloring of values that are outside the
190 *levels* range.
191
192 If 'neither', values outside the *levels* range are not colored. If 'min',
193 'max' or 'both', color the values below, above or below and above the
194 *levels* range.
195
196 Values below ``min(levels)`` and above ``max(levels)`` are mapped to the
197 under/over values of the `.Colormap`. Note that most colormaps do not have
198 dedicated colors for these by default, so that the over and under values
199 are the edge values of the colormap. You may want to set these values
200 explicitly using `.Colormap.set_under` and `.Colormap.set_over`.
201
202 .. note::
203
204 An existing `.TriContourSet` does not get notified if properties of its
205 colormap are changed. Therefore, an explicit call to
206 `.ContourSet.changed()` is needed after modifying the colormap. The
207 explicit call can be left out, if a colorbar is assigned to the
208 `.TriContourSet` because it internally calls `.ContourSet.changed()`.
209
210xunits, yunits : registered units, optional
211 Override axis units by specifying an instance of a
212 :class:`matplotlib.units.ConversionInterface`.
213
214antialiased : bool, optional
215 Enable antialiasing, overriding the defaults. For
216 filled contours, the default is *True*. For line contours,
217 it is taken from :rc:`lines.antialiased`.""" % _docstring.interpd.params)
218
219
220@_docstring.Substitution(func='tricontour', type='lines')
221@_docstring.dedent_interpd
222def tricontour(ax, *args, **kwargs):
223 """
224 %(_tricontour_doc)s
225
226 linewidths : float or array-like, default: :rc:`contour.linewidth`
227 The line width of the contour lines.
228
229 If a number, all levels will be plotted with this linewidth.
230
231 If a sequence, the levels in ascending order will be plotted with
232 the linewidths in the order specified.
233
234 If None, this falls back to :rc:`lines.linewidth`.
235
236 linestyles : {*None*, 'solid', 'dashed', 'dashdot', 'dotted'}, optional
237 If *linestyles* is *None*, the default is 'solid' unless the lines are
238 monochrome. In that case, negative contours will take their linestyle
239 from :rc:`contour.negative_linestyle` setting.
240
241 *linestyles* can also be an iterable of the above strings specifying a
242 set of linestyles to be used. If this iterable is shorter than the
243 number of contour levels it will be repeated as necessary.
244 """
245 kwargs['filled'] = False
246 return TriContourSet(ax, *args, **kwargs)
247
248
249@_docstring.Substitution(func='tricontourf', type='regions')
250@_docstring.dedent_interpd
251def tricontourf(ax, *args, **kwargs):
252 """
253 %(_tricontour_doc)s
254
255 hatches : list[str], optional
256 A list of crosshatch patterns to use on the filled areas.
257 If None, no hatching will be added to the contour.
258
259 Notes
260 -----
261 `.tricontourf` fills intervals that are closed at the top; that is, for
262 boundaries *z1* and *z2*, the filled region is::
263
264 z1 < Z <= z2
265
266 except for the lowest interval, which is closed on both sides (i.e. it
267 includes the lowest value).
268 """
269 kwargs['filled'] = True
270 return TriContourSet(ax, *args, **kwargs)