2

Is it possible to clip an image generated by imshow() to the area under a line/multiple lines? I think Clip an image using several patches in matplotlib may have the solution, but I'm not sure how to apply it here.

I just want the coloring (from imshow()) under the lines in this plot: Normalized Planck's law plot with IR/Vis/UV coloring

Here is my plotting code:

from __future__ import division
from matplotlib.pyplot import *
from numpy import *

# wavelength array
lambd = logspace(-3.8, -7.2, 1000)

# temperatures
T_earth = 300
T_sun = 6000

# planck's law constants
h = 6.626069e-34
c = 2.997925e8
k = 1.380648e-23

# compute power using planck's law
power_earth = 2*h*c**2/lambd**5 * 1/(exp(h*c/(lambd*k*T_earth)) - 1)
power_sun = 2*h*c**2/lambd**5 * 1/(exp(h*c/(lambd*k*T_sun)) - 1)

# set up color array based on "spectrum" colormap
colors = zeros((1000,1000))
colors[:,:1000-764] = 0.03
for x,i in enumerate(range(701,765)):
    colors[:,1000-i] = 1-x/(765-701)
colors[:,1000-701:] = 0.98

figure(1,(4,3),dpi=100)
# plot normalized planck's law graphs
semilogx(lambd, power_earth/max(power_earth), 'b-', lw=4, zorder=5); hold(True)
semilogx(lambd, power_sun/max(power_sun), 'r-', lw=4, zorder=5); hold(True)
# remove ticks (for now)
yticks([]); xticks([])
# set axis to contain lines nicely
axis([min(lambd), max(lambd), 0, 1.1])
# plot colors, shift extent to match graph
imshow(colors, cmap="spectral", extent=[min(lambd), max(lambd), 0, 1.1])
# reverse x-axis (longer wavelengths to the left)
ax = gca(); ax.set_xlim(ax.get_xlim()[::-1])

tight_layout()
show()
Community
  • 1
  • 1
jpatton
  • 394
  • 3
  • 17
  • 1
    do you mean 'under' as in the pixels that are covered by the lines, or 'under' as in the region between the curve and the x-axis? It is also best if you make the code you self-contained (as it stands, no one else can test your code). – tacaswell Feb 21 '13 at 00:57
  • Apologies for wait, I have updated the post will the entire code. I am looking to keep the imshow output (IR/Vis/UV spectrum) for areas underneath either curve. – jpatton Feb 25 '13 at 21:09

1 Answers1

4

What you can do in this case is using the area under the curve as a Patch to apply set_clip_path. All you have to do is call fill_between and extract the corresponding path, like this:

semilogx(lambd, power_earth/max(power_earth), 'b-', lw=4, zorder=5)
# Area under the curve
fillb_earth = fill_between(lambd, power_earth/max(power_earth), color='none', lw=0)
# Get the path
path_earth, = fillb_earth.get_paths()
# Create a Patch
mask_earth = PathPatch(path_earth, fc='none')
# Add it to the current axes
gca().add_patch(mask_earth)
# Add the image
im_earth = imshow(colors, cmap="spectral", extent=[min(lambd), max(lambd), 0, 1.1])
# Clip the image with the Patch
im_earth.set_clip_path(mask_earth)

And then repeat the same lines for the Sun. Here is the result.Clipped image

astrojuanlu
  • 6,744
  • 8
  • 45
  • 105