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

Reply via email to