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

Commitef81739

Browse files
timhoffmQuLogic
andcommitted
Cleanup logic and documentation of tripcolor
This issues more and more precise warnings on usage errors but does notchange behavior.Co-authored-by: Elliott Sales de Andrade <quantum.analyst@gmail.com>
1 parent39cfe2b commitef81739

File tree

3 files changed

+183
-91
lines changed

3 files changed

+183
-91
lines changed

‎lib/matplotlib/tests/test_triangulation.py

Lines changed: 92 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -12,50 +12,65 @@
1212
frommatplotlib.testing.decoratorsimportimage_comparison,check_figures_equal
1313

1414

15-
x= [-1,0,1,0]
16-
y= [0,-1,0,1]
17-
triangles= [[0,1,2], [0,2,3]]
18-
mask= [False,True]
19-
20-
21-
@pytest.mark.parametrize('args, kwargs, expected', [
22-
([x,y], {}, [x,y,None,None]),
23-
([x,y,triangles], {}, [x,y,triangles,None]),
24-
([x,y],dict(triangles=triangles), [x,y,triangles,None]),
25-
([x,y],dict(mask=mask), [x,y,None,mask]),
26-
([x,y,triangles],dict(mask=mask), [x,y,triangles,mask]),
27-
([x,y],dict(triangles=triangles,mask=mask), [x,y,triangles,mask]),
28-
])
29-
deftest_extract_triangulation_params(args,kwargs,expected):
30-
other_args= [1,2]
31-
other_kwargs= {'a':3,'b':'4'}
32-
x_,y_,triangles_,mask_,args_,kwargs_= \
33-
mtri.Triangulation._extract_triangulation_params(
34-
args+other_args, {**kwargs,**other_kwargs})
35-
x,y,triangles,mask=expected
36-
assertx_isx
37-
asserty_isy
38-
assert_array_equal(triangles_,triangles)
39-
assertmask_ismask
40-
assertargs_==other_args
41-
assertkwargs_==other_kwargs
15+
classTestTriangulationParams:
16+
x= [-1,0,1,0]
17+
y= [0,-1,0,1]
18+
triangles= [[0,1,2], [0,2,3]]
19+
mask= [False,True]
20+
21+
@pytest.mark.parametrize('args, kwargs, expected', [
22+
([x,y], {}, [x,y,None,None]),
23+
([x,y,triangles], {}, [x,y,triangles,None]),
24+
([x,y],dict(triangles=triangles), [x,y,triangles,None]),
25+
([x,y],dict(mask=mask), [x,y,None,mask]),
26+
([x,y,triangles],dict(mask=mask), [x,y,triangles,mask]),
27+
([x,y],dict(triangles=triangles,mask=mask), [x,y,triangles,mask]),
28+
])
29+
deftest_extract_triangulation_params(self,args,kwargs,expected):
30+
other_args= [1,2]
31+
other_kwargs= {'a':3,'b':'4'}
32+
x_,y_,triangles_,mask_,args_,kwargs_= \
33+
mtri.Triangulation._extract_triangulation_params(
34+
args+other_args, {**kwargs,**other_kwargs})
35+
x,y,triangles,mask=expected
36+
assertx_isx
37+
asserty_isy
38+
assert_array_equal(triangles_,triangles)
39+
assertmask_ismask
40+
assertargs_==other_args
41+
assertkwargs_==other_kwargs
4242

4343

4444
deftest_extract_triangulation_positional_mask():
45-
globalx,y,triangles,mask
4645
# mask cannot be passed positionally
46+
mask= [True]
47+
args= [[0,2,1], [0,0,1], [[0,1,2]],mask]
4748
x_,y_,triangles_,mask_,args_,kwargs_= \
48-
mtri.Triangulation._extract_triangulation_params(x,y,triangles,mask)
49+
mtri.Triangulation._extract_triangulation_params(args, {})
4950
assertmask_isNone
5051
assertargs_== [mask]
51-
# the positional maskhas tobecatched downstream because this must pass
52+
# the positional maskmustbecaught downstream because this must pass
5253
# unknown args through
5354

5455

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

6075

6176
deftest_delaunay():
@@ -223,6 +238,49 @@ def test_tripcolor():
223238
plt.title('facecolors')
224239

225240

