11"""
2- ============
3- Gradient Bar
4- ============
2+ ========================
3+ Bar chart with gradients
4+ ========================
5+
6+ Matplotlib does not natively support gradients. However, we can emulate a
7+ gradient-filled rectangle by an `.AxesImage` of the right size and coloring.
8+
9+ In particular, we use a colormap to generate the actual colors. It is then
10+ sufficient to define the underlying values on the corners of the image and
11+ let bicubic interpolation fill out the area. We define the gradient direction
12+ by a unit vector *v*. The values at the corners are then obtained by the
13+ lengths of the projections of the corner vectors on *v*.
14+
15+ A similar approach can be used to create a gradient background for an axes.
16+ In that case, it is helpful to uses Axes coordinates
17+ (`extent=(0, 1, 0, 1), transform=ax.transAxes`) to be independent of the data
18+ coordinates.
519
620"""
721import matplotlib .pyplot as plt
1024np .random .seed (19680801 )
1125
1226
13- def gbar (ax , x , y , width = 0.5 , bottom = 0 ):
14- X = [[.6 , .6 ], [.7 , .7 ]]
27+ def gradient_image (ax , extent , direction = 0.3 , cmap_range = (0 , 1 ), ** kwargs ):
28+ """
29+ Draw a gradient image based on a colormap.
30+
31+ Parameters
32+ ----------
33+ ax : Axes
34+ The axes to draw on.
35+ extent
36+ The extent of the image as (xmin, xmax, ymin, ymax).
37+ By default, this is in Axes coordinates but may be
38+ changed using the *transform* kwarg.
39+ direction : float
40+ The direction of the gradient. This is a number in
41+ range 0 (=vertical) to 1 (=horizontal).
42+ cmap_range : float, float
43+ The fraction (cmin, cmax) of the colormap that should be
44+ used for the gradient, where the complete colormap is (0, 1).
45+ **kwargs
46+ Other parameters are passed on to `.Axes.imshow()`.
47+ In particular useful is *cmap*.
48+ """
49+ phi = direction * np .pi / 2
50+ v = np .array ([np .cos (phi ), np .sin (phi )])
51+ X = np .array ([[v @ [1 , 0 ], v @ [1 , 1 ]],
52+ [v @ [0 , 0 ], v @ [0 , 1 ]]])
53+ a , b = cmap_range
54+ X = a + (b - a ) / X .max () * X
55+ im = ax .imshow (X , extent = extent , interpolation = 'bicubic' ,
56+ vmin = 0 , vmax = 1 , ** kwargs )
57+ return im
58+
59+
60+ def gradient_bar (ax , x , y , width = 0.5 , bottom = 0 ):
1561 for left , top in zip (x , y ):
1662 right = left + width
17- ax . imshow ( X , interpolation = 'bicubic' , cmap = plt . cm . Blues ,
18- extent = ( left , right , bottom , top ), alpha = 1 )
63+ gradient_image ( ax , extent = ( left , right , bottom , top ) ,
64+ cmap = plt . cm . Blues_r , cmap_range = ( 0 , 0.8 ) )
1965
2066
2167xmin , xmax = xlim = 0 , 10
@@ -24,13 +70,13 @@ def gbar(ax, x, y, width=0.5, bottom=0):
2470fig , ax = plt .subplots ()
2571ax .set (xlim = xlim , ylim = ylim , autoscale_on = False )
2672
27- X = [[ .6 , .6 ], [ .7 , .7 ]]
28- ax . imshow ( X , interpolation = 'bicubic' , cmap = plt . cm . copper ,
29- extent = ( xmin , xmax , ymin , ymax ), alpha = 1 )
73+ # background image
74+ gradient_image ( ax , direction = 0 , extent = ( 0 , 1 , 0 , 1 ), transform = ax . transAxes ,
75+ cmap = plt . cm . Oranges , cmap_range = ( 0.1 , 0.6 ) )
3076
3177N = 10
32- x = np .arange (N ) + 0.25
78+ x = np .arange (N ) + 0.15
3379y = np .random .rand (N )
34- gbar (ax , x , y , width = 0.7 )
80+ gradient_bar (ax , x , y , width = 0.7 )
3581ax .set_aspect ('auto' )
3682plt .show ()
0 commit comments