Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit382eca7

Browse files
committed
Cleanup logic and documentation of tripcolor
This issues more and more precise warnings on usage errors but does notchange behavior.
1 parent39cfe2b commit382eca7

File tree

3 files changed

+163
-62
lines changed

3 files changed

+163
-62
lines changed

‎lib/matplotlib/tests/test_triangulation.py

Lines changed: 70 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -41,21 +41,42 @@ def test_extract_triangulation_params(args, kwargs, expected):
4141
assertkwargs_==other_kwargs
4242

4343

44+
delx
45+
dely
46+
deltriangles
47+
delmask
48+
49+
4450
deftest_extract_triangulation_positional_mask():
45-
globalx,y,triangles,mask
4651
# mask cannot be passed positionally
52+
mask= [True]
53+
args= [[0,2,1], [0,0,1], [[0,1,2]],mask]
4754
x_,y_,triangles_,mask_,args_,kwargs_= \
48-
mtri.Triangulation._extract_triangulation_params(x,y,triangles,mask)
55+
mtri.Triangulation._extract_triangulation_params(args, {})
4956
assertmask_isNone
5057
assertargs_== [mask]
5158
# the positional mask has to be catched downstream because this must pass
5259
# unknown args through
5360

5461

55-
delx
56-
dely
57-
deltriangles
58-
delmask
62+
deftest_triangulation_init():
63+
x= [-1,0,1,0]
64+
y= [0,-1,0,1]
65+
withpytest.raises(ValueError,match="x and y must be equal-length"):
66+
mtri.Triangulation(x, [1,2])
67+
withpytest.raises(
68+
ValueError,
69+
match=r"triangles must be a \(N, 3\) array, but found shape "
70+
r"\(3,\)"):
71+
mtri.Triangulation(x,y, [0,1,2])
72+
withpytest.raises(
73+
ValueError,
74+
match=r"triangles must be a \(N, 3\) int array, not 'other'"):
75+
mtri.Triangulation(x,y,'other')
76+
withpytest.raises(ValueError,match="found value 99"):
77+
mtri.Triangulation(x,y, [[0,1,99]])
78+
withpytest.raises(ValueError,match="found value -1"):
79+
mtri.Triangulation(x,y, [[0,1,-1]])
5980

6081

6182
deftest_delaunay():
@@ -223,6 +244,49 @@ def test_tripcolor():
223244
plt.title('facecolors')
224245

225246

247+
deftest_tripcolor_color():
248+
x= [-1,0,1,0]
249+
y= [0,-1,0,1]
250+
fig,ax=plt.subplots()
251+
withpytest.raises(ValueError,match="Missing color parameter"):
252+
ax.tripcolor(x,y)
253+
withpytest.raises(ValueError,match="The length of C must match either"):
254+
ax.tripcolor(x,y, [1,2,3])
255+
withpytest.raises(ValueError,
256+
match="length of facecolors must match .* triangles"):
257+
ax.tripcolor(x,y,facecolors=[1,2,3,4])
258+
withpytest.raises(ValueError,
259+
match="'gouraud' .* at the points.* not at the faces"):
260+
ax.tripcolor(x,y,facecolors=[1,2],shading='gouraud')
261+
withpytest.raises(ValueError,
262+
match="'gouraud' .* at the points.* not at the faces"):
263+
ax.tripcolor(x,y, [1,2],shading='gouraud')# faces
264+
withpytest.raises(ValueError,
265+
match=r"pass C positionally or facecolors via keyword"):
266+
ax.tripcolor(x,y,C=[1,2,3,4])
267+
268+
# smoke test for valid color specifications (via C or facecolors)
269+
ax.tripcolor(x,y, [1,2,3,4])# edges
270+
ax.tripcolor(x,y, [1,2,3,4],shading='gouraud')# edges
271+
ax.tripcolor(x,y, [1,2])# faces
272+
ax.tripcolor(x,y,facecolors=[1,2])# faces
273+
274+
275+
deftest_tripcolor_warnings():
276+
x= [-1,0,1,0]
277+
y= [0,-1,0,1]
278+
C= [0.4,0.5]
279+
fig,ax=plt.subplots()
280+
# additional parameters
281+
withpytest.warns(UserWarning,match="Additional positional parameters"):
282+
ax.tripcolor(x,y,C,'unused_positional')
283+
# facecolors takes precednced over C
284+
withpytest.warns(UserWarning,match="Positional parameter C .*no effect"):
285+
ax.tripcolor(x,y,C,facecolors=C)
286+
withpytest.warns(UserWarning,match="Positional parameter C .*no effect"):
287+
ax.tripcolor(x,y,'interpreted as C',facecolors=C)
288+
289+
226290
deftest_no_modify():
227291
# Test that Triangulation does not modify triangles array passed to it.
228292
triangles=np.array([[3,2,0], [3,1,0]],dtype=np.int32)

‎lib/matplotlib/tri/triangulation.py

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,9 @@ def __init__(self, x, y, triangles=None, mask=None):
4343
self.x=np.asarray(x,dtype=np.float64)
4444
self.y=np.asarray(y,dtype=np.float64)
4545
ifself.x.shape!=self.y.shapeorself.x.ndim!=1:
46-
raiseValueError("x and y must be equal-length 1D arrays")
46+
raiseValueError("x and y must be equal-length 1D arrays, but "
47+
f"found shapes{self.x.shape!r} and "
48+
f"{self.y.shape!r}")
4749

4850
self.mask=None
4951
self._edges=None
@@ -58,13 +60,25 @@ def __init__(self, x, y, triangles=None, mask=None):
5860
else:
5961
# Triangulation specified. Copy, since we may correct triangle
6062
# orientation.
61-
self.triangles=np.array(triangles,dtype=np.int32,order='C')
63+
try:
64+
self.triangles=np.array(triangles,dtype=np.int32,order='C')
65+
exceptValueErrorase:
66+
raiseValueError('triangles must be a (N, 3) int array, not '
67+
f'{triangles!r}')frome
6268
ifself.triangles.ndim!=2orself.triangles.shape[1]!=3:
63-
raiseValueError('triangles must be a (?, 3) array')
69+
raiseValueError(
70+
'triangles must be a (N, 3) array, but found shape '
71+
f'{self.triangles.shape!r}')
6472
ifself.triangles.max()>=len(self.x):
65-
raiseValueError('triangles max element is out of bounds')
73+
raiseValueError(
74+
'triangles are indices into the points and must be in the '
75+
f'range 0 <= i <{len(self.x)} but found value '
76+
f'{self.triangles.max()}')
6677
ifself.triangles.min()<0:
67-
raiseValueError('triangles min element is out of bounds')
78+
raiseValueError(
79+
'triangles are indices into the points and must be in the '
80+
f'range 0 <= i <{len(self.x)} but found value '
81+
f'{self.triangles.min()}')
6882

6983
ifmaskisnotNone:
7084
self.mask=np.asarray(mask,dtype=bool)

‎lib/matplotlib/tri/tripcolor.py

