|
3 | 3 | importitertools
|
4 | 4 | importlogging
|
5 | 5 | importmath
|
| 6 | +importoperator |
6 | 7 | fromnumbersimportNumber
|
7 | 8 | importwarnings
|
8 | 9 |
|
@@ -4012,6 +4013,150 @@ def dopatch(xs, ys, **kwargs):
|
4012 | 4013 | returndict(whiskers=whiskers,caps=caps,boxes=boxes,
|
4013 | 4014 | medians=medians,fliers=fliers,means=means)
|
4014 | 4015 |
|
| 4016 | +def_parse_scatter_color_args(self,c,edgecolors,kwargs,xshape,yshape): |
| 4017 | +""" |
| 4018 | + Helper function to process color related arguments of `.Axes.scatter`. |
| 4019 | +
|
| 4020 | + Argument precedence for facecolors: |
| 4021 | +
|
| 4022 | + - c (if not None) |
| 4023 | + - kwargs['facecolors'] |
| 4024 | + - kwargs['facecolor'] |
| 4025 | + - kwargs['color'] (==kwcolor) |
| 4026 | + - 'b' if in classic mode else next color from color cycle |
| 4027 | +
|
| 4028 | + Argument precedence for edgecolors: |
| 4029 | +
|
| 4030 | + - edgecolors (is an explicit kw argument in scatter()) |
| 4031 | + - kwargs['edgecolor'] |
| 4032 | + - kwargs['color'] (==kwcolor) |
| 4033 | + - 'face' if not in classic mode else None |
| 4034 | +
|
| 4035 | + Arguments |
| 4036 | + --------- |
| 4037 | + c : color or sequence or sequence of color or None |
| 4038 | + See argument description of `.Axes.scatter`. |
| 4039 | + edgecolors : color or sequence of color or {'face', 'none'} or None |
| 4040 | + See argument description of `.Axes.scatter`. |
| 4041 | + kwargs : dict |
| 4042 | + Additional kwargs. If these keys exist, we pop and process them: |
| 4043 | + 'facecolors', 'facecolor', 'edgecolor', 'color' |
| 4044 | + Note: The dict is modified by this function. |
| 4045 | + xshape, yshape : tuple of int |
| 4046 | + The shape of the x and y arrays passed to `.Axes.scatter`. |
| 4047 | +
|
| 4048 | + Returns |
| 4049 | + ------- |
| 4050 | + c |
| 4051 | + The input *c* if it was not *None*, else some color specification |
| 4052 | + derived from the other inputs or defaults. |
| 4053 | + colors : array(N, 4) or None |
| 4054 | + The facecolors as RGBA values or *None* if a colormap is used. |
| 4055 | + edgecolors |
| 4056 | + The edgecolor specification. |
| 4057 | +
|
| 4058 | + """ |
| 4059 | +xsize=functools.reduce(operator.mul,xshape,1) |
| 4060 | +ysize=functools.reduce(operator.mul,yshape,1) |
| 4061 | + |
| 4062 | +facecolors=kwargs.pop('facecolors',None) |
| 4063 | +facecolors=kwargs.pop('facecolor',facecolors) |
| 4064 | +edgecolors=kwargs.pop('edgecolor',edgecolors) |
| 4065 | + |
| 4066 | +kwcolor=kwargs.pop('color',None) |
| 4067 | + |
| 4068 | +ifkwcolorisnotNoneandcisnotNone: |
| 4069 | +raiseValueError("Supply a 'c' argument or a 'color'" |
| 4070 | +" kwarg but not both; they differ but" |
| 4071 | +" their functionalities overlap.") |
| 4072 | + |
| 4073 | +ifkwcolorisnotNone: |
| 4074 | +try: |
| 4075 | +mcolors.to_rgba_array(kwcolor) |
| 4076 | +exceptValueError: |
| 4077 | +raiseValueError("'color' kwarg must be an mpl color" |
| 4078 | +" spec or sequence of color specs.\n" |
| 4079 | +"For a sequence of values to be color-mapped," |
| 4080 | +" use the 'c' argument instead.") |
| 4081 | +ifedgecolorsisNone: |
| 4082 | +edgecolors=kwcolor |
| 4083 | +iffacecolorsisNone: |
| 4084 | +facecolors=kwcolor |
| 4085 | + |
| 4086 | +ifedgecolorsisNoneandnotrcParams['_internal.classic_mode']: |
| 4087 | +edgecolors='face' |
| 4088 | + |
| 4089 | +c_was_none=cisNone |
| 4090 | +ifcisNone: |
| 4091 | +c= (facecolorsiffacecolorsisnotNone |
| 4092 | +else"b"ifrcParams['_internal.classic_mode'] |
| 4093 | +elseself._get_patches_for_fill.get_next_color()) |
| 4094 | + |
| 4095 | +# After this block, c_array will be None unless |
| 4096 | +# c is an array for mapping. The potential ambiguity |
| 4097 | +# with a sequence of 3 or 4 numbers is resolved in |
| 4098 | +# favor of mapping, not rgb or rgba. |
| 4099 | +# Convenience vars to track shape mismatch *and* conversion failures. |
| 4100 | +valid_shape=True# will be put to the test! |
| 4101 | +n_elem=-1# used only for (some) exceptions |
| 4102 | + |
| 4103 | +if (c_was_noneor |
| 4104 | +kwcolorisnotNoneor |
| 4105 | +isinstance(c,str)or |
| 4106 | + (isinstance(c,collections.abc.Iterable)and |
| 4107 | +len(c)>0and |
| 4108 | +isinstance(cbook.safe_first_element(c),str))): |
| 4109 | +c_array=None |
| 4110 | +else: |
| 4111 | +try:# First, does 'c' look suitable for value-mapping? |
| 4112 | +c_array=np.asanyarray(c,dtype=float) |
| 4113 | +n_elem=c_array.shape[0] |
| 4114 | +ifc_array.shapein [xshape,yshape]: |
| 4115 | +c=np.ma.ravel(c_array) |
| 4116 | +else: |
| 4117 | +ifc_array.shapein ((3,), (4,)): |
| 4118 | +_log.warning( |
| 4119 | +"'c' argument looks like a single numeric RGB or " |
| 4120 | +"RGBA sequence, which should be avoided as value-" |
| 4121 | +"mapping will have precedence in case its length " |
| 4122 | +"matches with 'x' & 'y'. Please use a 2-D array " |
| 4123 | +"with a single row if you really want to specify " |
| 4124 | +"the same RGB or RGBA value for all points.") |
| 4125 | +# Wrong size; it must not be intended for mapping. |
| 4126 | +valid_shape=False |
| 4127 | +c_array=None |
| 4128 | +exceptValueError: |
| 4129 | +# Failed to make a floating-point array; c must be color specs. |
| 4130 | +c_array=None |
| 4131 | +ifc_arrayisNone: |
| 4132 | +try:# Then is 'c' acceptable as PathCollection facecolors? |
| 4133 | +colors=mcolors.to_rgba_array(c) |
| 4134 | +n_elem=colors.shape[0] |
| 4135 | +ifcolors.shape[0]notin (0,1,xsize,ysize): |
| 4136 | +# NB: remember that a single color is also acceptable. |
| 4137 | +# Besides *colors* will be an empty array if c == 'none'. |
| 4138 | +valid_shape=False |
| 4139 | +raiseValueError |
| 4140 | +exceptValueError: |
| 4141 | +ifnotvalid_shape:# but at least one conversion succeeded. |
| 4142 | +raiseValueError( |
| 4143 | +"'c' argument has {nc} elements, which is not " |
| 4144 | +"acceptable for use with 'x' with size {xs}, " |
| 4145 | +"'y' with size {ys}." |
| 4146 | + .format(nc=n_elem,xs=xsize,ys=ysize) |
| 4147 | + ) |
| 4148 | +# Both the mapping *and* the RGBA conversion failed: pretty |
| 4149 | +# severe failure => one may appreciate a verbose feedback. |
| 4150 | +raiseValueError( |
| 4151 | +"'c' argument must either be valid as mpl color(s) " |
| 4152 | +"or as numbers to be mapped to colors. " |
| 4153 | +"Here c = {}."# <- beware, could be long depending on c. |
| 4154 | + .format(c) |
| 4155 | + ) |
| 4156 | +else: |
| 4157 | +colors=None# use cmap, norm after collection is created |
| 4158 | +returnc,colors,edgecolors |
| 4159 | + |
4015 | 4160 | @_preprocess_data(replace_names=["x","y","s","linewidths",
|
4016 | 4161 | "edgecolors","c","facecolor",
|
4017 | 4162 | "facecolors","color"],
|
@@ -4125,129 +4270,27 @@ def scatter(self, x, y, s=None, c=None, marker=None, cmap=None, norm=None,
|
4125 | 4270 |
|
4126 | 4271 | """
|
4127 | 4272 | # Process **kwargs to handle aliases, conflicts with explicit kwargs:
|
4128 |
| -facecolors=None |
4129 |
| -edgecolors=kwargs.pop('edgecolor',edgecolors) |
4130 |
| -fc=kwargs.pop('facecolors',None) |
4131 |
| -fc=kwargs.pop('facecolor',fc) |
4132 |
| -iffcisnotNone: |
4133 |
| -facecolors=fc |
4134 |
| -co=kwargs.pop('color',None) |
4135 |
| -ifcoisnotNone: |
4136 |
| -try: |
4137 |
| -mcolors.to_rgba_array(co) |
4138 |
| -exceptValueError: |
4139 |
| -raiseValueError("'color' kwarg must be an mpl color" |
4140 |
| -" spec or sequence of color specs.\n" |
4141 |
| -"For a sequence of values to be color-mapped," |
4142 |
| -" use the 'c' argument instead.") |
4143 |
| -ifedgecolorsisNone: |
4144 |
| -edgecolors=co |
4145 |
| -iffacecolorsisNone: |
4146 |
| -facecolors=co |
4147 |
| -ifcisnotNone: |
4148 |
| -raiseValueError("Supply a 'c' argument or a 'color'" |
4149 |
| -" kwarg but not both; they differ but" |
4150 |
| -" their functionalities overlap.") |
4151 |
| -ifcisNone: |
4152 |
| -iffacecolorsisnotNone: |
4153 |
| -c=facecolors |
4154 |
| -else: |
4155 |
| -ifrcParams['_internal.classic_mode']: |
4156 |
| -c='b'# The original default |
4157 |
| -else: |
4158 |
| -c=self._get_patches_for_fill.get_next_color() |
4159 |
| -c_none=True |
4160 |
| -else: |
4161 |
| -c_none=False |
4162 |
| - |
4163 |
| -ifedgecolorsisNoneandnotrcParams['_internal.classic_mode']: |
4164 |
| -edgecolors='face' |
4165 | 4273 |
|
4166 | 4274 | self._process_unit_info(xdata=x,ydata=y,kwargs=kwargs)
|
4167 | 4275 | x=self.convert_xunits(x)
|
4168 | 4276 | y=self.convert_yunits(y)
|
4169 | 4277 |
|
4170 | 4278 | # np.ma.ravel yields an ndarray, not a masked array,
|
4171 | 4279 | # unless its argument is a masked array.
|
4172 |
| -xy_shape= (np.shape(x),np.shape(y)) |
| 4280 | +xshape,yshape=np.shape(x),np.shape(y) |
4173 | 4281 | x=np.ma.ravel(x)
|
4174 | 4282 | y=np.ma.ravel(y)
|
4175 | 4283 | ifx.size!=y.size:
|
4176 | 4284 | raiseValueError("x and y must be the same size")
|
4177 | 4285 |
|
4178 | 4286 | ifsisNone:
|
4179 |
| -ifrcParams['_internal.classic_mode']: |
4180 |
| -s=20 |
4181 |
| -else: |
4182 |
| -s=rcParams['lines.markersize']**2.0 |
4183 |
| - |
| 4287 | +s= (20ifrcParams['_internal.classic_mode']else |
| 4288 | +rcParams['lines.markersize']**2.0) |
4184 | 4289 | s=np.ma.ravel(s)# This doesn't have to match x, y in size.
|
4185 | 4290 |
|
4186 |
| -# After this block, c_array will be None unless |
4187 |
| -# c is an array for mapping. The potential ambiguity |
4188 |
| -# with a sequence of 3 or 4 numbers is resolved in |
4189 |
| -# favor of mapping, not rgb or rgba. |
4190 |
| - |
4191 |
| -# Convenience vars to track shape mismatch *and* conversion failures. |
4192 |
| -valid_shape=True# will be put to the test! |
4193 |
| -n_elem=-1# used only for (some) exceptions |
4194 |
| - |
4195 |
| -if (c_noneor |
4196 |
| -coisnotNoneor |
4197 |
| -isinstance(c,str)or |
4198 |
| - (isinstance(c,collections.Iterable)and |
4199 |
| -len(c)>0and |
4200 |
| -isinstance(cbook.safe_first_element(c),str))): |
4201 |
| -c_array=None |
4202 |
| -else: |
4203 |
| -try:# First, does 'c' look suitable for value-mapping? |
4204 |
| -c_array=np.asanyarray(c,dtype=float) |
4205 |
| -n_elem=c_array.shape[0] |
4206 |
| -ifc_array.shapeinxy_shape: |
4207 |
| -c=np.ma.ravel(c_array) |
4208 |
| -else: |
4209 |
| -ifc_array.shapein ((3,), (4,)): |
4210 |
| -_log.warning( |
4211 |
| -"'c' argument looks like a single numeric RGB or " |
4212 |
| -"RGBA sequence, which should be avoided as value-" |
4213 |
| -"mapping will have precedence in case its length " |
4214 |
| -"matches with 'x' & 'y'. Please use a 2-D array " |
4215 |
| -"with a single row if you really want to specify " |
4216 |
| -"the same RGB or RGBA value for all points.") |
4217 |
| -# Wrong size; it must not be intended for mapping. |
4218 |
| -valid_shape=False |
4219 |
| -c_array=None |
4220 |
| -exceptValueError: |
4221 |
| -# Failed to make a floating-point array; c must be color specs. |
4222 |
| -c_array=None |
4223 |
| - |
4224 |
| -ifc_arrayisNone: |
4225 |
| -try:# Then is 'c' acceptable as PathCollection facecolors? |
4226 |
| -colors=mcolors.to_rgba_array(c) |
4227 |
| -n_elem=colors.shape[0] |
4228 |
| -ifcolors.shape[0]notin (0,1,x.size,y.size): |
4229 |
| -# NB: remember that a single color is also acceptable. |
4230 |
| -# Besides *colors* will be an empty array if c == 'none'. |
4231 |
| -valid_shape=False |
4232 |
| -raiseValueError |
4233 |
| -exceptValueError: |
4234 |
| -ifnotvalid_shape:# but at least one conversion succeeded. |
4235 |
| -raiseValueError( |
4236 |
| -"'c' argument has {nc} elements, which is not " |
4237 |
| -"acceptable for use with 'x' with size {xs}, " |
4238 |
| -"'y' with size {ys}." |
4239 |
| - .format(nc=n_elem,xs=x.size,ys=y.size) |
4240 |
| - ) |
4241 |
| -# Both the mapping *and* the RGBA conversion failed: pretty |
4242 |
| -# severe failure => one may appreciate a verbose feedback. |
4243 |
| -raiseValueError( |
4244 |
| -"'c' argument must either be valid as mpl color(s) " |
4245 |
| -"or as numbers to be mapped to colors. " |
4246 |
| -"Here c = {}."# <- beware, could be long depending on c. |
4247 |
| - .format(c) |
4248 |
| - ) |
4249 |
| -else: |
4250 |
| -colors=None# use cmap, norm after collection is created |
| 4291 | +c,colors,edgecolors= \ |
| 4292 | +self._parse_scatter_color_args(c,edgecolors,kwargs, |
| 4293 | +xshape,yshape) |
4251 | 4294 |
|
4252 | 4295 | # `delete_masked_points` only modifies arguments of the same length as
|
4253 | 4296 | # `x`.
|
|