|
| 1 | +""" |
| 2 | +=========================================== |
| 3 | +Blend transparency with color in 2-D images |
| 4 | +=========================================== |
| 5 | +
|
| 6 | +Blend transparency with color to highlight parts of data with imshow. |
| 7 | +
|
| 8 | +A common use for :func:`matplotlib.pyplot.imshow` is to plot a 2-D statistical |
| 9 | +map. While ``imshow`` makes it easy to visualize a 2-D matrix as an image, |
| 10 | +it doesn't easily let you add transparency to the output. For example, one can |
| 11 | +plot a statistic (such as a t-statistic) and color the transparency of |
| 12 | +each pixel according to its p-value. This example demonstrates how you can |
| 13 | +achieve this effect using :class:`matplotlib.colors.Normalize`. Note that it is |
| 14 | +not possible to directly pass alpha values to :func:`matplotlib.pyplot.imshow`. |
| 15 | +
|
| 16 | +First we will generate some data, in this case, we'll create two 2-D "blobs" |
| 17 | +in a 2-D grid. One blob will be positive, and the other negative. |
| 18 | +""" |
| 19 | +# sphinx_gallery_thumbnail_number = 3 |
| 20 | +import numpy as np |
| 21 | +import matplotlib.pyplot as plt |
| 22 | +from matplotlib.colors import Normalize |
| 23 | + |
| 24 | + |
| 25 | +def normal_pdf(x, mean, var): |
| 26 | + return np.exp(-(x - mean)**2 / (2*var)) |
| 27 | + |
| 28 | + |
| 29 | +# Generate the space in which the blobs will live |
| 30 | +xmin, xmax, ymin, ymax = (0, 100, 0, 100) |
| 31 | +n_bins = 100 |
| 32 | +xx = np.linspace(xmin, xmax, n_bins) |
| 33 | +yy = np.linspace(ymin, ymax, n_bins) |
| 34 | + |
| 35 | +# Generate the blobs. The range of the values is roughly -.0002 to .0002 |
| 36 | +means_high = [20, 50] |
| 37 | +means_low = [50, 60] |
| 38 | +var = [150, 200] |
| 39 | + |
| 40 | +gauss_x_high = normal_pdf(xx, means_high[0], var[0]) |
| 41 | +gauss_y_high = normal_pdf(yy, means_high[1], var[0]) |
| 42 | + |
| 43 | +gauss_x_low = normal_pdf(xx, means_low[0], var[1]) |
| 44 | +gauss_y_low = normal_pdf(yy, means_low[1], var[1]) |
| 45 | + |
| 46 | +weights_high = np.array(np.meshgrid(gauss_x_high, gauss_y_high)).prod(0) |
| 47 | +weights_low = -1 * np.array(np.meshgrid(gauss_x_low, gauss_y_low)).prod(0) |
| 48 | +weights = weights_high + weights_low |
| 49 | + |
| 50 | +# We'll also create a grey background into which the pixels will fade |
| 51 | +greys = np.ones(weights.shape + (3,)) * 70 |
| 52 | + |
| 53 | +# First we'll plot these blobs using only ``imshow``. |
| 54 | +vmax = np.abs(weights).max() |
| 55 | +vmin = -vmax |
| 56 | +cmap = plt.cm.RdYlBu |
| 57 | + |
| 58 | +fig, ax = plt.subplots() |
| 59 | +ax.imshow(greys) |
| 60 | +ax.imshow(weights, extent=(xmin, xmax, ymin, ymax), cmap=cmap) |
| 61 | +ax.set_axis_off() |
| 62 | + |
| 63 | +############################################################################### |
| 64 | +# Blending in transparency |
| 65 | +# ======================== |
| 66 | +# |
| 67 | +# The simplest way to include transparency when plotting data with |
| 68 | +# :func:`matplotlib.pyplot.imshow` is to convert the 2-D data array to a |
| 69 | +# 3-D image array of rgba values. This can be done with |
| 70 | +# :class:`matplotlib.colors.Normalize`. For example, we'll create a gradient |
| 71 | +# moving from left to right below. |
| 72 | + |
| 73 | +# Create an alpha channel of linearly increasing values moving to the right. |
| 74 | +alphas = np.ones(weights.shape) |
| 75 | +alphas[:, 30:] = np.linspace(1, 0, 70) |
| 76 | + |
| 77 | +# Normalize the colors b/w 0 and 1, we'll then pass an MxNx4 array to imshow |
| 78 | +colors = Normalize(vmin, vmax, clip=True)(weights) |
| 79 | +colors = cmap(colors) |
| 80 | + |
| 81 | +# Now set the alpha channel to the one we created above |
| 82 | +colors[..., -1] = alphas |
| 83 | + |
| 84 | +# Create the figure and image |
| 85 | +# Note that the absolute values may be slightly different |
| 86 | +fig, ax = plt.subplots() |
| 87 | +ax.imshow(greys) |
| 88 | +ax.imshow(colors, extent=(xmin, xmax, ymin, ymax)) |
| 89 | +ax.set_axis_off() |
| 90 | + |
| 91 | +############################################################################### |
| 92 | +# Using transparency to highlight values with high amplitude |
| 93 | +# ========================================================== |
| 94 | +# |
| 95 | +# Finally, we'll recreate the same plot, but this time we'll use transparency |
| 96 | +# to highlight the extreme values in the data. This is often used to highlight |
| 97 | +# data points with smaller p-values. We'll also add in contour lines to |
| 98 | +# highlight the image values. |
| 99 | + |
| 100 | +# Create an alpha channel based on weight values |
| 101 | +# Any value whose absolute value is > .0001 will have zero transparency |
| 102 | +alphas = Normalize(0, .3, clip=True)(np.abs(weights)) |
| 103 | +alphas = np.clip(alphas, .4, 1) # alpha value clipped at the bottom at .4 |
| 104 | + |
| 105 | +# Normalize the colors b/w 0 and 1, we'll then pass an MxNx4 array to imshow |
| 106 | +colors = Normalize(vmin, vmax)(weights) |
| 107 | +colors = cmap(colors) |
| 108 | + |
| 109 | +# Now set the alpha channel to the one we created above |
| 110 | +colors[..., -1] = alphas |
| 111 | + |
| 112 | +# Create the figure and image |
| 113 | +# Note that the absolute values may be slightly different |
| 114 | +fig, ax = plt.subplots() |
| 115 | +ax.imshow(greys) |
| 116 | +ax.imshow(colors, extent=(xmin, xmax, ymin, ymax)) |
| 117 | + |
| 118 | +# Add contour lines to further highlight different levels. |
| 119 | +ax.contour(weights[::-1], levels=[-.1, .1], colors='k', linestyles='-') |
| 120 | +ax.set_axis_off() |
| 121 | +plt.show() |
| 122 | + |
| 123 | +ax.contour(weights[::-1], levels=[-.0001, .0001], colors='k', linestyles='-') |
| 124 | +ax.set_axis_off() |
| 125 | +plt.show() |
0 commit comments