热图半球图 [英] Heat Map half-sphere plot

查看:29
本文介绍了热图半球图的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想将 720 x 180 的 theta 和 phi 值绘制成theta 范围 =(-180 到 180,步长为 0.5)phi 范围 =(0 到 -90,步长为 0.5)

这是我拥有的数据集示例:

Theta Phi 值-180 0 0.2-180 0.5 0.5…………-180 -90 1.1-179.5 0 0.92…………0 -90 0.6…………180 -89.5 0.17180 -90 0.12

所以最终,我想得到一个类似的情节:

我知道如何使用下面的代码创建半球,但如何从我的数据框中分配值?

将 matplotlib.pyplot 导入为 plt从 matplotlib 导入厘米,颜色从 mpl_toolkits.mplot3d 导入 Axes3D将 numpy 导入为 np# 创建一个球体r = 2pi = np.picos = np.cossin = np.sin高度p theta = np.mgrid[0.0:0.5*pi:180j, 0.0:2.0*pi:720j] #phi = alti, theta = azix = r*sin(phi)*cos(theta)y = r*sin(phi)*sin(theta)z = r*cos(phi)#设置颜色和渲染fig = plt.figure(figsize=(10, 8))ax = fig.add_subplot(111, 投影='3d')ax.plot_surface(x, y, z, rstride=4, cstride=4, color='w', alpha=0.1, linewidth=0)ax.set_xlim([-2.2,2.2])ax.set_ylim([-2.2,2.2])ax.set_zlim([0,3])ax.set_aspect("相等")ax.plot_wireframe(x, y, z, color="k")

代码生成这个

解决方案

I want to plot 720 x 180 values of theta and phi into theta range = (-180 to 180 with 0.5 step) phi range = (0 to -90 with 0.5 step)

This is the example of dataset that I have:

Theta Phi Values
-180   0    0.2
-180   0.5  0.5
...    ...  ...
-180   -90  1.1
-179.5  0   0.92
...    ...  ...
 0     -90   0.6
...    ...  ...
180   -89.5 0.17
180   -90   0.12

So eventually, I want to get a similar plot like this one:

I know how to create the half sphere with the code below, but how can assign the values from my dataframe?

import matplotlib.pyplot as plt
from matplotlib import cm, colors
from mpl_toolkits.mplot3d import Axes3D
import numpy as np

# Create a sphere
r = 2
pi = np.pi
cos = np.cos
sin = np.sin
altitude
phi, theta = np.mgrid[0.0:0.5*pi:180j, 0.0:2.0*pi:720j] # phi = alti, theta = azi
x = r*sin(phi)*cos(theta)
y = r*sin(phi)*sin(theta)
z = r*cos(phi)    
#Set colours and render
fig = plt.figure(figsize=(10, 8))
ax = fig.add_subplot(111, projection='3d')
ax.plot_surface(
    x, y, z,  rstride=4, cstride=4, color='w', alpha=0.1, linewidth=0)    
ax.set_xlim([-2.2,2.2])
ax.set_ylim([-2.2,2.2])
ax.set_zlim([0,3])
ax.set_aspect("equal")
ax.plot_wireframe(x, y, z, color="k")

the code generate this one

解决方案

Axes3D.plot_surface accepts 2D arrays as inputs. It provides the facecolors argument, which accepts an array of the same shape as the input arrays. This array should have the color for each face as rgba tuple in it. One can therefore normalize the array values to the range up to 1 and supply it the a colormap from matplotlib.cm.

The remaining problem is then to obtain this array from the 3 column list which is provided. Given a the datatable of length n*m where the first column denotes x values, second y values and the third some value, and where the sorting is first by x and then by y. One can then reshape the last column to an (n,m) array, where n is the number of x values and m of y values, using .reshape((m,n)).T.

Some further remarks:

  1. In the solution below, I needed to mimic this array and directly used angles in radiant, instead of degrees.
  2. The number of points, 180*720 seems a bit high. In order for the window not to take ages to rotate, I decreased that number.
  3. I renamed the angles, such that they match with the usual textbook definition, phi = azimuthal angle, theta=inclination angle (from z axis).
  4. The use of plot_wireframe may not make too much sense, since it will hide the surface below. If a wireframe is desired, one can play with the number of points to be drawn and the linewidth keyword argument. Setting linewidth to something big, like 3 or 5 makes the surface look nice, setting it to 1 leaves some wireframe look.

Here is the complete solution.

import matplotlib.pyplot as plt
from matplotlib import cm
from mpl_toolkits.mplot3d import Axes3D
import numpy as np

#theta inclination angle
#phi azimuthal angle
n_theta = 50 # number of values for theta
n_phi = 200  # number of values for phi
r = 2        #radius of sphere

theta, phi = np.mgrid[0.0:0.5*np.pi:n_theta*1j, 0.0:2.0*np.pi:n_phi*1j]

x = r*np.sin(theta)*np.cos(phi)
y = r*np.sin(theta)*np.sin(phi)
z = r*np.cos(theta)

# mimic the input array
# array columns phi, theta, value
# first n_theta entries: phi=0, second n_theta entries: phi=0.0315..
inp = []
for j in phi[0,:]:
    for i in theta[:,0]:
        val = 0.7+np.cos(j)*np.sin(i+np.pi/4.)# put something useful here
        inp.append([j, i, val])
inp = np.array(inp)
print inp.shape
print inp[49:60, :]

#reshape the input array to the shape of the x,y,z arrays. 
c = inp[:,2].reshape((n_phi,n_theta)).T
print z.shape
print c.shape


#Set colours and render
fig = plt.figure(figsize=(10, 8))
ax = fig.add_subplot(111, projection='3d')
#use facecolors argument, provide array of same shape as z
# cm.<cmapname>() allows to get rgba color from array.
# array must be normalized between 0 and 1
ax.plot_surface(
    x,y,z,  rstride=1, cstride=1, facecolors=cm.hot(c/c.max()), alpha=0.9, linewidth=1) 
ax.set_xlim([-2.2,2.2])
ax.set_ylim([-2.2,2.2])
ax.set_zlim([0,4.4])
ax.set_aspect("equal")
#ax.plot_wireframe(x, y, z, color="k") #not needed?!
plt.savefig(__file__+".png")
plt.show()

这篇关于热图半球图的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