From 60d78ab53be2393cad763005943d857115fee263 Mon Sep 17 00:00:00 2001 From: Chris Holdgraf Date: Sat, 30 Sep 2017 10:24:51 +0100 Subject: [PATCH 1/3] transparency blend example --- .../image_transparency_blend.py | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 examples/images_contours_and_fields/image_transparency_blend.py diff --git a/examples/images_contours_and_fields/image_transparency_blend.py b/examples/images_contours_and_fields/image_transparency_blend.py new file mode 100644 index 000000000000..b4b98ac4839f --- /dev/null +++ b/examples/images_contours_and_fields/image_transparency_blend.py @@ -0,0 +1,77 @@ +""" +============================================= +Blend transparency with color with 2-D images +============================================= + +Blend transparency with color to highlight parts of data with imshow. + +A common use for :func:`matplotlib.pyplot.imshow` is to plot a 2-D statistical +map. In this case, it's common to visualize the statistic of choice (e.g., +a t-statistic) alongisde another value of interest (e.g., the p-value for that +statistic). One way to do this is to map the p-value onto the transparency of +the image such that data with "significant" values are highlighted. + +This example demonstrates how you can achieve this effect using +:class:`matplotlib.colors.Normalize. Note that it is not possible to directly +pass alpha values to :func:`matplotlib.pyplot.imshow`. + +First we will generate some data, in this case, we'll create two 2-D "blobs" +in a 2-D grid. One blob will be positive, and the other negative. +""" +# sphinx_gallery_thumbnail_number = 2 +import numpy as np +from scipy.stats import multivariate_normal +import matplotlib.pyplot as plt +from matplotlib.colors import Normalize + +# Generate the space in which the blobs will live +xmin, xmax, ymin, ymax = (0, 100, 0, 100) +xx = np.linspace(xmin, xmax, 100) +yy = np.linspace(ymin, ymax, 100) +grid = np.array(np.meshgrid(xx, yy)) +grid = grid.transpose(2, 1, 0) + +# Generate the blobs +means_high = [20, 50] +means_low = [50, 60] +cov = [[500, 0], [0, 800]] +gauss_high = multivariate_normal.pdf(grid, means_high, cov) +gauss_low = -1 * multivariate_normal.pdf(grid, means_low, cov) +weights = gauss_high + gauss_low + +# We'll plot these blobs using only ``imshow``. +vmax = np.abs(weights).max() * 1.5 +vmin = -vmax +cmap = plt.cm.RdYlBu +fig, ax = plt.subplots() +ax.imshow(weights, extent=(xmin, xmax, ymin, ymax), cmap=cmap) +ax.set_axis_off() + +################################################################################ +# Blending in transparency +# ======================== +# +# Below, we'll recreate the same plot, but this time we'll blend in +# transparency with the image so that the extreme values are highlighted. +# We'll also add in contour lines to highlight the image values. + +# Create an alpha channel based on weight values +alphas = Normalize(0, .0001, clip=True)(np.abs(weights)) +alphas = np.clip(alphas, .4, 1) + +# Normalize the colors b/w 0 and 1, we'll then pass an MxNx4 array to imshow +colors = Normalize(vmin, vmax)(weights) +colors = cmap(colors) + +# Now set the alpha channel to the one we created above +colors[..., -1] = alphas + +# Create the figure and image +# Note that the absolute values may be slightly different +fig, ax = plt.subplots() +ax.imshow(colors, extent=(xmin, xmax, ymin, ymax)) + +# Add contour lines to further highlight different levels. +ax.contour(weights[::-1], levels=[-.0001, .0001], colors='k', linestyles='-') +ax.set_axis_off() +plt.show() From 5b448ccc55130ae0e395942b13d040284b334f07 Mon Sep 17 00:00:00 2001 From: Chris Holdgraf Date: Sun, 1 Oct 2017 15:31:12 +0100 Subject: [PATCH 2/3] addressing comments --- .../image_transparency_blend.py | 74 ++++++++++++++----- 1 file changed, 54 insertions(+), 20 deletions(-) diff --git a/examples/images_contours_and_fields/image_transparency_blend.py b/examples/images_contours_and_fields/image_transparency_blend.py index b4b98ac4839f..c57328d1128b 100644 --- a/examples/images_contours_and_fields/image_transparency_blend.py +++ b/examples/images_contours_and_fields/image_transparency_blend.py @@ -1,24 +1,22 @@ """ -============================================= -Blend transparency with color with 2-D images -============================================= +=========================================== +Blend transparency with color in 2-D images +=========================================== Blend transparency with color to highlight parts of data with imshow. A common use for :func:`matplotlib.pyplot.imshow` is to plot a 2-D statistical -map. In this case, it's common to visualize the statistic of choice (e.g., -a t-statistic) alongisde another value of interest (e.g., the p-value for that -statistic). One way to do this is to map the p-value onto the transparency of -the image such that data with "significant" values are highlighted. - -This example demonstrates how you can achieve this effect using -:class:`matplotlib.colors.Normalize. Note that it is not possible to directly -pass alpha values to :func:`matplotlib.pyplot.imshow`. +map. While ``imshow`` makes it easy to visualize a 2-D matrix as an image, +it doesn't easily let you add transparency to the output. For example, one can +plot a statistic (such as a t-statistic) and color the transparency of +each pixel according to its p-value. This example demonstrates how you can +achieve this effect using :class:`matplotlib.colors.Normalize`. Note that it is +not possible to directly pass alpha values to :func:`matplotlib.pyplot.imshow`. First we will generate some data, in this case, we'll create two 2-D "blobs" in a 2-D grid. One blob will be positive, and the other negative. """ -# sphinx_gallery_thumbnail_number = 2 +# sphinx_gallery_thumbnail_number = 3 import numpy as np from scipy.stats import multivariate_normal import matplotlib.pyplot as plt @@ -31,7 +29,7 @@ grid = np.array(np.meshgrid(xx, yy)) grid = grid.transpose(2, 1, 0) -# Generate the blobs +# Generate the blobs. The range of the values is roughly -.0002 to .0002 means_high = [20, 50] means_low = [50, 60] cov = [[500, 0], [0, 800]] @@ -39,25 +37,60 @@ gauss_low = -1 * multivariate_normal.pdf(grid, means_low, cov) weights = gauss_high + gauss_low -# We'll plot these blobs using only ``imshow``. -vmax = np.abs(weights).max() * 1.5 +# We'll also create a grey background into which the pixels will fade +greys = np.ones(weights.shape + (3,)) * 70 + +# First we'll plot these blobs using only ``imshow``. +vmax = np.abs(weights).max() vmin = -vmax cmap = plt.cm.RdYlBu + fig, ax = plt.subplots() +ax.imshow(greys) ax.imshow(weights, extent=(xmin, xmax, ymin, ymax), cmap=cmap) ax.set_axis_off() -################################################################################ +############################################################################### # Blending in transparency # ======================== # -# Below, we'll recreate the same plot, but this time we'll blend in -# transparency with the image so that the extreme values are highlighted. -# We'll also add in contour lines to highlight the image values. +# The simplest way to include transparency when plotting data with +# :func:`matplotlib.pyplot.imshow` is to convert the 2-D data array to a +# 3-D image array of rgba values. This can be done with +# :class:`matplotlib.colors.Normalize`. For example, we'll create a gradient +# moving from left to right below. + +# Create an alpha channel of linearly increasing values moving to the right. +alphas = np.ones(weights.shape) +alphas[:, 30:] = np.linspace(1, 0, 70) + +# Normalize the colors b/w 0 and 1, we'll then pass an MxNx4 array to imshow +colors = Normalize(vmin, vmax, clip=True)(weights) +colors = cmap(colors) + +# Now set the alpha channel to the one we created above +colors[..., -1] = alphas + +# Create the figure and image +# Note that the absolute values may be slightly different +fig, ax = plt.subplots() +ax.imshow(greys) +ax.imshow(colors, extent=(xmin, xmax, ymin, ymax)) +ax.set_axis_off() + +############################################################################### +# Using transparency to highlight values with high amplitude +# ========================================================== +# +# Finally, we'll recreate the same plot, but this time we'll use transparency +# to highlight the extreme values in the data. This is often used to highlight +# data points with smaller p-values. We'll also add in contour lines to +# highlight the image values. # Create an alpha channel based on weight values +# Any value whose absolute value is > .0001 will have zero transparency alphas = Normalize(0, .0001, clip=True)(np.abs(weights)) -alphas = np.clip(alphas, .4, 1) +alphas = np.clip(alphas, .4, 1) # alpha value clipped at the bottom at .4 # Normalize the colors b/w 0 and 1, we'll then pass an MxNx4 array to imshow colors = Normalize(vmin, vmax)(weights) @@ -69,6 +102,7 @@ # Create the figure and image # Note that the absolute values may be slightly different fig, ax = plt.subplots() +ax.imshow(greys) ax.imshow(colors, extent=(xmin, xmax, ymin, ymax)) # Add contour lines to further highlight different levels. From 750d4d8ce388782d8599fa255015f08249acd8c9 Mon Sep 17 00:00:00 2001 From: Chris Holdgraf Date: Sat, 14 Oct 2017 21:33:53 -0700 Subject: [PATCH 3/3] no scipy --- .../image_transparency_blend.py | 34 +++++++++++++------ 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/examples/images_contours_and_fields/image_transparency_blend.py b/examples/images_contours_and_fields/image_transparency_blend.py index c57328d1128b..54a4a59c6923 100644 --- a/examples/images_contours_and_fields/image_transparency_blend.py +++ b/examples/images_contours_and_fields/image_transparency_blend.py @@ -18,24 +18,34 @@ """ # sphinx_gallery_thumbnail_number = 3 import numpy as np -from scipy.stats import multivariate_normal import matplotlib.pyplot as plt from matplotlib.colors import Normalize + +def normal_pdf(x, mean, var): + return np.exp(-(x - mean)**2 / (2*var)) + + # Generate the space in which the blobs will live xmin, xmax, ymin, ymax = (0, 100, 0, 100) -xx = np.linspace(xmin, xmax, 100) -yy = np.linspace(ymin, ymax, 100) -grid = np.array(np.meshgrid(xx, yy)) -grid = grid.transpose(2, 1, 0) +n_bins = 100 +xx = np.linspace(xmin, xmax, n_bins) +yy = np.linspace(ymin, ymax, n_bins) # Generate the blobs. The range of the values is roughly -.0002 to .0002 means_high = [20, 50] means_low = [50, 60] -cov = [[500, 0], [0, 800]] -gauss_high = multivariate_normal.pdf(grid, means_high, cov) -gauss_low = -1 * multivariate_normal.pdf(grid, means_low, cov) -weights = gauss_high + gauss_low +var = [150, 200] + +gauss_x_high = normal_pdf(xx, means_high[0], var[0]) +gauss_y_high = normal_pdf(yy, means_high[1], var[0]) + +gauss_x_low = normal_pdf(xx, means_low[0], var[1]) +gauss_y_low = normal_pdf(yy, means_low[1], var[1]) + +weights_high = np.array(np.meshgrid(gauss_x_high, gauss_y_high)).prod(0) +weights_low = -1 * np.array(np.meshgrid(gauss_x_low, gauss_y_low)).prod(0) +weights = weights_high + weights_low # We'll also create a grey background into which the pixels will fade greys = np.ones(weights.shape + (3,)) * 70 @@ -89,7 +99,7 @@ # Create an alpha channel based on weight values # Any value whose absolute value is > .0001 will have zero transparency -alphas = Normalize(0, .0001, clip=True)(np.abs(weights)) +alphas = Normalize(0, .3, clip=True)(np.abs(weights)) alphas = np.clip(alphas, .4, 1) # alpha value clipped at the bottom at .4 # Normalize the colors b/w 0 and 1, we'll then pass an MxNx4 array to imshow @@ -106,6 +116,10 @@ ax.imshow(colors, extent=(xmin, xmax, ymin, ymax)) # Add contour lines to further highlight different levels. +ax.contour(weights[::-1], levels=[-.1, .1], colors='k', linestyles='-') +ax.set_axis_off() +plt.show() + ax.contour(weights[::-1], levels=[-.0001, .0001], colors='k', linestyles='-') ax.set_axis_off() plt.show()