|
2 | 2 | importitertools
|
3 | 3 | importlogging
|
4 | 4 | importmath
|
| 5 | +importoperator |
5 | 6 | fromnumbersimportNumber
|
6 | 7 | importwarnings
|
7 | 8 |
|
@@ -3760,6 +3761,146 @@ def dopatch(xs, ys, **kwargs):
|
3760 | 3761 | returndict(whiskers=whiskers,caps=caps,boxes=boxes,
|
3761 | 3762 | medians=medians,fliers=fliers,means=means)
|
3762 | 3763 |
|
| 3764 | +def_parse_scatter_color_args(self,c,edgecolors,kwargs,xshape,yshape): |
| 3765 | +""" |
| 3766 | + Helper function to process color related arguments of `.Axes.scatter`. |
| 3767 | +
|
| 3768 | + Argument precedence for facecolors: |
| 3769 | +
|
| 3770 | + - c (if not None) |
| 3771 | + - kwargs['facecolors'] |
| 3772 | + - kwargs['facecolor'] |
| 3773 | + - kwargs['color'] (==kwcolor) |
| 3774 | + - 'b' if in classic mode else next color from color cycle |
| 3775 | +
|
| 3776 | + Argument precedence for edgecolors: |
| 3777 | +
|
| 3778 | + - edgecolors (is an explicit kw argument in scatter()) |
| 3779 | + - kwargs['edgecolor'] |
| 3780 | + - kwargs['color'] (==kwcolor) |
| 3781 | + - 'face' if not in classic mode else None |
| 3782 | +
|
| 3783 | + Arguments |
| 3784 | + --------- |
| 3785 | + c : color or sequence or sequence of color or None |
| 3786 | + See argument description of `.Axes.scatter`. |
| 3787 | + edgecolors : color or sequence of color or {'face', 'none'} or None |
| 3788 | + See argument description of `.Axes.scatter`. |
| 3789 | + kwargs : dict |
| 3790 | + Additional kwargs. If these keys exist, we pop and process them: |
| 3791 | + 'facecolors', 'facecolor', 'edgecolor', 'color' |
| 3792 | + Note: The dict is modified by this function. |
| 3793 | + xshape, yshape : tuple of int |
| 3794 | + The shape of the x and y arrays passed to `.Axes.scatter`. |
| 3795 | +
|
| 3796 | + Returns |
| 3797 | + ------- |
| 3798 | + c |
| 3799 | + The input *c* if it was not *None*, else some color specification |
| 3800 | + derived from the other inputs or defaults. |
| 3801 | + colors : array(N, 4) or None |
| 3802 | + The facecolors as RGBA values or *None* if a colormap is used. |
| 3803 | + edgecolors |
| 3804 | + The edgecolor specification. |
| 3805 | +
|
| 3806 | + """ |
| 3807 | +xsize=functools.reduce(operator.mul,xshape,1) |
| 3808 | +ysize=functools.reduce(operator.mul,yshape,1) |
| 3809 | + |
| 3810 | +facecolors=kwargs.pop('facecolors',None) |
| 3811 | +facecolors=kwargs.pop('facecolor',facecolors) |
| 3812 | +edgecolors=kwargs.pop('edgecolor',edgecolors) |
| 3813 | + |
| 3814 | +kwcolor=kwargs.pop('color',None) |
| 3815 | + |
| 3816 | +ifkwcolorisnotNoneandcisnotNone: |
| 3817 | +raiseValueError("Supply a 'c' argument or a 'color'" |
| 3818 | +" kwarg but not both; they differ but" |
| 3819 | +" their functionalities overlap.") |
| 3820 | + |
| 3821 | +ifkwcolorisnotNone: |
| 3822 | +try: |
| 3823 | +mcolors.to_rgba_array(kwcolor) |
| 3824 | +exceptValueError: |
| 3825 | +raiseValueError("'color' kwarg must be an mpl color" |
| 3826 | +" spec or sequence of color specs.\n" |
| 3827 | +"For a sequence of values to be color-mapped," |
| 3828 | +" use the 'c' argument instead.") |
| 3829 | +ifedgecolorsisNone: |
| 3830 | +edgecolors=kwcolor |
| 3831 | +iffacecolorsisNone: |
| 3832 | +facecolors=kwcolor |
| 3833 | + |
| 3834 | +ifedgecolorsisNoneandnotrcParams['_internal.classic_mode']: |
| 3835 | +edgecolors='face' |
| 3836 | + |
| 3837 | +c_is_none=cisNone |
| 3838 | +ifcisNone: |
| 3839 | +iffacecolorsisnotNone: |
| 3840 | +c=facecolors |
| 3841 | +else: |
| 3842 | +c= ('b'ifrcParams['_internal.classic_mode']else |
| 3843 | +self._get_patches_for_fill.get_next_color()) |
| 3844 | + |
| 3845 | +# After this block, c_array will be None unless |
| 3846 | +# c is an array for mapping. The potential ambiguity |
| 3847 | +# with a sequence of 3 or 4 numbers is resolved in |
| 3848 | +# favor of mapping, not rgb or rgba. |
| 3849 | +# Convenience vars to track shape mismatch *and* conversion failures. |
| 3850 | +valid_shape=True# will be put to the test! |
| 3851 | +n_elem=-1# used only for (some) exceptions |
| 3852 | +ifc_is_noneorkwcolorisnotNone: |
| 3853 | +c_array=None |
| 3854 | +else: |
| 3855 | +try:# First, does 'c' look suitable for value-mapping? |
| 3856 | +c_array=np.asanyarray(c,dtype=float) |
| 3857 | +n_elem=c_array.shape[0] |
| 3858 | +ifc_array.shapein [xshape,yshape]: |
| 3859 | +c=np.ma.ravel(c_array) |
| 3860 | +else: |
| 3861 | +ifc_array.shapein ((3,), (4,)): |
| 3862 | +_log.warning( |
| 3863 | +"'c' argument looks like a single numeric RGB or " |
| 3864 | +"RGBA sequence, which should be avoided as value-" |
| 3865 | +"mapping will have precedence in case its length " |
| 3866 | +"matches with 'x' & 'y'. Please use a 2-D array " |
| 3867 | +"with a single row if you really want to specify " |
| 3868 | +"the same RGB or RGBA value for all points.") |
| 3869 | +# Wrong size; it must not be intended for mapping. |
| 3870 | +valid_shape=False |
| 3871 | +c_array=None |
| 3872 | +exceptValueError: |
| 3873 | +# Failed to make a floating-point array; c must be color specs. |
| 3874 | +c_array=None |
| 3875 | +ifc_arrayisNone: |
| 3876 | +try:# Then is 'c' acceptable as PathCollection facecolors? |
| 3877 | +colors=mcolors.to_rgba_array(c) |
| 3878 | +n_elem=colors.shape[0] |
| 3879 | +ifcolors.shape[0]notin (0,1,xsize,ysize): |
| 3880 | +# NB: remember that a single color is also acceptable. |
| 3881 | +# Besides *colors* will be an empty array if c == 'none'. |
| 3882 | +valid_shape=False |
| 3883 | +raiseValueError |
| 3884 | +exceptValueError: |
| 3885 | +ifnotvalid_shape:# but at least one conversion succeeded. |
| 3886 | +raiseValueError( |
| 3887 | +"'c' argument has {nc} elements, which is not " |
| 3888 | +"acceptable for use with 'x' with size {xs}, " |
| 3889 | +"'y' with size {ys}." |
| 3890 | + .format(nc=n_elem,xs=xsize,ys=ysize) |
| 3891 | + ) |
| 3892 | +# Both the mapping *and* the RGBA conversion failed: pretty |
| 3893 | +# severe failure => one may appreciate a verbose feedback. |
| 3894 | +raiseValueError( |
| 3895 | +"'c' argument must either be valid as mpl color(s) " |
| 3896 | +"or as numbers to be mapped to colors. " |
| 3897 | +"Here c = {}."# <- beware, could be long depending on c. |
| 3898 | + .format(c) |
| 3899 | + ) |
| 3900 | +else: |
| 3901 | +colors=None# use cmap, norm after collection is created |
| 3902 | +returnc,colors,edgecolors |
| 3903 | + |
3763 | 3904 | @_preprocess_data(replace_names=["x","y","s","linewidths",
|
3764 | 3905 | "edgecolors","c","facecolor",
|
3765 | 3906 | "facecolors","color"],
|
@@ -3865,124 +4006,27 @@ def scatter(self, x, y, s=None, c=None, marker=None, cmap=None, norm=None,
|
3865 | 4006 |
|
3866 | 4007 | """
|
3867 | 4008 | # Process **kwargs to handle aliases, conflicts with explicit kwargs:
|
3868 |
| -facecolors=None |
3869 |
| -edgecolors=kwargs.pop('edgecolor',edgecolors) |
3870 |
| -fc=kwargs.pop('facecolors',None) |
3871 |
| -fc=kwargs.pop('facecolor',fc) |
3872 |
| -iffcisnotNone: |
3873 |
| -facecolors=fc |
3874 |
| -co=kwargs.pop('color',None) |
3875 |
| -ifcoisnotNone: |
3876 |
| -try: |
3877 |
| -mcolors.to_rgba_array(co) |
3878 |
| -exceptValueError: |
3879 |
| -raiseValueError("'color' kwarg must be an mpl color" |
3880 |
| -" spec or sequence of color specs.\n" |
3881 |
| -"For a sequence of values to be color-mapped," |
3882 |
| -" use the 'c' argument instead.") |
3883 |
| -ifedgecolorsisNone: |
3884 |
| -edgecolors=co |
3885 |
| -iffacecolorsisNone: |
3886 |
| -facecolors=co |
3887 |
| -ifcisnotNone: |
3888 |
| -raiseValueError("Supply a 'c' argument or a 'color'" |
3889 |
| -" kwarg but not both; they differ but" |
3890 |
| -" their functionalities overlap.") |
3891 |
| -ifcisNone: |
3892 |
| -iffacecolorsisnotNone: |
3893 |
| -c=facecolors |
3894 |
| -else: |
3895 |
| -ifrcParams['_internal.classic_mode']: |
3896 |
| -c='b'# The original default |
3897 |
| -else: |
3898 |
| -c=self._get_patches_for_fill.get_next_color() |
3899 |
| -c_none=True |
3900 |
| -else: |
3901 |
| -c_none=False |
3902 |
| - |
3903 |
| -ifedgecolorsisNoneandnotrcParams['_internal.classic_mode']: |
3904 |
| -edgecolors='face' |
3905 | 4009 |
|
3906 | 4010 | self._process_unit_info(xdata=x,ydata=y,kwargs=kwargs)
|
3907 | 4011 | x=self.convert_xunits(x)
|
3908 | 4012 | y=self.convert_yunits(y)
|
3909 | 4013 |
|
3910 | 4014 | # np.ma.ravel yields an ndarray, not a masked array,
|
3911 | 4015 | # unless its argument is a masked array.
|
3912 |
| -xy_shape= (np.shape(x),np.shape(y)) |
| 4016 | +xshape,yshape=np.shape(x),np.shape(y) |
3913 | 4017 | x=np.ma.ravel(x)
|
3914 | 4018 | y=np.ma.ravel(y)
|
3915 | 4019 | ifx.size!=y.size:
|
3916 | 4020 | raiseValueError("x and y must be the same size")
|
3917 | 4021 |
|
3918 | 4022 | ifsisNone:
|
3919 |
| -ifrcParams['_internal.classic_mode']: |
3920 |
| -s=20 |
3921 |
| -else: |
3922 |
| -s=rcParams['lines.markersize']**2.0 |
3923 |
| - |
| 4023 | +s= (20ifrcParams['_internal.classic_mode']else |
| 4024 | +rcParams['lines.markersize']**2.0) |
3924 | 4025 | s=np.ma.ravel(s)# This doesn't have to match x, y in size.
|
3925 | 4026 |
|
3926 |
| -# After this block, c_array will be None unless |
3927 |
| -# c is an array for mapping. The potential ambiguity |
3928 |
| -# with a sequence of 3 or 4 numbers is resolved in |
3929 |
| -# favor of mapping, not rgb or rgba. |
3930 |
| - |
3931 |
| -# Convenience vars to track shape mismatch *and* conversion failures. |
3932 |
| -valid_shape=True# will be put to the test! |
3933 |
| -n_elem=-1# used only for (some) exceptions |
3934 |
| - |
3935 |
| -ifc_noneorcoisnotNone: |
3936 |
| -c_array=None |
3937 |
| -else: |
3938 |
| -try:# First, does 'c' look suitable for value-mapping? |
3939 |
| -c_array=np.asanyarray(c,dtype=float) |
3940 |
| -n_elem=c_array.shape[0] |
3941 |
| -ifc_array.shapeinxy_shape: |
3942 |
| -c=np.ma.ravel(c_array) |
3943 |
| -else: |
3944 |
| -ifc_array.shapein ((3,), (4,)): |
3945 |
| -_log.warning( |
3946 |
| -"'c' argument looks like a single numeric RGB or " |
3947 |
| -"RGBA sequence, which should be avoided as value-" |
3948 |
| -"mapping will have precedence in case its length " |
3949 |
| -"matches with 'x' & 'y'. Please use a 2-D array " |
3950 |
| -"with a single row if you really want to specify " |
3951 |
| -"the same RGB or RGBA value for all points.") |
3952 |
| -# Wrong size; it must not be intended for mapping. |
3953 |
| -valid_shape=False |
3954 |
| -c_array=None |
3955 |
| -exceptValueError: |
3956 |
| -# Failed to make a floating-point array; c must be color specs. |
3957 |
| -c_array=None |
3958 |
| - |
3959 |
| -ifc_arrayisNone: |
3960 |
| -try:# Then is 'c' acceptable as PathCollection facecolors? |
3961 |
| -colors=mcolors.to_rgba_array(c) |
3962 |
| -n_elem=colors.shape[0] |
3963 |
| -ifcolors.shape[0]notin (0,1,x.size,y.size): |
3964 |
| -# NB: remember that a single color is also acceptable. |
3965 |
| -# Besides *colors* will be an empty array if c == 'none'. |
3966 |
| -valid_shape=False |
3967 |
| -raiseValueError |
3968 |
| -exceptValueError: |
3969 |
| -ifnotvalid_shape:# but at least one conversion succeeded. |
3970 |
| -raiseValueError( |
3971 |
| -"'c' argument has {nc} elements, which is not " |
3972 |
| -"acceptable for use with 'x' with size {xs}, " |
3973 |
| -"'y' with size {ys}." |
3974 |
| - .format(nc=n_elem,xs=x.size,ys=y.size) |
3975 |
| - ) |
3976 |
| -# Both the mapping *and* the RGBA conversion failed: pretty |
3977 |
| -# severe failure => one may appreciate a verbose feedback. |
3978 |
| -raiseValueError( |
3979 |
| -"'c' argument must either be valid as mpl color(s) " |
3980 |
| -"or as numbers to be mapped to colors. " |
3981 |
| -"Here c = {}."# <- beware, could be long depending on c. |
3982 |
| - .format(c) |
3983 |
| - ) |
3984 |
| -else: |
3985 |
| -colors=None# use cmap, norm after collection is created |
| 4027 | +c,colors,edgecolors= \ |
| 4028 | +self._parse_scatter_color_args(c,edgecolors,kwargs, |
| 4029 | +xshape,yshape) |
3986 | 4030 |
|
3987 | 4031 | # `delete_masked_points` only modifies arguments of the same length as
|
3988 | 4032 | # `x`.
|
|