带有用户输入的 Pymol 的 Python 脚本

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

我为 Pymol 准备了一个脚本,它可以很好地评估感兴趣的蛋白质残基列表的 RMSD 值(目标残基由脚本嵌入命令生成)。但是,我希望实现该脚本以允许用户选择分析的残基。我尝试使用输入功能,但失败。由于代码有点长,我逐步简化了脚本。这样,我最终得到了以下两个脚本:

“测试.py”:

import Bio.PDB
import numpy as np
from pymol import cmd
import os,glob
from LFGA_functions import user_entered

List_tot = user_entered()
print (List_tot)

从“My_function.py”脚本中调用简单的“user_entered”函数:

def user_entered():
    List_res = []
    List_tot = []
    a = input("Please indicate the number of residues to analyze/per monomer:")
    numberRes =int(a)
    for i in range(numberRes):
        Res = input("Please provide each residue NUMBER and hit ENTER:")
        Res1 = int(Res)
        Res2 = Res1+2000
        Res3 = Res1+3000
        Res4 = Res1+4000
        Res5 = Res1+5000
        Res6 = Res1+6000
        List_res = (str(Res1),str(Res2),str(Res3),str(Res4),str(Res5),str(Res6))
        List_tot.append(List_res)
    return List_tot

脚本“test.py”在 Windows 命令行中由 Python(3.7.5,与 Pymol 2.3.4 一起安装,在 Windows 7 Prof 下安装)执行时运行良好。结果示例: [首先输入表示将治疗2个病例,然后输入每个病例的识别号][1]

但是,当从 Pymol GUI 运行脚本时,我收到以下错误消息: input():lost sys.stdin

有人知道问题出在哪里吗?显然,我是一个非常原始的Python用户...

我也受益于询问与这个问题相关的问题......在 Pymol 中运行良好的原始脚本中,在尝试实现“输入”选项之前,我以表单暂时存储一些数据(残基名称、类型和链)一个“集合”。我需要一个集合,而不是一个列表,因为它会自动删除数据重复。然而,当我尝试从 PYthon 运行它时(考虑克服上述输入问题),它会停止并显示一条消息:名称“close_to_A”未定义。然而,它如下面所示的代码部分所示,并且确实可以在 Pymol 中工作。

...
# Step 3: 
# listing of residues sufficiently close to chainA
# that will be considered in calculation of RMSD during trajectory

cmd.load("%s/%s" %(path3,"Average.pdb"), "Average", quiet=0)
cmd.select("around_A", "Average and chain B+C near_to 5 of chain A")
cmd.select("in_A", "Average and chain A near_to 5 of chain B+C")
close_to_A = set()
cmd.iterate("(around_A)","close_to_A.add((chain,resi,resn))")
cmd.iterate("(in_A)","close_to_A.add((chain,resi,resn))")
cmd.delete("around_A")
cmd.delete("in_A")
...

如何在 Python 3 中定义集合?为什么从 Pymol 运行时它可以工作?

如果您能帮助我解决这两个问题,我将非常感激。预先感谢您,

致以诚挚的问候,

路易斯

set user-input python-3.7 pymol
1个回答
0
投票

我尝试在 pymol 脚本中获取用户输入(

cmd.run(script.py)
或从 FileMenu/Run 脚本...),我没有收到您的错误,但来自控制台的输入与 pymol 标准输出混合在一起。根据 M.Peters 的建议,我采用了插件方法。我的尝试如下:

'''
PyMOL .............................. Plugin

'''


"""
https://stackoverflow.com/questions/15849567/pyqt-how-can-i-change-the-texts-of-my-qinputdialog-buttons

The QInputDialog itself contains methods setOkButtonText and setCancelButtonText, however, the static method gitInt you are 
using creates a QInputDialog object, which is visible only inside the getInt method and is not accessible to you.

I would suggest to create your own InputIntegerDialog(QtGui.QInputDialog), on which you'll have to manually add a s
pinBox and set its properties. You would then be able to change text on both buttons, because the dialog object is 
under your control, not created somewhere inside PyQt.

"""


from pymol.Qt import QtWidgets , QtGui

def __init_plugin__(app=None):
    '''
    Add an entry to the PyMOL "Plugin" menu
    '''
    from pymol.plugins import addmenuitemqt
    
    addmenuitemqt('Plug', run_plugin_gui)

