我试图在循环反应中对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()
给了我:
此方法的问题包括:
有没有人知道解决这些问题的好方法?
我尝试使用mpl_toolkits.mplot3d.art3d.Poly3DCollection
手动生成曲面,但只是很少记录。