Python - 在网格

时间:2015-12-21 13:58:19

标签: python matplotlib

我写了一个函数(参见结束),它计算特定顺序和度数的球谐系数,并将它们绘制在球体上。

我想将几个这些球体组合在一个网格中。我希望最终结果类似于此enter image description here

我尝试使用plt.subplots和plt.gridSpec两个图表无济于事。它总是最终将其他情节放在外面。这是我尝试过的代码:

fig, axes = plt.subplots(ncols=1, nrows=2)
ax1, ax2 = axes.ravel()
ax1.plot(sh(6,6))
ax2.plot(sh(7,7))
plt.show()

我得到了下图:

enter image description here

和追溯@第3行:

  

ValueError:x和y不能为None

此外,

### GridSpec ####
plt.subplot2grid((2,2), (0,0))
sh(7,7)
plt.subplot2grid((2,2), (1, 0))
sh(8,7)
plt.subplot2grid((2,2), (1, 1))
sh(9,7)
plt.show()

产生3个独立的(非网格)图。

这是一个更好的结果,但第三个球体应位于第二个球体的右侧,除非我做错了什么。 注意:sh()是我写的函数,用于计算球面谐波用球面谐波投影绘制球体。换句话说,我在这里有2个球。我想要做的就是将两个(实际上更多)球体组合成一个像上面那样的网格。

PS:我曾尝试与Mayavi合作,但我无法使其发挥作用。网站上的所有代码对我都不起作用。我稍后会重新检查,但我现在很紧张,所以我写了自己的功能。

我写的功能:

def sh(l,m,cent_lat,cent_lon):
    # function that calculates the spherical harmonics of order l and degree m and visualizes it on a
    # sphere centered at (cent_lat, cent_lon) given in degrees

    if l < m:
        print "Order cannot be smaller than the degree! Try again."
    else:

        import numpy as np
        import scipy.special as sp
        from math import pi
        import matplotlib.cm as cm
        from mpl_toolkits.basemap import Basemap
        import matplotlib.pyplot as plt

        res = pi/100 # resolution
        theta = np.r_[0:2*pi:res]; phi = np.r_[0:pi:res] # theta: lon, phi: coalt

        coef = []
        for i in theta:
            for j in phi:
                coef.append(sp.sph_harm(m,l,i,j))
        coef = np.asarray(coef) # convert list to array
        coef = np.reshape(coef, (len(theta),-1)) # reshapte array as per number of angles


        ## Plotting ##

        # create lat/lon arrays
        lon = np.linspace(0,2*pi,len(theta))
        lat = np.linspace(-pi/2,pi/2,len(phi))
        colat = lat+pi/2 # colatitude array

        # create 2D meshgrid
        mesh_grid = np.meshgrid(lon, lat) # create a meshgrid out of lat/lon
        lon_grid = mesh_grid[0] # grab the meshgrid part for lon
        lat_grid = mesh_grid[1] # grab the meshgrid part for lat

        real_coef = np.real(coef) # read parts of the coefficients
        norm_coef = np.round(real_coef / np.max(real_coef),2) # normalize

        # set up orthographic map projection
        mp = Basemap(projection='ortho', lat_0 = cent_lat, lon_0 = cent_lon) # setup an orthographic basemap centered at lat_0 & lon_0
        # draw the edge of the map projection region (the projection limb)
        mp.drawmapboundary()

        # convert angles from radians to degrees & pipe them to basemap
        x,y = mp(np.degrees(lon_grid), np.degrees(lat_grid)) 

        cmap = cm.get_cmap('jet') # Set color map
        mp.pcolor(x,y,np.transpose(norm_coef), cmap=cmap)
        # cax = figure.add_axes([0.15,0.03,0.7,0.03])
#         cb = plt.colorbar(orientation = 'horizontal')
        plt.show()

感谢任何帮助。

1 个答案:

答案 0 :(得分:3)

GridSpec适用于我(matplotlib v1.5.0,如果重要的话):

import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from matplotlib.colors import LightSource
import matplotlib.cm as cm

import matplotlib.gridspec as gridspec

import numpy as np


u = np.linspace(0, 2 * np.pi, 100)
v = np.linspace(0, np.pi, 100)

x = 10 * np.outer(np.cos(u), np.sin(v))
y = 10 * np.outer(np.sin(u), np.sin(v))
z = 10 * np.outer(np.ones(np.size(u)), np.cos(v))

ls = LightSource(270, 45)
rgb = ls.shade(z, cmap=cm.gist_earth, vert_exag=0.1, blend_mode='soft')


def plot_sphere(s):

    s.plot_surface(x, y, z, rstride=4, cstride=4, facecolors=rgb,
                           linewidth=0, antialiased=False, shade=False)

    s.w_xaxis.set_pane_color((1.0, 1.0, 1.0, 0.0))
    s.w_yaxis.set_pane_color((1.0, 1.0, 1.0, 0.0))
    s.w_zaxis.set_pane_color((1.0, 1.0, 1.0, 0.0))

    s.w_xaxis.line.set_color((1.0, 1.0, 1.0, 0.0))
    s.w_yaxis.line.set_color((1.0, 1.0, 1.0, 0.0))
    s.w_zaxis.line.set_color((1.0, 1.0, 1.0, 0.0))

    s.set_xticks([])
    s.set_yticks([])
    s.set_zticks([])


fig = plt.figure()

gs = gridspec.GridSpec(6, 7)

for i in range(6):
    for j in range(6):
        if i >= j:
            s = fig.add_subplot(gs[i,j+1], projection='3d')
            plot_sphere(s)


for i in range(6):

    pos = gs[i,0].get_position(fig)
    fig.text(pos.x0, (pos.y0 + pos.y1) / 2, "$\\ell = " + str(i) + "$", fontsize=16)

fig.savefig('t.png')

enter image description here