简体   繁体   中英

density plot on a sphere Python

How to plot density map on the surface of a sphere if I have array of values corresponding to given (theta,phi) points in spherical coordinates? I have found how to construct a sphere eg Bloch sphere or plotting on a sphere . The first example is really nice looking - axes are needed and heatmap.

If you subclass the Bloch class of QuTip , and alter the way it draws the sphere, you can draw density plots and keep all the other framework it creates.

Taking the matplotlib surface_plot examples , and altering the Bloch class' plotting functions works. Putting it in your own subclass prevents you from hacking away at the libraries.

from qutip import Bloch
from math import sqrt, sin, cos, pi
from colorsys import hsv_to_rgb


from numpy import linspace, outer, ones, sin, cos, arccos, arctan2, size, empty
class BlochDensity(Bloch):
  def plot_back(self):
    # back half of sphere
    u = linspace(0, pi, 25)
    v = linspace(0, pi, 25)
    x = outer(cos(u), sin(v))
    y = outer(sin(u), sin(v))
    z = outer(ones(size(u)), cos(v))

    colours = empty(x.shape, dtype=object)
    for i in range(len(x)):
      for j in range(len(y)):
        theta = arctan2(y[i,j], x[i,j])
        phi = arccos(z[i,j])

        colours[i,j] = self.density(theta, phi)


    self.axes.plot_surface(x, y, z, rstride=1, cstride=1,
                           facecolors=colours,
                           alpha=self.sphere_alpha, 
                           linewidth=0, antialiased=True)
    # wireframe
    self.axes.plot_wireframe(x, y, z, rstride=5, cstride=5,
                             color=self.frame_color,
                             alpha=self.frame_alpha)
    # equator
    self.axes.plot(1.0 * cos(u), 1.0 * sin(u), zs=0, zdir='z',
                   lw=self.frame_width, color=self.frame_color)
    self.axes.plot(1.0 * cos(u), 1.0 * sin(u), zs=0, zdir='x',
                   lw=self.frame_width, color=self.frame_color)



  def plot_front(self):
    # front half of sphere
    u = linspace(-pi, 0, 25)
    v = linspace(0, pi, 25)
    x = outer(cos(u), sin(v))
    y = outer(sin(u), sin(v))
    z = outer(ones(size(u)), cos(v))

    colours = empty(x.shape, dtype=object)
    for i in range(len(x)):
      for j in range(len(y)):
        theta = arctan2(y[i,j], x[i,j])
        phi = arccos(z[i,j])

        colours[i,j] = self.density(theta, phi)


    self.axes.plot_surface(x, y, z, rstride=1, cstride=1,
                           facecolors=colours,
                           alpha=self.sphere_alpha, 
                           linewidth=0, antialiased=True)


    # wireframe
    self.axes.plot_wireframe(x, y, z, rstride=5, cstride=5,
                             color=self.frame_color,
                             alpha=self.frame_alpha)
    # equator
    self.axes.plot(1.0 * cos(u), 1.0 * sin(u),
                   zs=0, zdir='z', lw=self.frame_width,
                   color=self.frame_color)
    self.axes.plot(1.0 * cos(u), 1.0 * sin(u),
                   zs=0, zdir='x', lw=self.frame_width,
                   color=self.frame_color)

What i've done here is make the plotting part call the function of BlochDensity : self.density(theta, phi) - which i haven't defined.

After you create the BlochDensity object, you need to create that function, which is the mapping of theta, phi onto your density. I would advise using SciPy's 2D interpolation to create the function, something like this:

from scipy.interpolate import interp2d
from numpy.random import rand

b = BlochDensity()
b.sphere_alpha=0.5

thetas, phis = linspace(-pi,pi,10), linspace(0,pi,10)
density = rand(len(thetas), len(phis))

#scale density to a maximum of 1
density /= density.max()

interpolated_density = interp2d(thetas, phis, density)

def f(theta, phi):
  return hsv_to_rgb(interpolated_density(theta,phi), 1, 1)

b.density = f

b.show()

b.density = f

b.show()

在此处输入图片说明

If you want to increase the resolution, then just change the numbers in the linspace inside the plot_* functions of BlochDensity .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM