Coverage for /usr/lib/python3/dist-packages/matplotlib/tri/tripcolor.py: 10%

62 statements  

« prev     ^ index     » next       coverage.py v7.4.4, created at 2025-06-14 15:25 +0200

1import numpy as np 

2 

3from matplotlib import _api 

4from matplotlib.collections import PolyCollection, TriMesh 

5from matplotlib.colors import Normalize 

6from matplotlib.tri.triangulation import Triangulation 

7 

8 

9def tripcolor(ax, *args, alpha=1.0, norm=None, cmap=None, vmin=None, 

10 vmax=None, shading='flat', facecolors=None, **kwargs): 

11 """ 

12 Create a pseudocolor plot of an unstructured triangular grid. 

13 

14 Call signatures:: 

15 

16 tripcolor(triangulation, c, *, ...) 

17 tripcolor(x, y, c, *, [triangles=triangles], [mask=mask], ...) 

18 

19 The triangular grid can be specified either by passing a `.Triangulation` 

20 object as the first parameter, or by passing the points *x*, *y* and 

21 optionally the *triangles* and a *mask*. See `.Triangulation` for an 

22 explanation of these parameters. 

23 

24 It is possible to pass the triangles positionally, i.e. 

25 ``tripcolor(x, y, triangles, c, ...)``. However, this is discouraged. 

26 For more clarity, pass *triangles* via keyword argument. 

27 

28 If neither of *triangulation* or *triangles* are given, the triangulation 

29 is calculated on the fly. In this case, it does not make sense to provide 

30 colors at the triangle faces via *c* or *facecolors* because there are 

31 multiple possible triangulations for a group of points and you don't know 

32 which triangles will be constructed. 

33 

34 Parameters 

35 ---------- 

36 triangulation : `.Triangulation` 

37 An already created triangular grid. 

38 x, y, triangles, mask 

39 Parameters defining the triangular grid. See `.Triangulation`. 

40 This is mutually exclusive with specifying *triangulation*. 

41 c : array-like 

42 The color values, either for the points or for the triangles. Which one 

43 is automatically inferred from the length of *c*, i.e. does it match 

44 the number of points or the number of triangles. If there are the same 

45 number of points and triangles in the triangulation it is assumed that 

46 color values are defined at points; to force the use of color values at 

47 triangles use the keyword argument ``facecolors=c`` instead of just 

48 ``c``. 

49 This parameter is position-only. 

50 facecolors : array-like, optional 

51 Can be used alternatively to *c* to specify colors at the triangle 

52 faces. This parameter takes precedence over *c*. 

53 shading : {'flat', 'gouraud'}, default: 'flat' 

54 If 'flat' and the color values *c* are defined at points, the color 

55 values used for each triangle are from the mean c of the triangle's 

56 three points. If *shading* is 'gouraud' then color values must be 

57 defined at points. 

58 other_parameters 

59 All other parameters are the same as for `~.Axes.pcolor`. 

60 """ 

61 _api.check_in_list(['flat', 'gouraud'], shading=shading) 

62 

63 tri, args, kwargs = Triangulation.get_from_args_and_kwargs(*args, **kwargs) 

64 

65 # Parse the color to be in one of (the other variable will be None): 

66 # - facecolors: if specified at the triangle faces 

67 # - point_colors: if specified at the points 

68 if facecolors is not None: 

69 if args: 

70 _api.warn_external( 

71 "Positional parameter c has no effect when the keyword " 

72 "facecolors is given") 

73 point_colors = None 

74 if len(facecolors) != len(tri.triangles): 

75 raise ValueError("The length of facecolors must match the number " 

76 "of triangles") 

77 else: 

78 # Color from positional parameter c 

79 if not args: 

80 raise TypeError( 

81 "tripcolor() missing 1 required positional argument: 'c'; or " 

82 "1 required keyword-only argument: 'facecolors'") 

83 elif len(args) > 1: 

84 _api.warn_deprecated( 

85 "3.6", message=f"Additional positional parameters " 

86 f"{args[1:]!r} are ignored; support for them is deprecated " 

87 f"since %(since)s and will be removed %(removal)s") 

88 c = np.asarray(args[0]) 

89 if len(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 elif len(c) == len(tri.triangles): 

95 point_colors = None 

96 facecolors = c 

97 else: 

98 raise ValueError('The length of c must match either the number ' 

99 'of points or the number of triangles') 

100 

101 # Handling of linewidths, shading, edgecolors and antialiased as 

102 # in Axes.pcolor 

103 linewidths = (0.25,) 

104 if 'linewidth' in kwargs: 

105 kwargs['linewidths'] = kwargs.pop('linewidth') 

106 kwargs.setdefault('linewidths', linewidths) 

107 

108 edgecolors = 'none' 

109 if 'edgecolor' in kwargs: 

110 kwargs['edgecolors'] = kwargs.pop('edgecolor') 

111 ec = kwargs.setdefault('edgecolors', edgecolors) 

112 

113 if 'antialiased' in kwargs: 

114 kwargs['antialiaseds'] = kwargs.pop('antialiased') 

115 if 'antialiaseds' not in kwargs and ec.lower() == "none": 

116 kwargs['antialiaseds'] = False 

117 

118 _api.check_isinstance((Normalize, None), norm=norm) 

119 if shading == 'gouraud': 

120 if facecolors is not None: 

121 raise ValueError( 

122 "shading='gouraud' can only be used when the colors " 

123 "are specified at the points, not at the faces.") 

124 collection = TriMesh(tri, alpha=alpha, array=point_colors, 

125 cmap=cmap, norm=norm, **kwargs) 

126 else: # 'flat' 

127 # Vertices of triangles. 

128 maskedTris = tri.get_masked_triangles() 

129 verts = np.stack((tri.x[maskedTris], tri.y[maskedTris]), axis=-1) 

130 

131 # Color values. 

132 if facecolors is None: 

133 # One color per triangle, the mean of the 3 vertex color values. 

134 colors = point_colors[maskedTris].mean(axis=1) 

135 elif tri.mask is not None: 

136 # Remove color values of masked triangles. 

137 colors = facecolors[~tri.mask] 

138 else: 

139 colors = facecolors 

140 collection = PolyCollection(verts, alpha=alpha, array=colors, 

141 cmap=cmap, norm=norm, **kwargs) 

142 

143 collection._scale_norm(norm, vmin, vmax) 

144 ax.grid(False) 

145 

146 minx = tri.x.min() 

147 maxx = tri.x.max() 

148 miny = tri.y.min() 

149 maxy = tri.y.max() 

150 corners = (minx, miny), (maxx, maxy) 

151 ax.update_datalim(corners) 

152 ax.autoscale_view() 

153 ax.add_collection(collection) 

154 return collection