tricontour.py
11.0 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
import numpy as np
from matplotlib import docstring
from matplotlib.contour import ContourSet
from matplotlib.tri.triangulation import Triangulation
class TriContourSet(ContourSet):
"""
Create and store a set of contour lines or filled regions for
a triangular grid.
User-callable method: clabel
Attributes
----------
ax
The axes object in which the contours are drawn.
collections
A silent_list of LineCollections or PolyCollections.
levels
Contour levels.
layers
Same as levels for line contours; half-way between
levels for filled contours. See :meth:`_process_colors`.
"""
def __init__(self, ax, *args, **kwargs):
"""
Draw triangular grid contour lines or filled regions,
depending on whether keyword arg 'filled' is False
(default) or True.
The first argument of the initializer must be an axes
object. The remaining arguments and keyword arguments
are described in the docstring of `~.Axes.tricontour`.
"""
ContourSet.__init__(self, ax, *args, **kwargs)
def _process_args(self, *args, **kwargs):
"""
Process args and kwargs.
"""
if isinstance(args[0], TriContourSet):
C = args[0].cppContourGenerator
if self.levels is None:
self.levels = args[0].levels
else:
from matplotlib import _tri
tri, z = self._contour_args(args, kwargs)
C = _tri.TriContourGenerator(tri.get_cpp_triangulation(), z)
self._mins = [tri.x.min(), tri.y.min()]
self._maxs = [tri.x.max(), tri.y.max()]
self.cppContourGenerator = C
return kwargs
def _get_allsegs_and_allkinds(self):
"""
Create and return allsegs and allkinds by calling underlying C code.
"""
allsegs = []
if self.filled:
lowers, uppers = self._get_lowers_and_uppers()
allkinds = []
for lower, upper in zip(lowers, uppers):
segs, kinds = self.cppContourGenerator.create_filled_contour(
lower, upper)
allsegs.append([segs])
allkinds.append([kinds])
else:
allkinds = None
for level in self.levels:
segs = self.cppContourGenerator.create_contour(level)
allsegs.append(segs)
return allsegs, allkinds
def _contour_args(self, args, kwargs):
if self.filled:
fn = 'contourf'
else:
fn = 'contour'
tri, args, kwargs = Triangulation.get_from_args_and_kwargs(*args,
**kwargs)
z = np.ma.asarray(args[0])
if z.shape != tri.x.shape:
raise ValueError('z array must have same length as triangulation x'
' and y arrays')
# z values must be finite, only need to check points that are included
# in the triangulation.
z_check = z[np.unique(tri.get_masked_triangles())]
if np.ma.is_masked(z_check):
raise ValueError('z must not contain masked points within the '
'triangulation')
if not np.isfinite(z_check).all():
raise ValueError('z array must not contain non-finite values '
'within the triangulation')
z = np.ma.masked_invalid(z, copy=False)
self.zmax = float(z_check.max())
self.zmin = float(z_check.min())
if self.logscale and self.zmin <= 0:
raise ValueError('Cannot %s log of negative values.' % fn)
self._process_contour_level_args(args[1:])
return (tri, z)
docstring.interpd.update(_tricontour_doc="""
Draw contour %(type)s on an unstructured triangular grid.
The triangulation can be specified in one of two ways; either ::
%(func)s(triangulation, ...)
where *triangulation* is a `.Triangulation` object, or ::
%(func)s(x, y, ...)
%(func)s(x, y, triangles, ...)
%(func)s(x, y, triangles=triangles, ...)
%(func)s(x, y, mask=mask, ...)
%(func)s(x, y, triangles, mask=mask, ...)
in which case a `.Triangulation` object will be created. See that class'
docstring for an explanation of these cases.
The remaining arguments may be::
%(func)s(..., Z)
where *Z* is the array of values to contour, one per point in the
triangulation. The level values are chosen automatically.
::
%(func)s(..., Z, levels)
contour up to *levels+1* automatically chosen contour levels (*levels*
intervals).
::
%(func)s(..., Z, levels)
draw contour %(type)s at the values specified in sequence *levels*, which must
be in increasing order.
::
%(func)s(Z, **kwargs)
Use keyword arguments to control colors, linewidth, origin, cmap ... see below
for more details.
Parameters
----------
triangulation : `.Triangulation`, optional
The unstructured triangular grid.
If specified, then *x*, *y*, *triangles*, and *mask* are not accepted.
x, y : array-like, optional
The coordinates of the values in *Z*.
triangles : int array-like of shape (ntri, 3), optional
For each triangle, the indices of the three points that make up the
triangle, ordered in an anticlockwise manner. If not specified, the
Delaunay triangulation is calculated.
mask : bool array-like of shape (ntri), optional
Which triangles are masked out.
Z : array-like(N, M)
The height values over which the contour is drawn.
levels : int or array-like, optional
Determines the number and positions of the contour lines / regions.
If an int *n*, use `~matplotlib.ticker.MaxNLocator`, which tries to
automatically choose no more than *n+1* "nice" contour levels between
*vmin* and *vmax*.
If array-like, draw contour lines at the specified levels. The values must
be in increasing order.
Returns
-------
`~matplotlib.tri.TriContourSet`
Other Parameters
----------------
colors : color string or sequence of colors, optional
The colors of the levels, i.e., the contour %(type)s.
The sequence is cycled for the levels in ascending order. If the sequence
is shorter than the number of levels, it's repeated.
As a shortcut, single color strings may be used in place of one-element
lists, i.e. ``'red'`` instead of ``['red']`` to color all levels with the
same color. This shortcut does only work for color strings, not for other
ways of specifying colors.
By default (value *None*), the colormap specified by *cmap* will be used.
alpha : float, default: 1
The alpha blending value, between 0 (transparent) and 1 (opaque).
cmap : str or `.Colormap`, default: :rc:`image.cmap`
A `.Colormap` instance or registered colormap name. The colormap maps the
level values to colors.
If both *colors* and *cmap* are given, an error is raised.
norm : `~matplotlib.colors.Normalize`, optional
If a colormap is used, the `.Normalize` instance scales the level values to
the canonical colormap range [0, 1] for mapping to colors. If not given,
the default linear scaling is used.
origin : {*None*, 'upper', 'lower', 'image'}, default: None
Determines the orientation and exact position of *Z* by specifying the
position of ``Z[0, 0]``. This is only relevant, if *X*, *Y* are not given.
- *None*: ``Z[0, 0]`` is at X=0, Y=0 in the lower left corner.
- 'lower': ``Z[0, 0]`` is at X=0.5, Y=0.5 in the lower left corner.
- 'upper': ``Z[0, 0]`` is at X=N+0.5, Y=0.5 in the upper left corner.
- 'image': Use the value from :rc:`image.origin`.
extent : (x0, x1, y0, y1), optional
If *origin* is not *None*, then *extent* is interpreted as in `.imshow`: it
gives the outer pixel boundaries. In this case, the position of Z[0, 0] is
the center of the pixel, not a corner. If *origin* is *None*, then
(*x0*, *y0*) is the position of Z[0, 0], and (*x1*, *y1*) is the position
of Z[-1, -1].
This argument is ignored if *X* and *Y* are specified in the call to
contour.
locator : ticker.Locator subclass, optional
The locator is used to determine the contour levels if they are not given
explicitly via *levels*.
Defaults to `~.ticker.MaxNLocator`.
extend : {'neither', 'both', 'min', 'max'}, default: 'neither'
Determines the ``%(func)s``-coloring of values that are outside the
*levels* range.
If 'neither', values outside the *levels* range are not colored. If 'min',
'max' or 'both', color the values below, above or below and above the
*levels* range.
Values below ``min(levels)`` and above ``max(levels)`` are mapped to the
under/over values of the `.Colormap`. Note that most colormaps do not have
dedicated colors for these by default, so that the over and under values
are the edge values of the colormap. You may want to set these values
explicitly using `.Colormap.set_under` and `.Colormap.set_over`.
.. note::
An existing `.TriContourSet` does not get notified if properties of its
colormap are changed. Therefore, an explicit call to
`.ContourSet.changed()` is needed after modifying the colormap. The
explicit call can be left out, if a colorbar is assigned to the
`.TriContourSet` because it internally calls `.ContourSet.changed()`.
xunits, yunits : registered units, optional
Override axis units by specifying an instance of a
:class:`matplotlib.units.ConversionInterface`.""")
@docstring.Substitution(func='tricontour', type='lines')
@docstring.dedent_interpd
def tricontour(ax, *args, **kwargs):
"""
%(_tricontour_doc)s
linewidths : float or array-like, default: :rc:`contour.linewidth`
The line width of the contour lines.
If a number, all levels will be plotted with this linewidth.
If a sequence, the levels in ascending order will be plotted with
the linewidths in the order specified.
If None, this falls back to :rc:`lines.linewidth`.
linestyles : {*None*, 'solid', 'dashed', 'dashdot', 'dotted'}, optional
If *linestyles* is *None*, the default is 'solid' unless the lines are
monochrome. In that case, negative contours will take their linestyle
from :rc:`contour.negative_linestyle` setting.
*linestyles* can also be an iterable of the above strings specifying a
set of linestyles to be used. If this iterable is shorter than the
number of contour levels it will be repeated as necessary.
"""
kwargs['filled'] = False
return TriContourSet(ax, *args, **kwargs)
@docstring.Substitution(func='tricontourf', type='regions')
@docstring.dedent_interpd
def tricontourf(ax, *args, **kwargs):
"""
%(_tricontour_doc)s
antialiased : bool, default: True
Whether to use antialiasing.
Notes
-----
`.tricontourf` fills intervals that are closed at the top; that is, for
boundaries *z1* and *z2*, the filled region is::
z1 < Z <= z2
except for the lowest interval, which is closed on both sides (i.e. it
includes the lowest value).
"""
kwargs['filled'] = True
return TriContourSet(ax, *args, **kwargs)