#### ATTENZIONE A GLOBAL DIALOG SUPER NECESSARIO ############
# global reference to avoid garbage collection of our dialog
dialog = None


def run_plugin_gui():
    '''
    Open our custom dialog
    '''
    
    global dialog

    if dialog is None:
        dialog = make_dialog()

    dialog.show()
    


 
class Window(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(Window, self).__init__(parent)
        
        self.setGeometry(100,100,400,400)
           
        self.Winlayout = QtWidgets.QVBoxLayout()
        
        self.setLayout(self.Winlayout)
        
        self.button_start = QtWidgets.QPushButton('START')
        
        self.button_print = QtWidgets.QPushButton('PRINT')
        
        self.Winlayout.addWidget(self.button_start)
        
        self.Winlayout.addWidget(self.button_print)
    
        self.button_start.clicked.connect(self.inputz)
        
        self.button_print.clicked.connect(self.printz)
        
        self.List_tot = []
        
        self.List_res = []
        
        self.flag = {}
        
        
    def closeEvent(self, event):
        
        print('cloooooooooooooose') 
        
        event.accept()

        
    def inputz(self):
        
        self.flag['close'] = False
        
        while self.flag['close'] == False :
            
            self.showmydialog()

    def printz(self):
        
        print('\n\n-----------------------------------------------')
        
        print(self.List_res)
        
        self.List_tot = []
        
        for i in range(len(self.List_res)):
            
            Res1 = self.List_res[i]
            Res2 = Res1+2000
            Res3 = Res1+3000
            Res4 = Res1+4000
            Res5 = Res1+5000
            Res6 = Res1+6000
            
            List_app = (str(Res1),str(Res2),str(Res3),str(Res4),str(Res5),str(Res6))
        
            self.List_tot.append(List_app)
            
        print('\n', self.List_tot)
        
    def showmydialog(self):
        dialog = QtWidgets.QInputDialog(self)
        
        dialog.setInputMode(QtWidgets.QInputDialog.IntInput)
        
        dialog.setIntMaximum(2147483647)

        
        dialog.setWindowTitle("INPUT")
        dialog.setLabelText('Please indicate the '+(str(len(self.List_res)+1))+' residues numbers :')
        dialog.setOkButtonText("OK")                         
        dialog.setCancelButtonText("CLOSE")                   #
        if dialog.exec_() == QtWidgets.QDialog.Accepted:
            
            inpt = dialog.intValue()
            
            self.List_res.append(inpt)
            
        else:
            
            print('input finished , lenght List = ', (len(self.List_res)))
            
            self.flag['close'] = True
        
def make_dialog():

    dialog = Window()
    
    return dialog

我不要求用户提供残基数量

请注明要分析的残基数/每个单体,

但只要让用户输入任意数量的数字,直到他点击

CLOSE
按钮,您就会得到一个结果列表。仅使用
QInputDialog.getInt
会节省很多行,但最终您会得到一个
CANCEL
按钮而不是
CLOSE
,这可能会产生误导(请参阅操作系统代码开头的注释)。

有关如何安装插件,请参阅 [https://pymolwiki.org/index.php/Plugins][1]。

[![在此处输入图像描述][2]][2]

START打开输入小部件,PRINT打印您的输入派生列表*

*列表在多次 START 运行之间不会重置。

[![在此处输入图像描述][3]][3]

OK 将值存储在列表中,CLOSE 结束输入会话


至于第二个问题,不确定我是否正确,但尝试一下:

from pymol import(
                  cmd
                  stored
                  )

stored.close_to_A = set()

参见 [https://pymolwiki.org/index.php/Pymol.stored][4]

pymol.stored 辅助变量充当用户定义的全局变量的命名空间,可以通过类似迭代的命令访问这些全局变量。默认情况下,迭代命令将 pymol 模块名称空间公开为全局字典,因此 pymol.stored 可以作为stored访问,(用户定义的)成员可以作为stored.membername访问。



  [1]: https://pymolwiki.org/index.php/Plugins
  [2]: https://i.stack.imgur.com/k2tu7.png
  [3]: https://i.stack.imgur.com/wnAsx.png
  [4]: https://pymolwiki.org/index.php/Pymol.stored
© www.soinside.com 2019 - 2024. All rights reserved.