在球面上绘制密度图 Python

3
如果我有对应于给定的(theta,phi)点的球面坐标中的值数组,如何在球面上绘制密度图? 我已经找到了如何构建球体的方法,例如Bloch球在球面上作图。 第一个例子看起来真的很漂亮-需要轴和热力图。

我们需要更多的信息。你想要一个只有密度强度颜色的球形图吗?还是你想让它在对应密度的点上改变R值?(我建议选择前者)。如果你想要交互式的图形,我推荐使用MayaVi,效果会更好。如果你只需要特定视角的静态图像,那么matplotlib就可以了。 - will
另外,你尝试过什么?你有数据文件可以让我们测试吗? - will
我试图放置一个Mathematica图形,但是我没有足够的声望点来这样做 - 它只是一个带有热力图的球体。我正在考虑使用与数据点对应的值自定义着色球体。您知道如何在Bloch球中创建这个漂亮的球体吗? - WoofDoggy
请包含链接,有人会为您编辑图片。 - will
你可以通过修改Bloch类来实现这个功能 - 它使用了plot_surface,这意味着你可以传递一个"face_colors"关键字参数,并自己设置面的颜色。你是想要得到像这样的图吗? - will
1个回答

9
如果您创建QuTipBloch类的子类,并更改其绘制球的方式,则可以绘制密度图并保留它创建的所有其他框架。
参考 matplotlib surface_plot 示例 ,修改Bloch类的绘图函数即可。将其放在您自己的子类中可避免对库进行任何修改。
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)

我在这里做的是让绘图部分调用BlochDensity的函数:self.density(theta,phi) - 我还没有定义。
在创建BlochDensity对象之后,需要创建该函数,该函数将theta, phi映射到您的密度上。建议使用SciPy的2D插值来创建该函数,类似于以下内容:
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()

enter image description here

如果您想增加分辨率,只需在BlochDensityplot_*函数中更改linspace中的数字即可。


1
刚刚意识到底部的演示图查看密度图会更好,如果linspace中的值较小,则会减少波峰。尝试减少它以查看效果。 - will

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接