241+
deftest_tripcolor_color():
242+
x= [-1,0,1,0]
243+
y= [0,-1,0,1]
244+
fig,ax=plt.subplots()
245+
withpytest.raises(ValueError,match="Missing color parameter"):
246+
ax.tripcolor(x,y)
247+
withpytest.raises(ValueError,match="The length of C must match either"):
248+
ax.tripcolor(x,y, [1,2,3])
249+
withpytest.raises(ValueError,
250+
match="length of facecolors must match .* triangles"):
251+
ax.tripcolor(x,y,facecolors=[1,2,3,4])
252+
withpytest.raises(ValueError,
253+
match="'gouraud' .* at the points.* not at the faces"):
254+
ax.tripcolor(x,y,facecolors=[1,2],shading='gouraud')
255+
withpytest.raises(ValueError,
256+
match="'gouraud' .* at the points.* not at the faces"):
257+
ax.tripcolor(x,y, [1,2],shading='gouraud')# faces
258+
withpytest.raises(ValueError,
259+
match=r"pass C positionally or facecolors via keyword"):
260+
ax.tripcolor(x,y,C=[1,2,3,4])
261+
262+
# smoke test for valid color specifications (via C or facecolors)
263+
ax.tripcolor(x,y, [1,2,3,4])# edges
264+
ax.tripcolor(x,y, [1,2,3,4],shading='gouraud')# edges
265+
ax.tripcolor(x,y, [1,2])# faces
266+
ax.tripcolor(x,y,facecolors=[1,2])# faces
267+
268+
269+
deftest_tripcolor_warnings():
270+
x= [-1,0,1,0]
271+
y= [0,-1,0,1]
272+
C= [0.4,0.5]
273+
fig,ax=plt.subplots()
274+
# additional parameters
275+
withpytest.warns(UserWarning,match="Additional positional parameters"):
276+
ax.tripcolor(x,y,C,'unused_positional')
277+
# facecolors takes precednced over C
278+
withpytest.warns(UserWarning,match="Positional parameter C .*no effect"):
279+
ax.tripcolor(x,y,C,facecolors=C)
280+
withpytest.warns(UserWarning,match="Positional parameter C .*no effect"):
281+
ax.tripcolor(x,y,'interpreted as C',facecolors=C)
282+
283+
226284
deftest_no_modify():
227285
# Test that Triangulation does not modify triangles array passed to it.
228286
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) int 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: 72 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -21,62 +21,82 @@ 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
29-
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`.
35+
Parameters defining the triangular grid. See `.Triangulation`.
36+
This is mutually exclusive with specifying *triangulation*.
37+
C : array-like
38+
The color values, either for the points or for the triangles. Which one
39+
is automatically inferred from the length of *C*, i.e. does it match
40+
the number of points or the number of triangles. If there are the same
41+
number of points and triangles in the triangulation it is assumed that
42+
color values are defined at points; to force the use of color values at
43+
triangles use the keyword argument ``facecolors=C`` instead of just
44+
``C``.
45+
This parameter is position-only.
46+
facecolors : array-like, optional
47+
Can be used alternatively to *C* to specify colors at the triangle
48+
faces. This parameter takes precedence over *C*.
49+
shading : {'flat', 'gouraud'}, default: 'flat'
50+
If 'flat' and the color values *C* are defined at points, the color
51+
values used for each triangle are from the mean C of the triangle's
52+
three points. If *shading* is 'gouraud' then color values must be
53+
defined at points.
54+
other_parameters
55+
All other parameters are the same as for `~.Axes.pcolor`.
56+
57+
Notes
58+
-----
59+
It is possible to pass the triangles positionally, i.e.
60+
``tripcolor(x, y, triangles, C, ...)``. However, this is discouraged.
61+
For more clarity, pass *triangles* via keyword argument.
5362
"""
5463
_api.check_in_list(['flat','gouraud'],shading=shading)
5564

5665
tri,args,kwargs=Triangulation.get_from_args_and_kwargs(*args,**kwargs)
5766

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.
67+
#Parsethecolor to be in one of (the other variable will be None):
68+
#- facecolors: if specified at the triangle faces
69+
#- point_colors: if specifiedatthe points
6170
iffacecolorsisnotNone:
62-
C=facecolors
71+
ifargs:
72+
_api.warn_external(
73+
"Positional parameter C has no effect when the keyword "
74+
"facecolors is given")
75+
point_colors=None
76+
iflen(facecolors)!=len(tri.triangles):
77+
raiseValueError("The length of facecolors must match the number "
78+
"of triangles")
6379
else:
80+
# Color from positional parameter C
81+
ifnotargs:
82+
raiseValueError(
83+
"Missing color parameter. Please pass C positionally or "
84+
"facecolors via keyword")
85+
eliflen(args)>1:
86+
_api.warn_external(
87+
"Additional positional parameters {args[1:]!r} are ignored")
6488
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')
89+
iflen(C)==len(tri.x):
90+
# having this before the len(tri.triangles) comparison gives
91+
# precedence to nodes if there are as many nodes as triangles
92+
point_colors=C
93+
facecolors=None
94+
eliflen(C)==len(tri.triangles):
95+
point_colors=None
96+
facecolors=C
97+
else:
98+
raiseValueError('The length of C must match either the number '
99+
'of points or the number of triangles')
80100

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

98118
ifshading=='gouraud':
99119
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')
120+
raiseValueError(
121+
"shading='gouraud' can only be used when the colors "
122+
"are specified at the points, not at the faces.")
106123
collection=TriMesh(tri,**kwargs)
124+
colors=point_colors
107125
else:
108126
# Vertices of triangles.
109127
maskedTris=tri.get_masked_triangles()
@@ -112,15 +130,17 @@ def tripcolor(ax, *args, alpha=1.0, norm=None, cmap=None, vmin=None,
112130
# Color values.
113131
iffacecolorsisNone:
114132
# One color per triangle, the mean of the 3 vertex color values.
115-
C=C[maskedTris].mean(axis=1)
133+
colors=point_colors[maskedTris].mean(axis=1)
116134
eliftri.maskisnotNone:
117135
# Remove color values of masked triangles.
118-
C=C[~tri.mask]
136+
colors=facecolors[~tri.mask]
137+
else:
138+
colors=facecolors
119139

120140
collection=PolyCollection(verts,**kwargs)
121141

122142
collection.set_alpha(alpha)
123-
collection.set_array(C)
143+
collection.set_array(colors)
124144
_api.check_isinstance((Normalize,None),norm=norm)
125145
collection.set_cmap(cmap)
126146
collection.set_norm(norm)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp