Timothée Lecomte wrote:
Dear all,
I am using matplotlib with a great pleasure, and I enjoy its capabilities.
I have recently attended a conference where the invited speaker showed
great visualizations of arrays from both experiments and simulations.
His plots were basically looking like those produced by imshow, that is
a luminance array rendered as a colormap image, but with the additionnal
use of a shading, which gives a really great feeling to the image. You
can feel the height of each part of the image.
I have tried to find what software could have produced such a plot, and
found the ReliefPlot function of Mathematica, which has precisely this
purpose : rendering a colormap image from an array with a shading to
give the perception of relief.
The documentation and its examples are self-explanatory :
http://reference.wolfram.com/mathematica/ref/ReliefPlot.html
(look in particular at the first "neat example" at the bottom of that page)
The two "live" demonstrations illustrate this plot style quite well too :
http://demonstrations.wolfram.com/ReliefShadedElevationMap/
http://demonstrations.wolfram.com/VoronoiImage/
So here are my questions :
Is there a trick to generate an image with such a shading in matplotlib ?
If not, do you know of a python tool that could help ?
Where could I start if I want to code it myself in matplotlib ?
Thanks for your help.
Best regards,
Timothée Lecomte
Timothée: There is nothing built-in, but it would be a nice thing to have.
Here's a proof-of-concept hack that follows the approach used in the Generic
Mapping Tools (explained here
http://www.seismo.ethz.ch/gmt/doc/html/tutorial/node70.html), with some code
borrowed from http://www.langarson.com.au/blog/?p=14. It's very rough, but if
it looks promising to you I can try to polish it.
-Jeff
--
Jeffrey S. Whitaker Phone : (303)497-6313
Meteorologist FAX : (303)497-6449
NOAA/OAR/PSD R/PSD1 Email : jeffrey.s.whita...@noaa.gov
325 Broadway Office : Skaggs Research Cntr 1D-113
Boulder, CO, USA 80303-3328 Web : http://tinyurl.com/5telg
import numpy as np
import matplotlib.pyplot as plt
def rgb_to_hsv_arr(arr):
""" fast rgb_to_hsv using numpy array """
# adapted from Arnar Flatberg http://www.mail-archive.com/numpy-discuss...@scipy.org/msg06147.html it now handles
# NaN properly and mimics colorsys.rgb_to_hsv output
arr = arr/255.
out = np.empty_like(arr)
arr_max = arr.max(-1)
delta = arr.ptp(-1)
s = delta / arr_max
s[delta==0] = 0
# red is max
idx = (arr[:,:,0] == arr_max)
out[idx, 0] = (arr[idx, 1] - arr[idx, 2]) / delta[idx]
# green is max
idx = (arr[:,:,1] == arr_max)
out[idx, 0] = 2. + (arr[idx, 2] - arr[idx, 0] ) / delta[idx]
# blue is max
idx = (arr[:,:,2] == arr_max)
out[idx, 0] = 4. + (arr[idx, 0] - arr[idx, 1] ) / delta[idx]
out[:,:,0] = (out[:,:,0]/6.0) % 1.0
out[:,:,1] = s
out[:,:,2] = arr_max
return out
# code from colorsys module, should numpy'ify
def hsv_to_rgb(h, s, v):
if s == 0.0: return v, v, v
i = int(h*6.0) # XXX assume int() truncates!
f = (h*6.0) - i
p = v*(1.0 - s)
q = v*(1.0 - s*f)
t = v*(1.0 - s*(1.0-f))
if i%6 == 0: return v, t, p
if i == 1: return q, v, p
if i == 2: return p, v, t
if i == 3: return p, q, v
if i == 4: return t, p, v
if i == 5: return v, p, q
# Cannot get here
def hsv_to_rgb_arr(arr):
# vectorize this!
out = np.empty(arr.shape, arr.dtype)
for i in range(arr.shape[0]):
for j in range(arr.shape[1]):
h,s,v = arr[i,j,0].item(),arr[i,j,1].item(),arr[i,j,2].item()
r,g,b = hsv_to_rgb(h,s,v)
out[i,j,0]=r; out[i,j,1]=g; out[i,j,2]=b
return out
def illumination(idata,azdeg=315.0,altdeg=45.):
# convert alt, az to radians
az = azdeg*np.pi/180.0
alt = altdeg*np.pi/180.0
# gradient in x and y directions
dx, dy = np.gradient(idata)
slope = 0.5*np.pi - np.arctan(np.hypot(dx, dy))
aspect = np.arctan2(dx, dy)
odata = np.sin(alt)*np.sin(slope) + np.cos(alt)*np.cos(slope)*np.cos(-az -\
aspect - 0.5*np.pi)
# rescale to interval -1,1
# +1 means maximum sun exposure and -1 means complete shade.
odata = (odata - odata.min())/(odata.max() - odata.min())
odata = 2.*odata - 1.
return odata
# test data
X,Y=np.mgrid[-5:5:0.1,-5:5:0.1]
Z=np.sin(X**2+Y**2+1e-4)/(X**2+Y**2+1e-4) # Create the data to be plotted
# imagine an artificial sun placed at infinity in
# some azimuth and elevation position illuminating our surface. The parts of
# the surface that slope toward the sun should brighten while those sides
# facing away should become darker; no shadows are cast as a result of
# topographic undulations.
intensity = illumination(Z,altdeg=10)
plt.figure()
# plot original image
im = plt.imshow(Z,cmap=plt.cm.hsv)
# convert to rgb, then rgb to hsv
rgb = im.to_rgba(Z)
hsv = rgb_to_hsv_arr(rgb[:,:,0:3])
# darken any pure color (on the cube facets) by keeping H fixed and adding black
# and brighten it by adding white; for interior points in the cube we will add or
# remove gray.
hsv_min_sat = 1.0
hsv_max_sat = 0.1
hsv_min_val = 0.9
hsv_max_val = 1.0
hsv[:,:,1] = np.where(intensity > 0, (1.-intensity)*hsv[:,:,1] +\
intensity*hsv_max_sat, hsv[:,:,1])
hsv[:,:,2] = np.where(intensity > 0, (1.-intensity)*hsv[:,:,1] +\
intensity*hsv_max_val, hsv[:,:,1])
hsv[:,:,1] = np.where(intensity < 0, (1.+intensity)*hsv[:,:,1] -\
intensity*hsv_min_sat, hsv[:,:,1])
hsv[:,:,2] = np.where(intensity < 0, (1.+intensity)*hsv[:,:,1] -\
intensity*hsv_min_val, hsv[:,:,1])
hsv[:,:,1:] = np.where(hsv[:,:,1:]<0.,0,hsv[:,:,1:])
hsv[:,:,1:] = np.where(hsv[:,:,1:]>1.,1,hsv[:,:,1:])
# convert modified hsv back to rgb.
rgb[:,:,0:3] = hsv_to_rgb_arr(hsv)
plt.figure()
# plot shaded image.
plt.imshow(rgb)
plt.show()
------------------------------------------------------------------------------
Apps built with the Adobe(R) Flex(R) framework and Flex Builder(TM) are
powering Web 2.0 with engaging, cross-platform capabilities. Quickly and
easily build your RIAs with Flex Builder, the Eclipse(TM)based development
software that enables intelligent coding and step-through debugging.
Download the free 60 day trial. http://p.sf.net/sfu/www-adobe-com
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-users