Lines changed: 74 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -21,62 +21,85 @@ def tripcolor(ax, *args, alpha=1.0, norm=None, cmap=None, vmin=None,
2121
optionally the *triangles* and a *mask*. See `.Triangulation` for an
2222
explanation of these parameters.
2323
24+
If neither of *triangulation* or *triangles* are given, the triangulation
25+
is calculated on the fly. In this case, it does not make sense to provide
26+
colors at the triangle faces via *C* or *facecolors* because there are
27+
multiple possible triangulations for a group of points and you don't know
28+
which triangles will be constructed.
29+
2430
Parameters
2531
----------
2632
triangulation : `.Triangulation`
2733
An already created triangular grid.
2834
x, y, triangles, mask
2935
Parameters specifying defining the triangular grid. See
30-
`.Triangulation`.
31-
32-
33-
The next argument must be *C*, the array of color values, either
34-
one per point in the triangulation if color values are defined at
35-
points, or one per triangle in the triangulation if color values
36-
are defined at triangles. If there are the same number of points
37-
and triangles in the triangulation it is assumed that color
38-
values are defined at points; to force the use of color values at
39-
triangles use the kwarg ``facecolors=C`` instead of just ``C``.
40-
41-
*shading* may be 'flat' (the default) or 'gouraud'. If *shading*
42-
is 'flat' and C values are defined at points, the color values
43-
used for each triangle are from the mean C of the triangle's
44-
three points. If *shading* is 'gouraud' then color values must be
45-
defined at points.
46-
47-
48-
49-
tripcolor(x, y, [triangles], C, [mask=mask], ...)
50-
51-
52-
The remaining kwargs are the same as for `~.Axes.pcolor`.
36+
`.Triangulation`. This is mutually exclusive with specifying
37+
*triangulation*.
38+
C : array-like
39+
The color values, either for the points or for the triangles. Which one
40+
is automatically inferred from the length of *C*, i.e. does it match
41+
the number of points or the number of triangles. If there are the same
42+
number of points and triangles in the triangulation it is assumed that
43+
color values are defined at points; to force the use of color values at
44+
triangles use the keyword argument ``facecolors=C`` instead of just
45+
``C``.
46+
This parameter is position-only.
47+
facecolors : array-like, optional
48+
Can be used alternatively to *C* to specify colors at the triangle
49+
faces. This parameter takes precedence over *C*.
50+
shading : {'flat', 'gouraud'}, default: 'flat'
51+
If is 'flat' and the color values *C* are defined at points, the color
52+
values used for each triangle are from the mean C of the triangle's
53+
three points. If *shading* is 'gouraud' then color values must be
54+
defined at points.
55+
other parameters
56+
All other parameters are the same as for `~.Axes.pcolor`.
57+
58+
Notes
59+
-----
60+
It is possible to pass the triangles positionally, i.e. using the call
61+
signature ``tripcolor(x, y, triangles, C, [mask=mask], ...)``. However,
62+
this is discouraged. For more clarity, pass *triangles* via keyword
63+
argument.
5364
"""
5465
_api.check_in_list(['flat','gouraud'],shading=shading)
5566

5667
tri,args,kwargs=Triangulation.get_from_args_and_kwargs(*args,**kwargs)
5768

58-
#C isthecolors array defined at either points or faces (i.e. triangles).
59-
#If facecolors is None, C are defined at points.
60-
#If facecolors is not None, C are definedatfaces.
69+
#Parsethecolor to be in one of (the other variable will be None):
70+
#- facecolors: if specified at the triangle faces
71+
#- node_colors: if specifiedatthe points
6172
iffacecolorsisnotNone:
62-
C=facecolors
73+
print(args)
74+
ifargs:
75+
_api.warn_external(
76+
"Positional parameter C has no effect when the keyword "
77+
"facecolors is given")
78+
node_colors=None
79+
iflen(facecolors)!=len(tri.triangles):
80+
raiseValueError("The length of facecolors must match the number "
81+
"of triangles")
6382
else:
83+
# Color from positional parameter C
84+
ifnotargs:
85+
raiseValueError(
86+
"Missing color parameter. Please pass C positionally or "
87+
"facecolors via keyword")
88+
eliflen(args)>1:
89+
_api.warn_external(
90+
"Additional positional parameters {args[1:]!r} are ignored")
6491
C=np.asarray(args[0])
65-
66-
# If there are a different number of points and triangles in the
67-
# triangulation, can omit facecolors kwarg as it is obvious from
68-
# length of C whether it refers to points or faces.
69-
# Do not do this for gouraud shading.
70-
if (facecolorsisNoneandlen(C)==len(tri.triangles)and
71-
len(C)!=len(tri.x)andshading!='gouraud'):
72-
facecolors=C
73-
74-
# Check length of C is OK.
75-
if ((facecolorsisNoneandlen(C)!=len(tri.x))or
76-
(facecolorsisnotNoneandlen(C)!=len(tri.triangles))):
77-
raiseValueError('Length of color values array must be the same '
78-
'as either the number of triangulation points '
79-
'or triangles')
92+
iflen(C)==len(tri.x):
93+
# having this before the len(tri.triangles) comparison gives
94+
# precedence to nodes if there are as many nodes as triangles
95+
node_colors=C
96+
facecolors=None
97+
eliflen(C)==len(tri.triangles):
98+
node_colors=None
99+
facecolors=C
100+
else:
101+
raiseValueError('The length of C must match either the number '
102+
'of points or the number of triangles')
80103

81104
# Handling of linewidths, shading, edgecolors and antialiased as
82105
# in Axes.pcolor
@@ -97,13 +120,11 @@ def tripcolor(ax, *args, alpha=1.0, norm=None, cmap=None, vmin=None,
97120

98121
ifshading=='gouraud':
99122
iffacecolorsisnotNone:
100-
raiseValueError('Gouraud shading does not support the use '
101-
'of facecolors kwarg')
102-
iflen(C)!=len(tri.x):
103-
raiseValueError('For gouraud shading, the length of color '
104-
'values array must be the same as the '
105-
'number of triangulation points')
123+
raiseValueError(
124+
"shading='gouraud' can only be used when the colors "
125+
"are specified at the points, not at the faces.")
106126
collection=TriMesh(tri,**kwargs)
127+
colors=node_colors
107128
else:
108129
# Vertices of triangles.
109130
maskedTris=tri.get_masked_triangles()
@@ -112,15 +133,17 @@ def tripcolor(ax, *args, alpha=1.0, norm=None, cmap=None, vmin=None,
112133
# Color values.
113134
iffacecolorsisNone:
114135
# One color per triangle, the mean of the 3 vertex color values.
115-
C=C[maskedTris].mean(axis=1)
136+
colors=node_colors[maskedTris].mean(axis=1)
116137
eliftri.maskisnotNone:
117138
# Remove color values of masked triangles.
118-
C=C[~tri.mask]
139+
colors=facecolors[~tri.mask]
140+
else:
141+
colors=facecolors
119142

120143
collection=PolyCollection(verts,**kwargs)
121144

122145
collection.set_alpha(alpha)
123-
collection.set_array(C)
146+
collection.set_array(colors)
124147
_api.check_isinstance((Normalize,None),norm=norm)
125148
collection.set_cmap(cmap)
126149
collection.set_norm(norm)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp