测量每个状态下两个原子之间的距离,以 pymol 为单位

问题描述 投票:0回答:1

我正在使用 Pymol 来测量核酸两个原子之间的距离。我有一个 pdb。分子动力学计算的文件。当我在 pymol 中打开该文件时,我有该分子的多种状态。我想测量两个特定原子之间以及每个状态的距离,并将距离导出到文件中。然后我可以可视化距离的分布。任何人都可以建议一种使用 pymol 执行此操作的方法吗?

python bioinformatics pymol
1个回答
1
投票

我的尝试,使用

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 的文章:

在 PyMOL 会话中创建一个新的 Tk 窗口/线程并在其上输出 matplotlib 图形

© www.soinside.com 2019 - 2024. All rights reserved.