我正在使用 Pymol 来测量核酸两个原子之间的距离。我有一个 pdb。分子动力学计算的文件。当我在 pymol 中打开该文件时,我有该分子的多种状态。我想测量两个特定原子之间以及每个状态的距离,并将距离导出到文件中。然后我可以可视化距离的分布。任何人都可以建议一种使用 pymol 执行此操作的方法吗?
我的尝试,使用
1m82.pdb
作为示例分子进行编码,并且
distance("dist_1m82" , "/1m82/A/A/U`22/P" , "/1m82/A/A/U`22/N1" , mode = 0)
作为距离命令(如果您不想/不需要创建距离对象,可以使用 get_distance
:
#!/usr/bin/env python3
import pymol
from pymol import (
cmd ,
)
pdb_code = '1m82'
print('########## PYMOL VERSION ##########################################')
print(' ', cmd.get_version() )
print('###################################################################')
pymol.finish_launching()
# cmd.feedback("enable" , "all" , "blather")
cmd.set('internal_gui_width' , '500')
# cmd.load('1m82.pdb' , '1m82' , state = 0)
cmd.fetch(pdb_code , pdb_code , state = 0 , quiet = 0 , async_ = 0)
number_of_states = cmd.count_states(pdb_code)
print('states_count -----> ' , number_of_states)
cmd.split_states(pdb_code)
cmd.sync()
cmd.delete(pdb_code)
distances = []
for state_num in range(1, number_of_states + 1):
obj_name = pdb_code+ "_" + str(state_num).zfill(4)
## PyMOLWiki doesnt show default mode number for distance command https://pymolwiki.org/index.php/Distance
dis = cmd.distance("dist_"+obj_name , '/'+obj_name+"/A/A/U`22/P" , '/'+obj_name+"/A/A/U`22/N1" , mode = 0)
distances.append(('dist_'+obj_name , dis))
print('\n ---------\n')
for dist in distances:
print(dist)
输出:
########## PYMOL VERSION ##########################################
('2.3.0' ....
states_count -----> 31
---------
('dist_1m82_0001', 5.300721168518066)
('dist_1m82_0002', 5.251534938812256)
('dist_1m82_0003', 5.176976203918457)
('dist_1m82_0004', 5.227502822875977)
('dist_1m82_0005', 4.940760135650635)
('dist_1m82_0006', 5.036609649658203)
('dist_1m82_0007', 5.408339977264404)
('dist_1m82_0008', 5.204244613647461)
('dist_1m82_0009', 5.257850646972656)
('dist_1m82_0010', 5.196445941925049)
('dist_1m82_0011', 5.122419357299805)
('dist_1m82_0012', 5.103713512420654)
('dist_1m82_0013', 5.154935836791992)
('dist_1m82_0014', 5.303188323974609)
('dist_1m82_0015', 5.011679649353027)
('dist_1m82_0016', 5.331982612609863)
('dist_1m82_0017', 5.318058967590332)
('dist_1m82_0018', 5.257812023162842)
('dist_1m82_0019', 5.262117385864258)
('dist_1m82_0020', 5.251483917236328)
('dist_1m82_0021', 5.132598400115967)
('dist_1m82_0022', 5.1809163093566895)
('dist_1m82_0023', 5.067441463470459)
('dist_1m82_0024', 5.514594078063965)
('dist_1m82_0025', 5.220001697540283)
('dist_1m82_0026', 5.40653133392334)
('dist_1m82_0027', 5.2190141677856445)
('dist_1m82_0028', 5.212803363800049)
('dist_1m82_0029', 5.346554279327393)
('dist_1m82_0030', 5.3021650314331055)
('dist_1m82_0031', 5.262298107147217)
图片,距离绘制为浅黄色虚线:
根据
然后我可以可视化距离分布
你的问题的一部分,我需要创建一个
.py
文件,例如:
runnable.py
:
#!/usr/bin/env python3
import matplotlib.pyplot as plt
y = [i[1] for i in stored.distances]
print('\n\ny : \n' , y ,'\n\n')
fig, axs = plt.subplots()
axs.hist(y , bins = 5)
plt.show()
然后在我的第一个脚本的末尾添加以下几行:
stored.distances = distances
cmd.do('run runnable.py')
当然
runnable.py
与我的主脚本位于同一文件夹中
这将为您提供一个额外的窗口,一个像这样的 matplotlib 窗口:
在哪里,需要检查你会发现计算距离的分布。
不幸的是,您也会收到错误,最好是警告,例如:
runnable.py:17: UserWarning: Starting a Matplotlib GUI outside of the main thread will likely fail.
fig, axs = plt.subplots()
runnable.py:21: UserWarning: Starting a Matplotlib GUI outside of the main thread will likely fail.
.....
....and many other lines.....
但至少它会跑得快。
尝试将
runnable.py
放入主脚本中或恢复使用:
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg
将导致:
QObject: Cannot create children for a parent that is in a different thread.
(Parent is ........, parent's thread is QThread(0x7fa9a800cd40), current thread is QThread(0x30374d0)
QObject::installEventFilter(): Cannot filter events for objects in a different thread.
窗口显示右侧的直方图(上面的那个),此时,
pymol
窗口加载速度非常慢,并且发送消息的时间超过数十次。
我想第二部分需要更多时间来回答。
附录
将
runnable.py
重新定义为 runnable_2.py
以便我的脚本带有:
stored.distances = distances
cmd.do('run runnable_2.py')
和
runnable_2.py
,复制并改编自 https://www.pythonguis.com/tutorials/plotting-matplotlib/is:
import matplotlib
matplotlib.use('Qt5Agg')
# from PyQt5 import QtCore, QtWidgets
from pymol.Qt import QtWidgets, QtCore
print('\n\n###################################\n')
print(' QtCore.qVersion( ---> ' ,QtCore.qVersion())
print('\n\n###################################\n')
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg
from matplotlib.figure import Figure
class MplCanvas(FigureCanvasQTAgg):
def __init__(self, parent=None, width=5, height=4, dpi=100):
fig = Figure(figsize=(width, height), dpi=dpi)
self.axes = fig.add_subplot(111)
super(MplCanvas, self).__init__(fig)
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, values , *args, **kwargs):
super(MainWindow, self).__init__(*args, **kwargs)
self.y = values
# Create the maptlotlib FigureCanvas object,
# which defines a single set of axes as self.axes.
sc = MplCanvas(self, width=5, height=4, dpi=100)
sc.axes.hist(self.y , bins = 5)
self.setCentralWidget(sc)
self.show()
# matplotlib.plot.show()
y = [i[1] for i in stored.distances]
w = MainWindow(y)
我得到了上面描述的直方图(现在是一个 PyMOL 窗口,而不是 matplotlib 窗口),没有任何错误。
在主脚本中使用
from pymol.Qt import QtWidgets, QtCore
和 runnable_2.py
QWidgets(所以不是由 cmd.do('run
启动,...)`
一直缓慢地呈现直方图并带有:
QObject: Cannot create children for a parent that is in a different thread.
(Parent is ...........), parent's thread is QThread(0x7f5ddc00cd40), current thread is QThread(0x30ae7b0)
QObject::installEventFilter(): Cannot filter events for objects in a different thread.
QObject::installEventFilter(): Cannot filter events for objects in a different thread.
我想我错过了类似这篇关于使用 PyQt 的 pymol 的文章: