@@ -2355,12 +2355,10 @@ def __init__(self, levels, norm=None, unique=None, step=None, clip=False):
23552355            of the normalizer are set to the minimum and maximum values in `levels`. 
23562356        unique : {'neither', 'both', 'min', 'max'}, optional 
23572357            Which out-of-bounds regions should be assigned unique colormap colors. 
2358-             Possible values are equivalent to the `extend` values. The normalizer 
2359-             needs this information so it can ensure the colorbar always spans the 
2360-             full range of colormap colors. Internally, proplot sets this automatically 
2361-             depending on whether the colormap is cyclic and whether "extreme" colors 
2362-             were designated separately using `~matplotlib.colors.Colormap.set_under` 
2363-             and/or `~matplotlib.colors.Colormap.set_over`. 
2358+             Possible values are equivalent to the `extend` values. Internally, proplot 
2359+             sets this depending on the user-input `extend`, whether the colormap is 
2360+             cyclic, and whether `~matplotlib.colors.Colormap.set_under` 
2361+             or `~matplotlib.colors.Colormap.set_over` were called for the colormap. 
23642362        step : float, optional 
23652363            The intensity of the transition to out-of-bounds colors as a fraction 
23662364            of the adjacent step between in-bounds colors. Internally, proplot sets 
@@ -2376,16 +2374,15 @@ def __init__(self, levels, norm=None, unique=None, step=None, clip=False):
23762374        ---- 
23772375        This normalizer also makes sure that levels always span the full range 
23782376        of colors in the colormap, whether `extend` is set to ``'min'``, ``'max'``, 
2379-         ``'neither'``, or ``'both'``. By default, when `extend` is not ``'both'``, 
2380-         matplotlib cuts off the most intense colors (reserved for "out of bounds" 
2381-         data), even though they are not being used. Note that this means 
2382-         using a diverging colormap with ``extend='max'`` or ``extend='min'`` 
2383-         will shift the central color by default. But that is very strange 
2384-         usage anyway... so please just don't do that :) 
2377+         ``'neither'``, or ``'both'``. In matplotlib, when `extend` is not ``'both'``, 
2378+         the most intense colors are cut off (reserved for "out of bounds" data), 
2379+         even though they are not being used. 
23852380
23862381        See also 
23872382        -------- 
23882383        proplot.constructor.Norm 
2384+         proplot.colors.SegmentedNorm 
2385+         proplot.ticker.DiscreteLocator 
23892386        """ 
23902387        # Parse input arguments 
23912388        # NOTE: This must be a subclass BoundaryNorm, so ColorbarBase will 
@@ -2435,26 +2432,25 @@ def __init__(self, levels, norm=None, unique=None, step=None, clip=False):
24352432            mids [0 ] +=  step  *  (mids [1 ] -  mids [2 ])
24362433        if  unique  in  ('max' , 'both' ):
24372434            mids [- 1 ] +=  step  *  (mids [- 2 ] -  mids [- 3 ])
2435+         mmin , mmax  =  np .min (mids ), np .max (mids )
24382436        if  vcenter  is  None :
2439-             mids  =  _interpolate_scalar (mids , np . min ( mids ),  np . max ( mids ) , vmin , vmax )
2437+             mids  =  _interpolate_scalar (mids , mmin ,  mmax , vmin , vmax )
24402438        else :
2441-             mids [mids  <  vcenter ] =  _interpolate_scalar (
2442-                 mids [mids  <  vcenter ], np .min (mids ), vcenter , vmin , vcenter 
2443-             )
2444-             mids [mids  >=  vcenter ] =  _interpolate_scalar (
2445-                 mids [mids  >=  vcenter ], vcenter , np .max (mids ), vcenter , vmax 
2446-             )
2439+             mask1 , mask2  =  mids  <  vcenter , mids  >=  vcenter 
2440+             mids [mask1 ] =  _interpolate_scalar (mids [mask1 ], mmin , vcenter , vmin , vcenter )
2441+             mids [mask2 ] =  _interpolate_scalar (mids [mask2 ], vcenter , mmax , vcenter , vmax )
24472442
2448-         # Attributes  
2443+         # Instance attributes  
24492444        # NOTE: If clip is True, we clip values to the centers of the end bins 
24502445        # rather than vmin/vmax to prevent out-of-bounds colors from getting an 
24512446        # in-bounds bin color due to landing on a bin edge. 
24522447        # NOTE: With unique='min' the minimimum in-bounds and out-of-bounds 
24532448        # colors are the same so clip=True will have no effect. Same goes 
24542449        # for unique='max' with maximum colors. 
2450+         eps  =  1e-10 
24552451        dest  =  norm (mids )
2456-         dest [0 ] -=  1e-10   # dest guaranteed to be numpy.float64 
2457-         dest [- 1 ] +=  1e-10 
2452+         dest [0 ] -=  eps   # dest guaranteed to be numpy.float64 
2453+         dest [- 1 ] +=  eps 
24582454        self ._descending  =  descending 
24592455        self ._bmin  =  np .min (mids )
24602456        self ._bmax  =  np .max (mids )
@@ -2470,7 +2466,7 @@ def __init__(self, levels, norm=None, unique=None, step=None, clip=False):
24702466        # up with unpredictable fill value, weird "out-of-bounds" colors 
24712467        self ._norm_clip  =  None 
24722468        if  isinstance (norm , mcolors .LogNorm ):
2473-             self ._norm_clip  =  (5e -249None )
2469+             self ._norm_clip  =  (1e -249None )
24742470
24752471    def  __call__ (self , value , clip = None ):
24762472        """ 
@@ -2504,41 +2500,56 @@ def __call__(self, value, clip=None):
25042500
25052501    def  inverse (self , value ):  # noqa: U100 
25062502        """ 
2507-         Raise an error. Inversion after discretization is impossible. 
2503+         Raise an error. 
2504+ 
2505+         Raises 
2506+         ------ 
2507+         ValueError 
2508+             Inversion after discretization is impossible. 
25082509        """ 
25092510        raise  ValueError ('DiscreteNorm is not invertible.' )
25102511
25112512    @property  
25122513    def  descending (self ):
25132514        """ 
2514-         Whether the normalizer  levels are descending. 
2515+         Boolean indicating whether the  levels are descending. 
25152516        """ 
25162517        return  self ._descending 
25172518
25182519
25192520class  SegmentedNorm (mcolors .Normalize ):
25202521    """ 
2521-     Normalizer that scales data linearly with respect to the interpolated  
2522-     index in an arbitrary monotonically increasing  level sequence. 
2522+     Normalizer that scales data linearly with respect to the 
2523+     interpolated  index in an arbitrary monotonic  level sequence. 
25232524    """ 
25242525    def  __init__ (self , levels , vmin = None , vmax = None , clip = False ):
25252526        """ 
25262527        Parameters 
25272528        ---------- 
25282529        levels : sequence of float 
2529-             The level boundaries. Must be monotonically increasing or decreasing. 
2530-         vmin, vmax : None 
2531-             Ignored but included for consistency with other normalizers. These are 
2532-             set to the minimum and maximum of `levels`. 
2530+             The level boundaries. Must be monotonically increasing 
2531+             or decreasing. 
2532+         vmin : float, optional 
2533+             Ignored but included for consistency with other normalizers. 
2534+             Set to the minimum of `levels`. 
2535+         vmax : float, optional 
2536+             Ignored but included for consistency with other normalizers. 
2537+             Set to the minimum of `levels`. 
25332538        clip : bool, optional 
2534-             Whether to clip values falling outside of the minimum and 
2535-             maximum levels. 
2539+             Whether to clip values falling outside of the minimum 
2540+             and maximum of `levels`. 
2541+ 
2542+         See also 
2543+         -------- 
2544+         proplot.constructor.Norm 
2545+         proplot.colors.DiscreteNorm 
25362546
25372547        Note 
25382548        ---- 
2539-         This normalizer adapts the algorithm used by 
2540-         `~matplotlib.colors.LinearSegmentedColormap` 
2541-         to select colors in-between indices in segment data tables. 
2549+         The algorithm this normalizer uses to select normalized values 
2550+         in-between level list indices is adapted from the algorithm 
2551+         `~matplotlib.colors.LinearSegmentedColormap` uses to select channel 
2552+         values in-between segment data points (hence the name `SegmentedNorm`). 
25422553
25432554        Example 
25442555        ------- 
@@ -2554,18 +2565,19 @@ def __init__(self, levels, vmin=None, vmax=None, clip=False):
25542565        >>> ax.contourf(data, levels=levels) 
25552566        """ 
25562567        # WARNING: Tried using descending levels by adding 1 - yq to __call__() and 
2557-         # inverse() but then tick labels fail. Instead just silently reverse here. 
2568+         # inverse() but then tick labels fail. Instead just silently reverse here and 
2569+         # the corresponding DiscreteLocator should enforce the descending axis. 
25582570        levels , _  =  _sanitize_levels (levels )
25592571        dest  =  np .linspace (0 , 1 , len (levels ))
2560-         vmin , vmax  =  np .min (levels ), np .max (levels )
2572+         vmin  =  np .min (levels )
2573+         vmax  =  np .max (levels )
25612574        super ().__init__ (vmin = vmin , vmax = vmax , clip = clip )
25622575        self ._x  =  self .boundaries  =  levels   # 'boundaries' are used in PlotAxes 
25632576        self ._y  =  dest 
25642577
25652578    def  __call__ (self , value , clip = None ):
25662579        """ 
2567-         Normalize the data values to 0-1. Inverse 
2568-         of `~SegmentedNorm.inverse`. 
2580+         Normalize the data values to 0-1. Inverse of `~SegmentedNorm.inverse`. 
25692581
25702582        Parameters 
25712583        ---------- 
@@ -2586,7 +2598,7 @@ def __call__(self, value, clip=None):
25862598
25872599    def  inverse (self , value ):
25882600        """ 
2589-         Inverse operation  of `~SegmentedNorm.__call__`. 
2601+         Inverse of `~SegmentedNorm.__call__`. 
25902602
25912603        Parameters 
25922604        ---------- 
@@ -2603,7 +2615,7 @@ def inverse(self, value):
26032615class  DivergingNorm (mcolors .Normalize ):
26042616    """ 
26052617    Normalizer that ensures some central data value lies at the central 
2606-     colormap color.   The default central value is ``0``. 
2618+     colormap color. The default central value is ``0``. 
26072619    """ 
26082620    def  __str__ (self ):
26092621        return  type (self ).__name__  +  f'(center={ self .vcenter !r}  
@@ -2616,15 +2628,16 @@ def __init__(
26162628        ---------- 
26172629        vcenter : float, default: 0 
26182630            The data value corresponding to the central colormap position. 
2619-         vmin, vmax : float, optional 
2620-             The minimum and maximum data values. 
2631+         vmin : float, optional 
2632+             The minimum data value. 
2633+         vmax : float, optional 
2634+             The maximum data value. 
26212635        fair : bool, optional 
2622-             If ``True`` (default), the speeds of the color gradations on 
2623-             either side of the center point are equal, but colormap colors may 
2624-             be omitted. If ``False``, all colormap colors are included, but 
2625-             the color gradations on one side may be faster than the other side. 
2626-             ``False`` should be used with great care, as it may result in 
2627-             a misleading interpretation of your data. 
2636+             If ``True`` (default), the speeds of the color gradations on either side 
2637+             of the center point are equal, but colormap colors may be omitted. If 
2638+             ``False``, all colormap colors are included, but the color gradations on 
2639+             one side may be faster than the other side. ``False`` should be used with 
2640+             great care, as it may result in a misleading interpretation of your data. 
26282641        clip : bool, optional 
26292642            Whether to clip values falling outside of `vmin` and `vmax`. 
26302643
@@ -2637,17 +2650,15 @@ def __init__(
26372650        # NOTE: This is a stale PR that plans to implement the same features. 
26382651        # https://github.com/matplotlib/matplotlib/pull/15333#issuecomment-537545430 
26392652        # Since proplot is starting without matplotlib's baggage we can just implement 
2640-         # DivergingNorm  like they would prefer if they didn't have to worry about 
2653+         # a diverging norm  like they would prefer if they didn't have to worry about 
26412654        # confusing users: single class, default "fair" scaling that can be turned off. 
26422655        super ().__init__ (vmin , vmax , clip )
2643-         self .vmin  =  vmin 
2644-         self .vmax  =  vmax 
26452656        self .vcenter  =  vcenter 
26462657        self .fair  =  fair 
26472658
26482659    def  __call__ (self , value , clip = None ):
26492660        """ 
2650-         Normalize data values to 0-1. 
2661+         Normalize the  data values to 0-1. 
26512662
26522663        Parameters 
26532664        ---------- 
0 commit comments