使用matplotlib绘制圆形3d条(圆盘)

时间:2014-10-02 14:28:25

标签: python matplotlib mplot3d

我试图在循环反应中对reaction barriers进行图形化可视化(参见citric acid cycle)。

我有两个反应路径的障碍,通过不同的方式关闭相同的反应循环 路径。对于这个用例,简单的2D绘图变得不直观,因此我给了matplotlib的Axes3D对象一个镜头:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

from __future__ import (absolute_import, division,
                        print_function, unicode_literals)

from math import sin, cos

import numpy as np

from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
from matplotlib import cm


def z_cycle(mesh, origin, cycle, r, angle_offset, ring_width=0.5):
    disc_radius = r/(len(cycle)+1)
    angles = np.linspace(0, 2*np.pi, len(cycle), endpoint=False)+angle_offset
    mesh_x, mesh_y = mesh
    xo, yo = origin
    z = np.zeros_like(mesh_x)
    for a, d in zip(angles, cycle):
        xc, yc = xo + r/2*cos(a), yo + r/2*sin(a)
        z += d*((mesh_x-xc)**2 + (mesh_y-yc)**2 < (0.2*r)**2)
    z0_mask = np.where(z == 0)
    ring = np.logical_and(
        (mesh_x-xo)**2+(mesh_y-yo)**2 < (r/2+ring_width/2*disc_radius)**2,
        (mesh_x-xo)**2+(mesh_y-yo)**2 > (r/2-ring_width/2*disc_radius)**2
    )
    z += min(cycle)/2*ring*(z == 0)
    return z


def main(data='1,3,2,4,3,4,2;1,3,1.5,2', r=1.0):
    """
    Plot energy barriers for reaction cycles in 3d

    Cycles as separated by semicolon, and individual
    barrier heights are separated by comma. Cycles need
    to share the value of their respective first barrier height.
    """

    max_barrier = None
    cycles = []
    max_ = lambda a, b: max(a, b) if b is not None else a
    for cycle_string in data.split(';'):
        cycle = []
        for barrier in map(float, cycle_string.split(',')):
            max_barrier = max_(barrier, max_barrier)
            cycle.append(barrier)
        cycles.append(cycle)

    assert all(cycle[0] == cycles[0][0] for cycle in cycles[1:])

    grid1d = np.linspace(-2*r, 2*r, 200)
    mesh_x, mesh_y = mesh = np.meshgrid(grid1d, grid1d)
    mesh_z = np.zeros_like(mesh_x)

    angles = np.linspace(0, 2*np.pi, len(cycles), endpoint=False)
    for angle, cycle in zip(angles, cycles):
        # cycle is an iterable of numerical values corresponding to
        # barrier heights
        disc_radius = r/(len(cycle)+1)
        centre = ((r/2+disc_radius)*cos(angle), (r/2+disc_radius)*sin(angle))
        mesh_z += z_cycle(mesh, centre, cycle, r, np.pi+angle)

    # Plot
    fig = plt.figure()
    ax = fig.gca(projection='3d')
    ax.plot_surface(mesh_x, mesh_y, mesh_z, rstride=1, cstride=1,
                    cmap=cm.coolwarm, linewidths=0)

    plt.savefig('barriers3d.png')
    plt.show()

if __name__ == '__main__':
    main()

给了我:

cyclic circular 3dbar plot

此方法的问题包括:

  • 由于需要非常密集的网格而导致性能不佳(旋转成为慢速)
  • 图形文物

有没有人知道解决这些问题的好方法?

我尝试使用mpl_toolkits.mplot3d.art3d.Poly3DCollection手动生成曲面,但只是很少记录。

0 个答案:

没有答案