MayaChemTools

    1 #!/bin/env python
    2 #
    3 # File: PyMOLVisualizeFpockets.py
    4 # Author: Manish Sud <msud@san.rr.com>
    5 #
    6 # Author: Manish Sud
    7 #
    8 # Collaborators: Joann Prescott-Roy and Pat Walters
    9 #
   10 # Copyright (C) 2024 Manish Sud. All rights reserved.
   11 #
   12 # The functionality available in this script is implemented using PyMOL, a
   13 # molecular visualization system on an open source foundation originally
   14 # developed by Warren DeLano.
   15 #
   16 # This file is part of MayaChemTools.
   17 #
   18 # MayaChemTools is free software; you can redistribute it and/or modify it under
   19 # the terms of the GNU Lesser General Public License as published by the Free
   20 # Software Foundation; either version 3 of the License, or (at your option) any
   21 # later version.
   22 #
   23 # MayaChemTools is distributed in the hope that it will be useful, but without
   24 # any warranty; without even the implied warranty of merchantability of fitness
   25 # for a particular purpose.  See the GNU Lesser General Public License for more
   26 # details.
   27 #
   28 # You should have received a copy of the GNU Lesser General Public License
   29 # along with MayaChemTools; if not, see <http://www.gnu.org/licenses/> or
   30 # write to the Free Software Foundation Inc., 59 Temple Place, Suite 330,
   31 # Boston, MA, 02111-1307, USA.
   32 #
   33 #
   34 
   35 from __future__ import print_function
   36 
   37 # Add local python path to the global path and import standard library modules...
   38 import os
   39 import sys;  sys.path.insert(0, os.path.join(os.path.dirname(sys.argv[0]), "..", "lib", "Python"))
   40 import time
   41 import re
   42 import glob
   43 import shutil
   44 
   45 # PyMOL imports...
   46 try:
   47     import pymol
   48     # Finish launching PyMOL in  a command line mode for batch processing (-c)
   49     # along with the following options:  disable loading of pymolrc and plugins (-k);
   50     # suppress start up messages (-q)
   51     pymol.finish_launching(['pymol', '-ckq'])
   52 except ImportError as ErrMsg:
   53     sys.stderr.write("\nFailed to import PyMOL module/package: %s\n" % ErrMsg)
   54     sys.stderr.write("Check/update your PyMOL environment and try again.\n\n")
   55     sys.exit(1)
   56 
   57 # MayaChemTools imports...
   58 try:
   59     from docopt import docopt
   60     import MiscUtil
   61     import PyMOLUtil
   62 except ImportError as ErrMsg:
   63     sys.stderr.write("\nFailed to import MayaChemTools module/package: %s\n" % ErrMsg)
   64     sys.stderr.write("Check/update your MayaChemTools environment and try again.\n\n")
   65     sys.exit(1)
   66 
   67 ScriptName = os.path.basename(sys.argv[0])
   68 Options = {}
   69 OptionsInfo = {}
   70 
   71 def main():
   72     """Start execution of the script"""
   73     
   74     MiscUtil.PrintInfo("\n%s (PyMOL v%s; MayaChemTools v%s; %s): Starting...\n" % (ScriptName, pymol.cmd.get_version()[0], MiscUtil.GetMayaChemToolsVersion(), time.asctime()))
   75     
   76     (WallClockTime, ProcessorTime) = MiscUtil.GetWallClockAndProcessorTime()
   77     
   78     # Retrieve command line arguments and options...
   79     RetrieveOptions()
   80     
   81     # Process and validate command line arguments and options...
   82     ProcessOptions()
   83 
   84     # Perform actions required by the script...
   85     GenerateFpocketsVisualization()
   86     
   87     MiscUtil.PrintInfo("\n%s: Done...\n" % ScriptName)
   88     MiscUtil.PrintInfo("Total time: %s" % MiscUtil.GetFormattedElapsedTime(WallClockTime, ProcessorTime))
   89 
   90 def GenerateFpocketsVisualization():
   91     """Generate fpockets visualization."""
   92     
   93     Outfile = OptionsInfo["PMLOutfilePath"]
   94     OutFH = open(Outfile, "w")
   95     if OutFH is None:
   96         MiscUtil.PrintError("Failed to open output fie %s " % Outfile)
   97     
   98     MiscUtil.PrintInfo("\nGenerating file %s..." % Outfile)
   99     
  100     # Setup header...
  101     WritePMLHeader(OutFH, ScriptName)
  102     WritePyMOLParameters(OutFH)
  103     
  104     if OptionsInfo["Align"]:
  105         WriteAlignReference(OutFH)
  106     
  107     # Setup view for each input file...
  108     FirstComplex = True
  109     FirstComplexFirstChainName = None
  110     for FileIndex in range(0, len(OptionsInfo["InfilesInfo"]["InfilesNames"])):
  111         # Setup PyMOL object names...
  112         PyMOLObjectNames = SetupPyMOLObjectNames(FileIndex)
  113         
  114         # Setup complex view...
  115         WriteComplexView(OutFH, FileIndex, PyMOLObjectNames, FirstComplex)
  116 
  117         # Setup chain and pocket views...
  118         SpecifiedChainsAndPocketsInfo = OptionsInfo["FpocketInfilesInfo"]["SpecifiedChainsAndPocketsInfo"][FileIndex]
  119         FirstChain = True
  120         for ChainID in SpecifiedChainsAndPocketsInfo["ChainIDs"]:
  121             if FirstComplex and FirstChain:
  122                 FirstComplexFirstChainName = PyMOLObjectNames["Chains"][ChainID]["ChainAlone"]
  123             
  124             WriteChainView(OutFH, FileIndex, PyMOLObjectNames, ChainID)
  125 
  126             # Setup fpocket views...
  127             FirstPocket = True
  128             PocketNum = 0
  129             for PocketID in SpecifiedChainsAndPocketsInfo["PocketIDs"][ChainID]:
  130                 PocketNum += 1
  131                 WriteChainPocketView(OutFH, FileIndex, PyMOLObjectNames, ChainID, PocketID, PocketNum)
  132                 
  133                 # Set up pocket level group...
  134                 Enable, Action = [False, "close"]
  135                 if FirstPocket:
  136                     FirstPocket = False
  137                     Enable, Action = [True, "open"]
  138                 GenerateAndWritePMLForGroup(OutFH, PyMOLObjectNames["Pockets"][ChainID][PocketID]["ChainPocketGroup"], PyMOLObjectNames["Pockets"][ChainID][PocketID]["ChainPocketGroupMembers"], Enable, Action)
  139                 
  140             # Setup Chain level group...
  141             Enable, Action = [False, "close"]
  142             if FirstChain:
  143                 FirstChain = False
  144                 Enable, Action = [True, "open"]
  145             GenerateAndWritePMLForGroup(OutFH, PyMOLObjectNames["Chains"][ChainID]["ChainGroup"], PyMOLObjectNames["Chains"][ChainID]["ChainGroupMembers"], Enable, Action)
  146         
  147         # Set up complex level group...
  148         Enable, Action = [False, "close"]
  149         if FirstComplex:
  150             FirstComplex = False
  151             Enable, Action = [True, "open"]
  152         GenerateAndWritePMLForGroup(OutFH, PyMOLObjectNames["PDBGroup"], PyMOLObjectNames["PDBGroupMembers"], Enable, Action)
  153     
  154     if OptionsInfo["Align"]:
  155         DeleteAlignReference(OutFH)
  156     
  157     if FirstComplexFirstChainName is not None:
  158         OutFH.write("""\ncmd.orient("%s", animate = -1)\n""" % FirstComplexFirstChainName)
  159     else:
  160         OutFH.write("""\ncmd.orient("visible", animate = -1)\n""")
  161     
  162     OutFH.close()
  163     
  164     CopyPDBFilesForPML()
  165 
  166 def WritePMLHeader(OutFH, ScriptName):
  167     """Write out PML header."""
  168 
  169     HeaderInfo = PyMOLUtil.SetupPMLHeaderInfo(ScriptName)
  170     OutFH.write("%s\n" % HeaderInfo)
  171 
  172 def WritePyMOLParameters(OutFH):
  173     """Write out PyMOL global parameters. """
  174 
  175     PMLCmds = []
  176     PMLCmds.append("""cmd.set("transparency", %.2f, "", 0)""" % (OptionsInfo["SurfaceTransparency"]))
  177     PMLCmds.append("""cmd.set("label_font_id", %s)""" % (OptionsInfo["LabelFontID"]))
  178     PML = "\n".join(PMLCmds)
  179     
  180     OutFH.write("""\n""\n"Setting up PyMOL gobal parameters..."\n""\n""")
  181     OutFH.write("%s\n" % PML)
  182     
  183 def WriteAlignReference(OutFH):
  184     """Setup object for alignment reference """
  185 
  186     RefFileInfo = OptionsInfo["RefFileInfo"]
  187     RefFile = RefFileInfo["RefFileName"]
  188     RefName = RefFileInfo["PyMOLObjectName"]
  189     
  190     PMLCmds = []
  191     PMLCmds.append("""cmd.load("%s", "%s")""" % (RefFile, RefName))
  192     PMLCmds.append("""cmd.hide("everything", "%s")""" % (RefName))
  193     PMLCmds.append("""cmd.disable("%s")""" % (RefName))
  194     PML = "\n".join(PMLCmds)
  195     
  196     OutFH.write("""\n""\n"Loading %s and setting up view for align reference..."\n""\n""" % RefFile)
  197     OutFH.write("%s\n" % PML)
  198     
  199 def WriteAlignComplex(OutFH, FileIndex, FpocketComplexMode, PyMOLObjectNames):
  200     """Setup alignment of complex to reference"""
  201 
  202     RefFileInfo = OptionsInfo["RefFileInfo"]
  203     RefName = RefFileInfo["PyMOLObjectName"]
  204 
  205     if FpocketComplexMode:
  206         ComplexName = PyMOLObjectNames["FpocketComplex"]
  207     else:
  208         ComplexName = PyMOLObjectNames["InitialComplex"]
  209     
  210     if re.match("^FirstChain$", OptionsInfo["AlignMode"], re.I):
  211         RefFirstChainID = RefFileInfo["ChainsAndLigandsInfo"]["ChainIDs"][0]
  212         RefAlignSelection = "%s and chain %s" % (RefName, RefFirstChainID)
  213         
  214         ComplexFirstChainID = RetrieveFirstChainID(FileIndex, FpocketComplexMode)
  215         ComplexAlignSelection = "%s and chain %s" % (ComplexName, ComplexFirstChainID)
  216     else:
  217         RefAlignSelection = RefName
  218         ComplexAlignSelection = ComplexName
  219 
  220     PML = PyMOLUtil.SetupPMLForAlignment(OptionsInfo["AlignMethod"], RefAlignSelection, ComplexAlignSelection)
  221     OutFH.write("""\n""\n"Aligning %s against reference %s ..."\n""\n""" % (ComplexAlignSelection, RefAlignSelection))
  222     OutFH.write("%s\n" % PML)
  223     
  224 def DeleteAlignReference(OutFH):
  225     """Delete alignment reference object."""
  226     
  227     RefName = OptionsInfo["RefFileInfo"]["PyMOLObjectName"]
  228     OutFH.write("""\n""\n"Deleting alignment reference object %s..."\n""\n""" % RefName)
  229     OutFH.write("""cmd.delete("%s")\n""" % RefName)
  230 
  231 def WriteComplexView(OutFH, FileIndex, PyMOLObjectNames, FirstComplex):
  232     """Write out PML for viewing polymer complex."""
  233 
  234     # Setup initial complex...
  235     Infile = OptionsInfo["InfilesInfo"]["InfilesNames"][FileIndex]
  236     PML = PyMOLUtil.SetupPMLForPolymerComplexView(PyMOLObjectNames["InitialComplex"], Infile, True)
  237     OutFH.write("""\n""\n"Loading %s and setting up view for complex..."\n""\n""" % Infile)
  238     OutFH.write("%s\n" % PML)
  239     
  240     if OptionsInfo["Align"]:
  241         # No need to align initial complex on to itself...
  242         FpocketComplexMode = False
  243         if not (re.match("^FirstInputFile$", OptionsInfo["AlignRefFile"], re.I) and FirstComplex):
  244             WriteAlignComplex(OutFH, FileIndex, FpocketComplexMode, PyMOLObjectNames)
  245     
  246     # Setup fpocket complex...
  247     Infile = OptionsInfo["FpocketInfilesInfo"]["InfilesNames"][FileIndex]
  248     PML = PyMOLUtil.SetupPMLForPolymerComplexView(PyMOLObjectNames["FpocketComplex"], Infile, True)
  249     
  250     # Modify default complex view for fpocket complex...
  251     PMLModify = SetupPMLModifyDefaultPolymerComplexView(PyMOLObjectNames["FpocketComplex"])
  252     
  253     OutFH.write("""\n""\n"Loading %s and setting up view for complex..."\n""\n""" % Infile)
  254     OutFH.write("%s\n%s\n" % (PML, PMLModify))
  255     
  256     if OptionsInfo["Align"]:
  257         # No need to align initial complex on to itself...
  258         FpocketComplexMode = True
  259         if not (re.match("^FirstInputFile$", OptionsInfo["AlignRefFile"], re.I) and FirstComplex):
  260             WriteAlignComplex(OutFH, FileIndex, FpocketComplexMode, PyMOLObjectNames)
  261     
  262     # Setup complex group...
  263     GenerateAndWritePMLForGroup(OutFH, PyMOLObjectNames["ComplexGroup"], PyMOLObjectNames["ComplexGroupMembers"], False, "close")
  264 
  265 def WriteChainView(OutFH, FileIndex, PyMOLObjectNames, ChainID):
  266     """Write out PML for viewing chain."""
  267     
  268     OutFH.write("""\n""\n"Setting up views for chain %s..."\n""\n""" % ChainID)
  269     
  270     ChainComplexName = PyMOLObjectNames["Chains"][ChainID]["ChainComplex"]
  271     
  272     # Setup chain complex group view...
  273     WriteChainComplexViews(OutFH, FileIndex, PyMOLObjectNames, ChainID)
  274     
  275     # Setup chain view...
  276     WriteChainAloneViews(OutFH, FileIndex, PyMOLObjectNames, ChainID)
  277 
  278 def WriteChainComplexViews(OutFH, FileIndex, PyMOLObjectNames, ChainID):
  279     """Write chain complex views. """
  280     
  281     # Setup chain complex...
  282     ChainComplexName = PyMOLObjectNames["Chains"][ChainID]["ChainComplex"]
  283     PML = SetupPMLForFpocketChainComplexView(FileIndex, ChainComplexName, PyMOLObjectNames["FpocketComplex"], ChainID, True)
  284     
  285     # Modify default complex view for fpocket chain complex...
  286     PMLModify = SetupPMLModifyDefaultPolymerComplexView(ChainComplexName)
  287     OutFH.write("%s\n%s\n" % (PML, PMLModify))
  288 
  289     # Setup chain complex group...
  290     GenerateAndWritePMLForGroup(OutFH, PyMOLObjectNames["Chains"][ChainID]["ChainComplexGroup"], PyMOLObjectNames["Chains"][ChainID]["ChainComplexGroupMembers"], False, "close")
  291 
  292 def WriteChainAloneViews(OutFH, FileIndex, PyMOLObjectNames, ChainID):
  293     """Write individual chain views. """
  294 
  295     ChainComplexName = PyMOLObjectNames["Chains"][ChainID]["ChainComplex"]
  296     
  297     # Setup chain view...
  298     ChainName = PyMOLObjectNames["Chains"][ChainID]["ChainAlone"]
  299     PML = PyMOLUtil.SetupPMLForPolymerChainView(ChainName, ChainComplexName, True)
  300     OutFH.write("\n%s\n" % PML)
  301     
  302     if GetChainAloneContainsSurfacesStatus(FileIndex, ChainID):
  303         # Setup a generic color surface...
  304         PML = PyMOLUtil.SetupPMLForSurfaceView(PyMOLObjectNames["Chains"][ChainID]["ChainAloneSurface"], ChainName,  Enable = False, Color = OptionsInfo["SurfaceColor"])
  305         OutFH.write("\n%s\n" % PML)
  306         
  307         if GetChainAloneSurfaceChainStatus(FileIndex, ChainID):
  308             # Setup surface colored by hydrophobicity...
  309             PML = PyMOLUtil.SetupPMLForHydrophobicSurfaceView(PyMOLObjectNames["Chains"][ChainID]["ChainAloneHydrophobicSurface"], ChainName, ColorPalette = OptionsInfo["SurfaceColorPalette"], Enable = False)
  310             OutFH.write("\n%s\n" % PML)
  311             
  312             # Setup surface colored by hyrdophobicity and charge...
  313             PML = PyMOLUtil.SetupPMLForHydrophobicAndChargeSurfaceView(PyMOLObjectNames["Chains"][ChainID]["ChainAloneHydrophobicChargeSurface"], ChainName, OptionsInfo["AtomTypesColorNames"]["HydrophobicAtomsColor"], OptionsInfo["AtomTypesColorNames"]["NegativelyChargedAtomsColor"], OptionsInfo["AtomTypesColorNames"]["PositivelyChargedAtomsColor"], OptionsInfo["AtomTypesColorNames"]["OtherAtomsColor"], Enable = False, DisplayAs = None)
  314             OutFH.write("\n%s\n" % PML)
  315         
  316         # Setup surface group...
  317         GenerateAndWritePMLForGroup(OutFH, PyMOLObjectNames["Chains"][ChainID]["ChainAloneSurfaceGroup"], PyMOLObjectNames["Chains"][ChainID]["ChainAloneSurfaceGroupMembers"], True, "open")
  318     
  319     # Setup chain group...
  320     GenerateAndWritePMLForGroup(OutFH, PyMOLObjectNames["Chains"][ChainID]["ChainAloneGroup"], PyMOLObjectNames["Chains"][ChainID]["ChainAloneGroupMembers"], True, "close")
  321 
  322 def WriteChainPocketView(OutFH, FileIndex, PyMOLObjectNames, ChainID, PocketID, PocketNum):
  323     """Write out PML for viewing pocket in a chain."""
  324 
  325     OutFH.write("""\n""\n"Setting up views for pocket %s in chain %s..."\n""\n""" % (PocketID, ChainID))
  326     
  327     FpocketComplexName = PyMOLObjectNames["FpocketComplex"]
  328     
  329     # Setup pocket...
  330     PML = SetupPMLForFPocketView(PyMOLObjectNames["Pockets"][ChainID][PocketID]["Pocket"], FpocketComplexName, ChainID, PocketID, PocketNum, True)
  331     OutFH.write("%s\n" % PML)
  332     
  333     # Setup pocket residues...
  334     ChainsAndPocketsInfo = OptionsInfo["FpocketInfilesInfo"]["ChainsAndPocketsInfo"][FileIndex]
  335     PocketResNums = ChainsAndPocketsInfo["PocketResNums"][ChainID][PocketID]
  336     PocketResiduesName = PyMOLObjectNames["Pockets"][ChainID][PocketID]["PocketResidues"]
  337     PML = SetupPMLForFPocketResiduesView(PocketResiduesName, FpocketComplexName, ChainID, PocketID, PocketNum, PocketResNums, True)
  338     OutFH.write("%s\n" % PML)
  339 
  340     # Setup pocket surfaces and group...
  341     if GetPocketContainsSurfaceStatus(FileIndex, ChainID, PocketID):
  342         # Setup a generic color surface...
  343         PML = PyMOLUtil.SetupPMLForSurfaceView(PyMOLObjectNames["Pockets"][ChainID][PocketID]["PocketSurface"], PocketResiduesName,  Enable = False, Color = OptionsInfo["SurfaceColor"])
  344         OutFH.write("\n%s\n" % PML)
  345         
  346         if GetPocketSurfaceChainStatus(FileIndex, ChainID, PocketID):
  347             # Setup surface colored by hydrophobicity...
  348             PML = PyMOLUtil.SetupPMLForHydrophobicSurfaceView(PyMOLObjectNames["Pockets"][ChainID][PocketID]["PocketHydrophobicitySurface"], PocketResiduesName, ColorPalette = OptionsInfo["SurfaceColorPalette"], Enable = False)
  349             OutFH.write("\n%s\n" % PML)
  350             
  351             # Setup surface colored by hyrdophobicity and charge...
  352             PML = PyMOLUtil.SetupPMLForHydrophobicAndChargeSurfaceView(PyMOLObjectNames["Pockets"][ChainID][PocketID]["PocketHydrophobicityChargeSurface"], PocketResiduesName, OptionsInfo["AtomTypesColorNames"]["HydrophobicAtomsColor"], OptionsInfo["AtomTypesColorNames"]["NegativelyChargedAtomsColor"], OptionsInfo["AtomTypesColorNames"]["PositivelyChargedAtomsColor"], OptionsInfo["AtomTypesColorNames"]["OtherAtomsColor"], Enable = False, DisplayAs = None)
  353             OutFH.write("\n%s\n" % PML)
  354             
  355         # Setup surface group...
  356         GenerateAndWritePMLForGroup(OutFH, PyMOLObjectNames["Pockets"][ChainID][PocketID]["PocketSurfaceGroup"], PyMOLObjectNames["Pockets"][ChainID][PocketID]["PocketSurfaceGroupMembers"], True, "open")
  357 
  358     # Setup pocket group...
  359     GenerateAndWritePMLForGroup(OutFH, PyMOLObjectNames["Pockets"][ChainID][PocketID]["ChainPocketGroup"], PyMOLObjectNames["Pockets"][ChainID][PocketID]["ChainPocketGroupMembers"], True, "open")
  360 
  361 def SetupPMLForFpocketChainComplexView(FileIndex, Name, Selection, ChainName, Enable = True):
  362     """Setup PML commands for creating a polymer chain complex view
  363     including fockets for the chain."""
  364     
  365     PMLCmds = []
  366     
  367     # Include fpockets as spheres for the chain complex view...
  368     ChainsAndPocketsInfo = OptionsInfo["FpocketInfilesInfo"]["ChainsAndPocketsInfo"][FileIndex]
  369     PocketIDs = ChainsAndPocketsInfo["PocketIDs"][ChainName]
  370     
  371     PMLCmds.append("""cmd.create("%s", "((%s and chain %s) or (%s and (resn STP and resi %s)))")""" % (Name, Selection, ChainName, Selection, "+".join(PocketIDs)))
  372     PMLCmds.append("""cmd.hide("everything", "%s")""" % (Name))
  373     PMLCmds.append("""cmd.show("cartoon", "%s")""" % (Name))
  374     PMLCmds.append("""util.cba(33, "%s", _self = cmd)""" % (Name))
  375     PMLCmds.append("""cmd.show("sticks", "(organic and (%s))")""" % (Name))
  376     
  377     PMLCmds.append("""cmd.show("nonbonded", "(solvent and (%s))")""" % (Name))
  378     PMLCmds.append("""cmd.show("nonbonded", "(inorganic and (%s))")""" % (Name))
  379     
  380     PMLCmds.append("""cmd.show("lines", "%s")""" % (Name))
  381     
  382     PMLCmds.append("""cmd.set_bond("valence", "1", "%s", quiet = 1)""" % (Name))
  383     PMLCmds.append(PyMOLUtil.SetupPMLForEnableDisable(Name, Enable))
  384 
  385     PML = "\n".join(PMLCmds)
  386     
  387     return PML
  388     
  389 def SetupPMLModifyDefaultPolymerComplexView(Name):
  390     """Setup PML to modify default polymer complex view for fpocket. """
  391 
  392     PMLCmds = []
  393     PMLCmds.append("""cmd.hide("lines", "%s")""" % (Name))
  394     PMLCmds.append("""cmd.show("lines", "(polymer and (%s))")""" % (Name))
  395     PMLCmds.append("""cmd.show("lines", "(solvent and (%s))")""" % (Name))
  396     PMLCmds.append("""cmd.show("spheres", "(inorganic and (%s))")""" % (Name))
  397     PMLCmds.append("""cmd.set("sphere_scale", "%s", "(inorganic and (%s))")""" % (OptionsInfo["SphereScale"], Name))
  398     PMLCmds.append("""cmd.set("sphere_transparency", "%s", "(inorganic and (%s))")""" % (OptionsInfo["SphereTransparency"], Name))
  399     
  400     PML = "\n".join(PMLCmds)
  401 
  402     return PML
  403 
  404 def SetupPMLForFPocketView(FpocketName, FpocketComplexName, ChainID, PocketID, PocketNum, Enable = True):
  405     """Setup PML  to visualize fpocket spheres using fpocket complex."""
  406 
  407     PMLCmds = []
  408     PMLCmds.append("""cmd.create("%s", "(%s and (resn STP and resi %s))")""" % (FpocketName, FpocketComplexName, PocketID))
  409     if PocketNum == 1:
  410         # Skip color index of 1: It is set to black. Use pocket one color name...
  411         PMLCmds.append("""cmd.color(%s, "%s")""" % (OptionsInfo["PocketNumOneColor"], FpocketName))
  412     else:
  413         PMLCmds.append("""cmd.color(%s, "%s")""" % (PocketNum, FpocketName))
  414     PMLCmds.append("""cmd.show("spheres", "%s")""" % (FpocketName))
  415     PMLCmds.append("""cmd.set("sphere_scale", "%s", "%s")""" % (OptionsInfo["SphereScale"], FpocketName))
  416     PMLCmds.append("""cmd.set("sphere_transparency", "%s", "%s")""" % (OptionsInfo["SphereTransparency"], FpocketName))
  417     
  418     PMLCmds.append(PyMOLUtil.SetupPMLForEnableDisable(FpocketName, Enable))
  419         
  420     PML = "\n".join(PMLCmds)
  421     return PML
  422 
  423 def SetupPMLForFPocketResiduesView(Name, FpocketComplexName, ChainID, PocketID, PocketNum, PocketResNums, Enable = True):
  424     """Setup PML to visualize fpocket residues."""
  425 
  426     PMLCmds = []
  427     
  428     PMLCmds.append("""cmd.create("%s", "(%s and (chain %s) and (resi %s))")""" % (Name, FpocketComplexName, ChainID, "+".join(PocketResNums)))
  429     PMLCmds.append("""cmd.hide("everything", "%s")""" % (Name))
  430 
  431     # Setup pocket residue labels...
  432     if OptionsInfo["PocketLabel"]:
  433         if OptionsInfo["ThreeLetterPocketLabelType"]:
  434             LabelFormat = '''"%s-%s"%(resn,resi)'''
  435             PMLCmds.append("""cmd.label("(name CA+C1*+C1' and (byres(%s)))", \'\'\'%s\'\'\')""" % (Name, LabelFormat))
  436         else:
  437             PMLCmds.append("""cmd.label("byca(%s)", "oneletter+resi")""" % (Name))
  438                 
  439     PocketColor = OptionsInfo["PocketNumOneColor"] if PocketNum == 1 else PocketNum
  440     
  441     if OptionsInfo["PocketColorByPocketNum"]:
  442         # Setup color of pocket residues...
  443         PMLCmds.append(PyMOLUtil.SetupPMLForDeepColoring(Name, PocketColor))
  444 
  445         # Setup color of pocket residue labels...
  446         PMLCmds.append("""cmd.set("label_color", %s, "%s")""" % (PocketColor, Name))
  447     else:
  448         PMLCmds.append("""util.cbag("%s", _self = cmd)""" % (Name))
  449 
  450     
  451     PMLCmds.append("""cmd.show("lines", "%s")""" % (Name))
  452     
  453     PMLCmds.append(PyMOLUtil.SetupPMLForEnableDisable(Name, Enable))
  454     
  455     PML = "\n".join(PMLCmds)
  456     return PML
  457     
  458 def GenerateAndWritePMLForGroup(OutFH, GroupName, GroupMembers, Enable = False, Action = "close"):
  459     """Generate and write PML for group. """
  460     
  461     PML = PyMOLUtil.SetupPMLForGroup(GroupName, GroupMembers, Enable, Action)
  462     OutFH.write("""\n""\n"Setting up group %s..."\n""\n""" % GroupName)
  463     OutFH.write("%s\n" % PML)
  464 
  465 def WritePMLToCheckAndDeleteEmptyObjects(OutFH, ObjectName, ParentObjectName = None):
  466     """Write PML to check and delete empty PyMOL objects. """
  467     
  468     if ParentObjectName is None:
  469         PML = """CheckAndDeleteEmptyObjects("%s")""" % (ObjectName)
  470     else:
  471         PML = """CheckAndDeleteEmptyObjects("%s", "%s")""" % (ObjectName, ParentObjectName)
  472     
  473     OutFH.write("%s\n" % PML)
  474     
  475 def SetupPyMOLObjectNames(FileIndex):
  476     """Setup hierarchy of PyMOL groups and objects for pocket centric views of
  477     chains and pockets present in input file.
  478     """
  479 
  480     PyMOLObjectNames = {}
  481     PyMOLObjectNames["Chains"] = {}
  482     PyMOLObjectNames["Pockets"] = {}
  483 
  484     # Setup groups and objects for complex...
  485     SetupPyMOLObjectNamesForComplex(FileIndex, PyMOLObjectNames)
  486     
  487     # Setup groups and objects for chains using fpockets info...
  488     SpecifiedChainsAndPocketsInfo = OptionsInfo["FpocketInfilesInfo"]["SpecifiedChainsAndPocketsInfo"][FileIndex]
  489     for ChainID in SpecifiedChainsAndPocketsInfo["ChainIDs"]:
  490         SetupPyMOLObjectNamesForChain(FileIndex, PyMOLObjectNames, ChainID)
  491     
  492         # Setup groups and objects for pocket...
  493         for PocketID in SpecifiedChainsAndPocketsInfo["PocketIDs"][ChainID]:
  494             SetupPyMOLObjectNamesForPocket(FileIndex, PyMOLObjectNames, ChainID, PocketID)
  495         
  496     return PyMOLObjectNames
  497 
  498 def SetupPyMOLObjectNamesForComplex(FileIndex, PyMOLObjectNames):
  499     """Setup groups and objects for complex. """
  500     
  501     PDBFileRoot = OptionsInfo["InfilesInfo"]["InfilesRoots"][FileIndex]
  502 
  503     PDBGroupName = "%s" % PDBFileRoot
  504     PyMOLObjectNames["PDBGroup"] = PDBGroupName
  505     PyMOLObjectNames["PDBGroupMembers"] = []
  506     
  507     ComplexGroupName = "%s.Complex" % PyMOLObjectNames["PDBGroup"]
  508     PyMOLObjectNames["ComplexGroup"] = ComplexGroupName
  509     PyMOLObjectNames["ComplexGroupMembers"] = []
  510     
  511     PyMOLObjectNames["PDBGroupMembers"].append(ComplexGroupName)
  512     
  513     PyMOLObjectNames["InitialComplex"] = "%s.Initial_Complex" % ComplexGroupName
  514     PyMOLObjectNames["FpocketComplex"] = "%s.Fpocket_Complex" % ComplexGroupName
  515     
  516     PyMOLObjectNames["ComplexGroupMembers"].append(PyMOLObjectNames["InitialComplex"])
  517     PyMOLObjectNames["ComplexGroupMembers"].append(PyMOLObjectNames["FpocketComplex"])
  518 
  519 def SetupPyMOLObjectNamesForChain(FileIndex, PyMOLObjectNames, ChainID):
  520     """Setup groups and objects for chain."""
  521     
  522     PDBGroupName = PyMOLObjectNames["PDBGroup"]
  523     
  524     PyMOLObjectNames["Chains"][ChainID] = {}
  525     PyMOLObjectNames["Pockets"][ChainID] = {}
  526     
  527     # Set up chain group and chain objects...
  528     ChainGroupName = "%s.Chain%s" % (PDBGroupName, ChainID)
  529     PyMOLObjectNames["Chains"][ChainID]["ChainGroup"] = ChainGroupName
  530     PyMOLObjectNames["PDBGroupMembers"].append(ChainGroupName)
  531     PyMOLObjectNames["Chains"][ChainID]["ChainGroupMembers"] = []
  532     
  533     # Setup chain complex group and objects...
  534     ChainComplexGroupName = "%s.Complex" % (ChainGroupName)
  535     PyMOLObjectNames["Chains"][ChainID]["ChainComplexGroup"] = ChainComplexGroupName
  536     PyMOLObjectNames["Chains"][ChainID]["ChainGroupMembers"].append(ChainComplexGroupName)
  537 
  538     PyMOLObjectNames["Chains"][ChainID]["ChainComplexGroupMembers"] = []
  539     
  540     Name = "%s.Complex" % (ChainComplexGroupName)
  541     PyMOLObjectNames["Chains"][ChainID]["ChainComplex"] = Name
  542     PyMOLObjectNames["Chains"][ChainID]["ChainComplexGroupMembers"].append(Name)
  543     
  544     # Setup up a group for individual chains...
  545     ChainAloneGroupName = "%s.Chain" % (ChainGroupName)
  546     PyMOLObjectNames["Chains"][ChainID]["ChainAloneGroup"] = ChainAloneGroupName
  547     PyMOLObjectNames["Chains"][ChainID]["ChainGroupMembers"].append(ChainAloneGroupName)
  548         
  549     PyMOLObjectNames["Chains"][ChainID]["ChainAloneGroupMembers"] = []
  550         
  551     Name = "%s.Chain" % (ChainAloneGroupName)
  552     PyMOLObjectNames["Chains"][ChainID]["ChainAlone"] = Name
  553     PyMOLObjectNames["Chains"][ChainID]["ChainAloneGroupMembers"].append(Name)
  554 
  555     if GetChainAloneContainsSurfacesStatus(FileIndex, ChainID):
  556         # Setup a surface group and add it to chain alone group...
  557         SurfaceGroupName = "%s.Surface" % (ChainAloneGroupName)
  558         PyMOLObjectNames["Chains"][ChainID]["ChainAloneSurfaceGroup"] = SurfaceGroupName
  559         PyMOLObjectNames["Chains"][ChainID]["ChainAloneGroupMembers"].append(SurfaceGroupName)
  560         
  561         PyMOLObjectNames["Chains"][ChainID]["ChainAloneSurfaceGroupMembers"] = []
  562 
  563         # Setup a generic color surface...
  564         Name = "%s.Surface" % (SurfaceGroupName)
  565         PyMOLObjectNames["Chains"][ChainID]["ChainAloneSurface"] = Name
  566         PyMOLObjectNames["Chains"][ChainID]["ChainAloneSurfaceGroupMembers"].append(Name)
  567         
  568         if GetChainAloneSurfaceChainStatus(FileIndex, ChainID):
  569             # Setup hydrophobicity surface...
  570             Name = "%s.Hydrophobicity" % (SurfaceGroupName)
  571             PyMOLObjectNames["Chains"][ChainID]["ChainAloneHydrophobicSurface"] = Name
  572             PyMOLObjectNames["Chains"][ChainID]["ChainAloneSurfaceGroupMembers"].append(Name)
  573             
  574             # Setup hydrophobicity and charge surface...
  575             Name = "%s.Hydrophobicity_Charge" % (SurfaceGroupName)
  576             PyMOLObjectNames["Chains"][ChainID]["ChainAloneHydrophobicChargeSurface"] = Name
  577             PyMOLObjectNames["Chains"][ChainID]["ChainAloneSurfaceGroupMembers"].append(Name)
  578         
  579 def SetupPyMOLObjectNamesForPocket(FileIndex, PyMOLObjectNames, ChainID, PocketID):
  580     """Stetup groups and objects for pocket."""
  581 
  582     PyMOLObjectNames["Pockets"][ChainID][PocketID] = {}
  583     
  584     ChainGroupName = PyMOLObjectNames["Chains"][ChainID]["ChainGroup"]
  585 
  586     # Setup a chain level pocket group...
  587     ChainPocketGroupName = SetupChainPocketGroupName(FileIndex, ChainGroupName, ChainID, PocketID)
  588     
  589     PyMOLObjectNames["Pockets"][ChainID][PocketID]["ChainPocketGroup"] = ChainPocketGroupName
  590     PyMOLObjectNames["Chains"][ChainID]["ChainGroupMembers"].append(ChainPocketGroupName)
  591     
  592     PyMOLObjectNames["Pockets"][ChainID][PocketID]["ChainPocketGroupMembers"] = []
  593 
  594     # Setup fpocket...
  595     Name = "%s.Fpocket" % (ChainPocketGroupName)
  596     PyMOLObjectNames["Pockets"][ChainID][PocketID]["Pocket"] = Name
  597     PyMOLObjectNames["Pockets"][ChainID][PocketID]["ChainPocketGroupMembers"].append(Name)
  598     
  599     # Setup fpocket residues...
  600     Name = "%s.Residues" % (ChainPocketGroupName)
  601     PyMOLObjectNames["Pockets"][ChainID][PocketID]["PocketResidues"] = Name
  602     PyMOLObjectNames["Pockets"][ChainID][PocketID]["ChainPocketGroupMembers"].append(Name)
  603     
  604     if GetPocketContainsSurfaceStatus(FileIndex, ChainID, PocketID):
  605         # Setup a pocket surface group and add it to chain pocket group
  606         SurfaceGroupName = "%s.Surface" % (ChainPocketGroupName)
  607         PyMOLObjectNames["Pockets"][ChainID][PocketID]["PocketSurfaceGroup"] = SurfaceGroupName
  608         PyMOLObjectNames["Pockets"][ChainID][PocketID]["ChainPocketGroupMembers"].append(SurfaceGroupName)
  609         
  610         PyMOLObjectNames["Pockets"][ChainID][PocketID]["PocketSurfaceGroupMembers"] = []
  611         
  612         # Setup a generic color surface...
  613         Name = "%s.Surface" % (SurfaceGroupName)
  614         PyMOLObjectNames["Pockets"][ChainID][PocketID]["PocketSurface"] = Name
  615         PyMOLObjectNames["Pockets"][ChainID][PocketID]["PocketSurfaceGroupMembers"].append(Name)
  616         
  617         if GetPocketSurfaceChainStatus(FileIndex, ChainID, PocketID):
  618             # Surface colored by hydrophobicity...
  619             Name = "%s.Hydrophobicity" % (SurfaceGroupName)
  620             PyMOLObjectNames["Pockets"][ChainID][PocketID]["PocketHydrophobicitySurface"] = Name
  621             PyMOLObjectNames["Pockets"][ChainID][PocketID]["PocketSurfaceGroupMembers"].append(Name)
  622             
  623             # Surface colored by hydrophobicity and charge...
  624             Name = "%s.Hydrophobicity_Charge" % (SurfaceGroupName)
  625             PyMOLObjectNames["Pockets"][ChainID][PocketID]["PocketHydrophobicityChargeSurface"] = Name
  626             PyMOLObjectNames["Pockets"][ChainID][PocketID]["PocketSurfaceGroupMembers"].append(Name)
  627 
  628 def SetupChainPocketGroupName(FileIndex, ChainGroupName, ChainID, PocketID):
  629     """Setup pocket group PyMOL object name. """
  630 
  631     ChainPocketGroupName = "%s.Fpocket%s" % (ChainGroupName, PocketID)
  632     
  633     if not OptionsInfo["FpocketPropertiesAppend"]:
  634         return ChainPocketGroupName
  635         
  636     PocketPropertiesName = SetupFpocketPropertiesForGroupName(FileIndex, ChainGroupName, ChainID, PocketID)
  637         
  638     ChainPocketGroupName = "%s_%s" % (ChainPocketGroupName, PocketPropertiesName)
  639 
  640     return ChainPocketGroupName
  641 
  642 def SetupFpocketPropertiesForGroupName(FileIndex, ChainGroupName, ChainID, PocketID):
  643     """Setup fpocket properties for PyMOL group name. """
  644 
  645     ChainsAndPocketsInfo = OptionsInfo["FpocketInfilesInfo"]["ChainsAndPocketsInfo"][FileIndex]
  646     
  647     PocketScore = FormatFpocketPropertyForGroupName(ChainsAndPocketsInfo["PocketScore"][ChainID][PocketID])
  648     DrugScore = FormatFpocketPropertyForGroupName(ChainsAndPocketsInfo["DrugScore"][ChainID][PocketID])
  649     HydrophobicityScore = FormatFpocketPropertyForGroupName(ChainsAndPocketsInfo["HydrophobicityScore"][ChainID][PocketID])
  650     PolarityScore = FormatFpocketPropertyForGroupName(ChainsAndPocketsInfo["PolarityScore"][ChainID][PocketID])
  651     PocketVolume = FormatFpocketPropertyForGroupName(ChainsAndPocketsInfo["PocketVolume"][ChainID][PocketID])
  652 
  653     PocketProperties = "S%s_D%s_V%s_H%s_P%s" % (PocketScore, DrugScore, PocketVolume, HydrophobicityScore, PolarityScore)
  654     
  655     return PocketProperties
  656     
  657 def FormatFpocketPropertyForGroupName(PocketProperty):
  658     """Format fpocket property for PyMOL group name. """
  659     
  660     if PocketProperty is None:
  661         PocketProperty = "NA"
  662     else:
  663         PocketProperty = "%.2f" % float(PocketProperty)
  664         PocketProperty = re.sub("\.", "p", PocketProperty)
  665         PocketProperty = re.sub("^-", "neg", PocketProperty)
  666     
  667     return PocketProperty
  668     
  669 def GetChainAloneContainsSurfacesStatus(FileIndex, ChainID):
  670     """Get status of surfaces present in chain alone object."""
  671 
  672     # Always set up generic color surfaces...
  673     return True
  674 
  675 def GetChainAloneSurfaceChainStatus(FileIndex, ChainID):
  676     """Get status of  surfaces for chain alone object."""
  677 
  678     return OptionsInfo["SurfaceChain"]
  679 
  680 def GetPocketContainsSurfaceStatus(FileIndex, ChainID, PocketID):
  681     """Get status of surfaces present in  a pocket object."""
  682 
  683     # Always set up generic color surfaces...
  684     return True
  685 
  686 def GetPocketSurfaceChainStatus(FileIndex, ChainID, PocketID):
  687     """Get status of  surfaces for pocket object."""
  688 
  689     return OptionsInfo["PocketSurface"]
  690 
  691 def CopyPDBFilesForPML():
  692     """Copy appropriate PDB files for PyMOL to OutfilesDir """
  693 
  694     OutfilesDir = OptionsInfo["OutfilesDir"]
  695     
  696     MiscUtil.PrintInfo("\nCopying appropriate PDB files to directory %s..." % OutfilesDir)
  697 
  698     # Copy input PDB files...
  699     for FileIndex in range(0, len(OptionsInfo["InfilesInfo"]["InfilesNames"])):
  700         Infile = OptionsInfo["InfilesInfo"]["InfilesNames"][FileIndex]
  701         NewInfilePath = os.path.join(OutfilesDir, Infile)
  702         
  703         shutil.copyfile(Infile, NewInfilePath)
  704 
  705     # Copy fpocket output PDB files...
  706     for FileIndex in range(0, len(OptionsInfo["FpocketInfilesInfo"]["InfilesNames"])):
  707         Infile = OptionsInfo["FpocketInfilesInfo"]["InfilesNames"][FileIndex]
  708         InfilePath = OptionsInfo["FpocketInfilesInfo"]["InfilesPaths"][FileIndex]
  709         NewInfilePath = os.path.join(OutfilesDir, Infile)
  710         
  711         shutil.copyfile(InfilePath, NewInfilePath)
  712     
  713 def RetrieveInfilesInfo():
  714     """Retrieve information for input files."""
  715 
  716     InfilesInfo = {}
  717     
  718     InfilesInfo["InfilesNames"] = []
  719     InfilesInfo["InfilesRoots"] = []
  720     InfilesInfo["ChainsAndLigandsInfo"] = []
  721     
  722     for Infile in OptionsInfo["InfilesNames"]:
  723         FileDir, FileName, FileExt = MiscUtil.ParseFileName(Infile)
  724         InfileRoot = FileName
  725         
  726         ChainsAndLigandInfo = PyMOLUtil.GetChainsAndLigandsInfo(Infile, InfileRoot)
  727         
  728         InfilesInfo["InfilesNames"].append(Infile)
  729         InfilesInfo["InfilesRoots"].append(InfileRoot)
  730         InfilesInfo["ChainsAndLigandsInfo"].append(ChainsAndLigandInfo)
  731     
  732     OptionsInfo["InfilesInfo"] = InfilesInfo
  733 
  734 def RetrieveRefFileInfo():
  735     """Retrieve information for ref file."""
  736 
  737     RefFileInfo = {}
  738     if not OptionsInfo["Align"]:
  739         OptionsInfo["RefFileInfo"] = RefFileInfo
  740         return
  741 
  742     RefFile = OptionsInfo["RefFileName"]
  743     
  744     FileDir, FileName, FileExt = MiscUtil.ParseFileName(RefFile)
  745     RefFileRoot = FileName
  746     
  747     if re.match("^FirstInputFile$", OptionsInfo["AlignRefFile"], re.I):
  748         ChainsAndLigandInfo = OptionsInfo["InfilesInfo"]["ChainsAndLigandsInfo"][0]
  749     else:
  750         MiscUtil.PrintInfo("\nRetrieving chain and ligand information for alignment reference file %s..." % RefFile)
  751         ChainsAndLigandInfo = PyMOLUtil.GetChainsAndLigandsInfo(RefFile, RefFileRoot)
  752 
  753     RefFileInfo["RefFileName"] = RefFile
  754     RefFileInfo["RefFileRoot"] = RefFileRoot
  755     RefFileInfo["PyMOLObjectName"] = "AlignRef_%s" % RefFileRoot
  756     RefFileInfo["ChainsAndLigandsInfo"] = ChainsAndLigandInfo
  757     
  758     OptionsInfo["RefFileInfo"] = RefFileInfo
  759 
  760 def RetrieveFpocketResultFilesInfo():
  761     """Check and retrieve information for Fpocket result files."""
  762 
  763     FpocketInfilesInfo = {}
  764     
  765     FpocketInfilesInfo["InfilesNames"] = []
  766     FpocketInfilesInfo["InfilesRoots"] = []
  767     FpocketInfilesInfo["InfilesPaths"] = []
  768     FpocketInfilesInfo["InfilesDirs"] = []
  769     
  770     FpocketInfilesInfo["InfilesPocketsDirs"] = []
  771     FpocketInfilesInfo["InfilesPocketsPDBFilesCount"] = []
  772     
  773     FpocketInfilesInfo["ChainsAndPocketsInfo"] = []
  774     
  775     for Infile in OptionsInfo["InfilesNames"]:
  776         MiscUtil.PrintInfo("\nRetrieving Fpocket result file information for input file %s..." % Infile)
  777         
  778         FileDir, FileName, FileExt = MiscUtil.ParseFileName(Infile)
  779         InfileRoot = FileName
  780 
  781         FpocketInfileDir = "%s_out" % InfileRoot
  782         FpocketInfileRoot = "%s_out" % InfileRoot
  783         FpocketInfileName = "%s.pdb" % FpocketInfileRoot
  784         FpocketInfilePath = os.path.join(FpocketInfileDir, FpocketInfileName)
  785         
  786         FpocketInfilePocketsDir = os.path.join(FpocketInfileDir, "pockets")
  787         
  788         if not os.path.isdir(FpocketInfileDir):
  789             MiscUtil.PrintError("Fpocket result file directory, %s, is missing for input PDB file, %s." % (FpocketInfileDir, Infile))
  790 
  791         if not os.path.isfile(FpocketInfilePath):
  792             MiscUtil.PrintError("Fpocket result PDB file, %s, is missing for input PDB file, %s." % (FpocketInfilePath, Infile))
  793             
  794         if not os.path.isdir(FpocketInfilePocketsDir):
  795             MiscUtil.PrintError("Fpocket pockets result file directory, %s, is missing for input PDB file, %s." % (FpocketInfilePocketsDir, Infile))
  796 
  797         PocketsPDBFiles = glob.glob(os.path.join(FpocketInfilePocketsDir, "pocket*_atm.pdb"))
  798         PocketsPDBFilesCount = len(PocketsPDBFiles)
  799         if PocketsPDBFilesCount == 0:
  800             MiscUtil.PrintError("Fpocket pockets result files missing in directory, %s, for input PDB file, %s." % (FpocketInfilePocketsDir, Infile))
  801 
  802         # Retrieve chains and pockets...
  803         ChainsAndPocketsInfo = GetFpocketChainsAndPocketsInfo(FpocketInfileRoot, FpocketInfilePath, FpocketInfileDir, FpocketInfilePocketsDir)
  804 
  805         FpocketInfilesInfo["InfilesNames"].append(FpocketInfileName)
  806         FpocketInfilesInfo["InfilesRoots"].append(FpocketInfileRoot)
  807         FpocketInfilesInfo["InfilesPaths"].append(FpocketInfilePath)
  808         FpocketInfilesInfo["InfilesDirs"].append(FpocketInfileDir)
  809         
  810         FpocketInfilesInfo["InfilesPocketsDirs"].append(FpocketInfilePocketsDir)
  811         FpocketInfilesInfo["InfilesPocketsPDBFilesCount"].append(PocketsPDBFilesCount)
  812         
  813         FpocketInfilesInfo["ChainsAndPocketsInfo"].append(ChainsAndPocketsInfo)
  814 
  815         MiscUtil.PrintInfo("PDB result file: %s..." % FpocketInfileName)
  816         MiscUtil.PrintInfo("Total number of pockets: %s..." % ChainsAndPocketsInfo["NumOfPockets"])
  817         
  818         MiscUtil.PrintInfo("Pocket Chain IDs: %s" % " ".join(ChainsAndPocketsInfo["ChainIDs"]))
  819         for ChainID in ChainsAndPocketsInfo["ChainIDs"]:
  820             MiscUtil.PrintInfo("Pocket Chain ID: %s; NumOfPockets: %s; PocketIDs: %s" % (ChainID, len(ChainsAndPocketsInfo["PocketIDs"][ChainID]), " ".join(ChainsAndPocketsInfo["PocketIDs"][ChainID])))
  821     
  822     OptionsInfo["FpocketInfilesInfo"] = FpocketInfilesInfo
  823 
  824 def GetFpocketChainsAndPocketsInfo(FpocketInfileRoot, FpocketInfilePath, FpocketInfileDir, FpocketInfilePocketsDir):
  825     """Get chains and pockets information for Fpocket result files. """
  826 
  827     ChainsAndPocketsInfo = {}
  828     ChainsAndPocketsInfo["ChainIDs"] = []
  829     ChainsAndPocketsInfo["PocketIDs"] = {}
  830     ChainsAndPocketsInfo["PocketResNums"] = {}
  831     
  832     ChainsAndPocketsInfo["DrugScore"] = {}
  833     ChainsAndPocketsInfo["PocketScore"] = {}
  834     ChainsAndPocketsInfo["HydrophobicityScore"] = {}
  835     ChainsAndPocketsInfo["PolarityScore"] = {}
  836     ChainsAndPocketsInfo["PocketVolume"] = {}
  837     
  838     ChainsAndPocketsInfo["NumOfPockets"] = 0
  839 
  840     # Retrieve chain IDs corresponding to main chain atoms...
  841     ChainIDs = GetPolymerChainIDs(FpocketInfilePath, FpocketInfileRoot)
  842     
  843     # Retrieve number of pockets and pocket IDs...
  844     PocketIDs = GetPocketIDs(FpocketInfilePath, FpocketInfileRoot)
  845     ChainsAndPocketsInfo["NumOfPockets"] = len(PocketIDs)
  846     
  847     # Retrieve residue numbers for fpockets across the chains...
  848     for PocketID in PocketIDs:
  849         PocketAtomFile = os.path.join(FpocketInfilePocketsDir, "pocket%s_atm.pdb" % PocketID)
  850         
  851         if not os.path.isfile(PocketAtomFile):
  852             MiscUtil.PrintError("Fpocket result PDB file, %s, is missing for pocket ID, %s." % (PocketAtomFile, PocketID))
  853 
  854         # Retrieve pocket properites for a pocket across chains...
  855         PocketScore, DrugScore, HydrophobicityScore, PolarityScore, PocketVolume = GetPocketProperties(PocketAtomFile)
  856         
  857         MolName = "pocket%s_atm" % PocketID
  858         pymol.cmd.load(PocketAtomFile, MolName)
  859         SelectionCmd = "(%s)" % MolName
  860         
  861         pymol.stored.FpocketInfo = []
  862         pymol.cmd.iterate(SelectionCmd, "pymol.stored.FpocketInfo.append([chain, resi, resn])")
  863         pymol.cmd.delete(MolName)
  864 
  865         for ChainID, ResNum, ResName in pymol.stored.FpocketInfo:
  866             if ChainID not in ChainsAndPocketsInfo["ChainIDs"]:
  867                 ChainsAndPocketsInfo["PocketIDs"][ChainID] = []
  868                 ChainsAndPocketsInfo["PocketResNums"][ChainID] = {}
  869                 
  870                 ChainsAndPocketsInfo["DrugScore"][ChainID] = {}
  871                 ChainsAndPocketsInfo["PocketScore"][ChainID] = {}
  872                 ChainsAndPocketsInfo["HydrophobicityScore"][ChainID] = {}
  873                 ChainsAndPocketsInfo["PolarityScore"][ChainID] = {}
  874                 ChainsAndPocketsInfo["PocketVolume"][ChainID] = {}
  875                 
  876                 ChainsAndPocketsInfo["ChainIDs"].append(ChainID)
  877 
  878             if PocketID not in ChainsAndPocketsInfo["PocketIDs"][ChainID]:
  879                 ChainsAndPocketsInfo["PocketResNums"][ChainID][PocketID] = []
  880                 ChainsAndPocketsInfo["PocketIDs"][ChainID].append(PocketID)
  881 
  882                 # Track pocket and drug score across chains...
  883                 ChainsAndPocketsInfo["DrugScore"][ChainID][PocketID] = DrugScore
  884                 ChainsAndPocketsInfo["PocketScore"][ChainID][PocketID] = PocketScore
  885                 ChainsAndPocketsInfo["HydrophobicityScore"][ChainID][PocketID] = HydrophobicityScore
  886                 ChainsAndPocketsInfo["PolarityScore"][ChainID][PocketID] = PolarityScore
  887                 ChainsAndPocketsInfo["PocketVolume"][ChainID][PocketID] = PocketVolume
  888                 
  889 
  890             if ResNum not in ChainsAndPocketsInfo["PocketResNums"][ChainID][PocketID]:
  891                 ChainsAndPocketsInfo["PocketResNums"][ChainID][PocketID].append(ResNum)
  892 
  893     ChainsAndPocketsInfo["ChainIDs"] = sorted(ChainsAndPocketsInfo["ChainIDs"])
  894     
  895     return ChainsAndPocketsInfo
  896 
  897 def GetPolymerChainIDs(Infile, MolName):
  898     """Get chain IDs for main chain excluding hetero atoms. """
  899     
  900     pymol.cmd.load(Infile, MolName)
  901     ChainIDs = PyMOLUtil.GetChains(MolName)
  902 
  903     # Retrieve polymer chains...
  904     SelectedChainIDs = []
  905     for ChainID in ChainIDs:
  906         AtomsCount = pymol.cmd.count_atoms("(%s and (chain %s) and (polymer) and (not hetatm))" % (MolName, ChainID))
  907         if AtomsCount > 0:
  908             SelectedChainIDs.append(ChainID)
  909             
  910     pymol.cmd.delete(MolName)
  911     
  912     return SelectedChainIDs
  913 
  914 def GetPocketIDs(Infile, MolName):
  915     """Get pocket IDs. """
  916 
  917     # Fpockets are annonated in PDB file as STP residue name and unique residue
  918     # numbers...
  919     pymol.cmd.load(Infile, MolName)
  920     SelectionCmd = "(%s and (resn STP) and hetatm)" % MolName
  921     
  922     pymol.stored.FpocketIDsInfo = []
  923     pymol.cmd.iterate(SelectionCmd, "pymol.stored.FpocketIDsInfo.append(resi)")
  924     pymol.cmd.delete(MolName)
  925 
  926     PocketIDs = []
  927     for PocketID in pymol.stored.FpocketIDsInfo:
  928         if PocketID not in PocketIDs:
  929             PocketIDs.append(PocketID)
  930 
  931     return PocketIDs
  932     
  933 def ProcessChainAndPocketIDs():
  934     """Process specified chain and pocket  IDs for infiles."""
  935 
  936     OptionsInfo["FpocketInfilesInfo"]["SpecifiedChainsAndPocketsInfo"] = []
  937     
  938     for FileIndex in range(0, len(OptionsInfo["InfilesInfo"]["InfilesNames"])):
  939         MiscUtil.PrintInfo("\nProcessing specified chain and Pocket IDs for input file %s..." % OptionsInfo["FpocketInfilesInfo"]["InfilesNames"][FileIndex])
  940         
  941         ChainsAndPocketsInfo = OptionsInfo["FpocketInfilesInfo"]["ChainsAndPocketsInfo"][FileIndex]
  942         
  943         SpecifiedChainsAndPocketsInfo = ProcessChainsAndPocketsOptionsInfo(ChainsAndPocketsInfo)
  944         OptionsInfo["FpocketInfilesInfo"]["SpecifiedChainsAndPocketsInfo"].append(SpecifiedChainsAndPocketsInfo)
  945         
  946         CheckPresenceOfValidPocketIDs(ChainsAndPocketsInfo, SpecifiedChainsAndPocketsInfo)
  947 
  948 def GetPocketProperties(PocketAtomFile):
  949     """Get pocket properites from the pocket PDB file. """
  950     
  951     PocketScore, DrugScore, HydrophobicityScore, PolarityScore, PocketVolume = [None] * 5
  952     
  953     PocketAtomFH = open(PocketAtomFile, "r")
  954     if PocketAtomFH is None:
  955         return (PocketScore, DrugScore, HydrophobicityScore, PolarityScore, PocketVolume)
  956     
  957     for Line in PocketAtomFH:
  958         Line = Line.rstrip()
  959         if re.search("Pocket Score", Line, re.I):
  960             LineWords = Line.split()
  961             PocketScore = LineWords[-1]
  962         elif re.search("Drug Score", Line, re.I):
  963             LineWords = Line.split()
  964             DrugScore = LineWords[-1]
  965         elif re.search("Hydrophobicity Score", Line, re.I):
  966             LineWords = Line.split()
  967             HydrophobicityScore = LineWords[-1]
  968         elif re.search("Polarity Score", Line, re.I):
  969             LineWords = Line.split()
  970             PolarityScore = LineWords[-1]
  971         elif re.search("Pocket volume \(Monte Carlo\)", Line, re.I):
  972             LineWords = Line.split()
  973             PocketVolume = LineWords[-1]
  974         
  975         if not re.match("^HEADER", Line, re.I):
  976             break
  977     
  978     PocketAtomFH.close()
  979 
  980     return (PocketScore, DrugScore, HydrophobicityScore, PolarityScore, PocketVolume)
  981 
  982 def ProcessChainsAndPocketsOptionsInfo(ChainsAndPocketsInfo):
  983     """Process specified chain and pocket IDs using command line options."""
  984 
  985     ChainIDs = OptionsInfo["ChainIDs"]
  986     FpocketMode = OptionsInfo["FpocketMode"]
  987     FpocketIDs = OptionsInfo["FpocketIDs"]
  988     
  989     SpecifiedChainsAndPocketsInfo = {}
  990     SpecifiedChainsAndPocketsInfo["ChainIDs"] = []
  991     SpecifiedChainsAndPocketsInfo["PocketIDs"] = {}
  992 
  993     ProcessChainsOptionInfo(ChainsAndPocketsInfo, SpecifiedChainsAndPocketsInfo)
  994     ProcessPocketsOptionInfo(ChainsAndPocketsInfo, SpecifiedChainsAndPocketsInfo)
  995     
  996     return SpecifiedChainsAndPocketsInfo
  997 
  998 def ProcessChainsOptionInfo(ChainsAndPocketsInfo, SpecifiedChainsAndPocketsInfo):
  999     """Process chain IDs"""
 1000 
 1001     MiscUtil.PrintInfo("Processing chain IDs...")
 1002     
 1003     ChainsOptionName = "-c, --chainIDs"
 1004     ChainsOptionValue = OptionsInfo["ChainIDs"]
 1005     
 1006     if re.match("^All$", ChainsOptionValue, re.I):
 1007         SpecifiedChainsAndPocketsInfo["ChainIDs"] = ChainsAndPocketsInfo["ChainIDs"]
 1008         return
 1009     elif re.match("^(First|Auto)$", ChainsOptionValue, re.I):
 1010         FirstChainID = ChainsAndPocketsInfo["ChainIDs"][0] if (len(ChainsAndPocketsInfo["ChainIDs"])) else None
 1011         if FirstChainID is not None:
 1012             SpecifiedChainsAndPocketsInfo["ChainIDs"].append(FirstChainID)
 1013         return
 1014     
 1015     ChainIDs = re.sub(" ", "", ChainsOptionValue)
 1016     if not ChainIDs:
 1017         MiscUtil.PrintError("No valid value specified using \"%s\" option." % ChainsOptionName)
 1018 
 1019     ChainIDsList = ChainsAndPocketsInfo["ChainIDs"]
 1020     SpecifiedChainIDsList = []
 1021     
 1022     ChainIDsWords = ChainIDs.split(",")
 1023     for ChainID in ChainIDsWords:
 1024         if not ChainID in ChainIDsList:
 1025             MiscUtil.PrintWarning("The chain ID, %s, specified using \"%s\" option is not valid. It'll be ignored. Valid chain IDs: %s" % (ChainID, ChainsOptionName, ", ".join(ChainIDsList)))
 1026             continue
 1027         if ChainID in SpecifiedChainIDsList:
 1028             MiscUtil.PrintWarning("The chain ID, %s, has already been specified using \"%s\" option. It'll be ignored." % (ChainID, ChainsOptionName))
 1029             continue
 1030         SpecifiedChainIDsList.append(ChainID)
 1031     
 1032     if not len(SpecifiedChainIDsList):
 1033         MiscUtil.PrintError("No valid chain IDs \"%s\"  specified using \"%s\" option." % (ChainsOptionValue, ChainsOptionName))
 1034     
 1035     SpecifiedChainsAndPocketsInfo["ChainIDs"] = SpecifiedChainIDsList
 1036     
 1037 def ProcessPocketsOptionInfo(ChainsAndPocketsInfo, SpecifiedChainsAndPocketsInfo):
 1038     """Process pocket IDs"""
 1039 
 1040     MiscUtil.PrintInfo("Processing pocket IDs...")
 1041     
 1042     PocketsModeOptionName = "-f, --fpocketMode"
 1043     PocketsModeOptionValue = OptionsInfo["FpocketMode"]
 1044     
 1045     PocketsIDsOptionName = "--fpocketIDs"
 1046     PocketsIDsOptionValue = OptionsInfo["FpocketIDs"]
 1047     
 1048     # Intialize pocketIDs...
 1049     for ChainID in SpecifiedChainsAndPocketsInfo["ChainIDs"]:
 1050         SpecifiedChainsAndPocketsInfo["PocketIDs"][ChainID] = []
 1051     
 1052     if re.match("^All$", PocketsModeOptionValue, re.I):
 1053         for ChainID in SpecifiedChainsAndPocketsInfo["ChainIDs"]:
 1054             SpecifiedChainsAndPocketsInfo["PocketIDs"][ChainID] = ChainsAndPocketsInfo["PocketIDs"][ChainID]
 1055         return
 1056     elif re.match("^TopN$", PocketsModeOptionValue, re.I):
 1057         # Setup TopN pocket IDs for each chain...
 1058         TopNPocketsCount = int(PocketsIDsOptionValue[0])
 1059         for ChainID in SpecifiedChainsAndPocketsInfo["ChainIDs"]:
 1060             TopNPocketsIDs = []
 1061             NumOfPockets = len(ChainsAndPocketsInfo["PocketIDs"][ChainID])
 1062 
 1063             if NumOfPockets:
 1064                 if TopNPocketsCount > NumOfPockets:
 1065                     TopNPocketsIDs = ChainsAndPocketsInfo["PocketIDs"][ChainID]
 1066                 else:
 1067                     TopNPocketsIDs = ChainsAndPocketsInfo["PocketIDs"][ChainID][0 : TopNPocketsCount]
 1068             
 1069             SpecifiedChainsAndPocketsInfo["PocketIDs"][ChainID] = TopNPocketsIDs
 1070         return
 1071 
 1072     # Process explicitly specified pocket IDs...
 1073     PocketIDsWords = PocketsIDsOptionValue
 1074     if  not len(PocketIDsWords):
 1075         MiscUtil.PrintError("No valid value specified using \"%s\" option." % PocketsIDsOptionName)
 1076 
 1077     for ChainID in SpecifiedChainsAndPocketsInfo["ChainIDs"]:
 1078         PocketIDsList = ChainsAndPocketsInfo["PocketIDs"][ChainID]
 1079         SpecifiedPocketIDsList = []
 1080         
 1081         for PocketID in PocketIDsWords:
 1082             if not PocketID in PocketIDsList:
 1083                 MiscUtil.PrintWarning("The pocket ID, %s, specified using \"%s\" option is not valid for chain, %s. It'll be ignored. Valid pocket IDs are listed earlier." % (PocketID, PocketsIDsOptionName, ChainID))
 1084                 continue
 1085             
 1086             if PocketID in SpecifiedPocketIDsList:
 1087                 MiscUtil.PrintWarning("The pocket ID, %s, has already been specified using \"%s\" option. It'll be ignored." % (PocketID, PocketsIDsOptionName))
 1088                 continue
 1089             
 1090             SpecifiedPocketIDsList.append(PocketID)
 1091             
 1092         if not len(SpecifiedPocketIDsList):
 1093             MiscUtil.PrintWarning("No valid pocket IDs \"%s\" specified using \"%s\" option for chain ID, %s." % (PocketsIDsOptionValue, PocketsIDsOptionName, ChainID))
 1094         
 1095         SpecifiedChainsAndPocketsInfo["PocketIDs"][ChainID] = SpecifiedPocketIDsList
 1096 
 1097 def CheckPresenceOfValidPocketIDs(ChainsAndPocketsInfo, SpecifiedChainsAndPocketsInfo):
 1098     """Check presence of valid pocket IDs."""
 1099 
 1100     MiscUtil.PrintInfo("\nSpecified chain IDs: %s" % (", ".join(SpecifiedChainsAndPocketsInfo["ChainIDs"])))
 1101     
 1102     for ChainID in SpecifiedChainsAndPocketsInfo["ChainIDs"]:
 1103         if len (SpecifiedChainsAndPocketsInfo["PocketIDs"][ChainID]):
 1104             MiscUtil.PrintInfo("Chain ID: %s; Specified PocketIDs: %s" % (ChainID, ", ".join(SpecifiedChainsAndPocketsInfo["PocketIDs"][ChainID])))
 1105         else:
 1106             MiscUtil.PrintInfo("Chain IDs: %s; Specified PocketIDs: None" % (ChainID))
 1107             MiscUtil.PrintWarning("No valid pocket IDs found for chain ID, %s. PyMOL groups and objects related to fpockets won't be created." % (ChainID))
 1108 
 1109 def RetrieveFirstChainID(FileIndex, FpocketComplexMode):
 1110     """Get first chain ID."""
 1111 
 1112     FirstChainID = None
 1113     if FpocketComplexMode:
 1114         ChainsAndPocketsInfo = OptionsInfo["FpocketInfilesInfo"]["ChainsAndPocketsInfo"][FileIndex]
 1115         if len(ChainsAndPocketsInfo["ChainIDs"]):
 1116             FirstChainID = ChainsAndPocketsInfo["ChainIDs"][0]
 1117     else:
 1118         ChainsAndLigandsInfo = OptionsInfo["InfilesInfo"]["ChainsAndLigandsInfo"][FileIndex]
 1119         if len(ChainsAndLigandsInfo["ChainIDs"]):
 1120             FirstChainID = ChainsAndLigandsInfo["ChainIDs"][0]
 1121     
 1122     return FirstChainID
 1123 
 1124 def ProcessSurfaceAtomTypesColors():
 1125     """Process surface atom types colors. """
 1126 
 1127     AtomTypesColorNamesInfo = PyMOLUtil.ProcessSurfaceAtomTypesColorsOptionsInfo("--surfaceAtomTypesColors", OptionsInfo["SurfaceAtomTypesColors"])
 1128     OptionsInfo["AtomTypesColorNames"] = AtomTypesColorNamesInfo
 1129 
 1130 def CheckAndSetupOutfilesDir():
 1131     """Check and setup a directory for output files used by PyMOL."""
 1132 
 1133     Outfile = Options["--outfile"]
 1134     OutfilesDir = Options["--outfilesDir"]
 1135     
 1136     FileDir, FileName, FileExt = MiscUtil.ParseFileName(Outfile)
 1137     if re.match("^auto$", OutfilesDir, re.I):
 1138         OutfilesDir = "%s_out_PyMOL" % FileName
 1139     
 1140     if os.path.isdir(OutfilesDir):
 1141         if not OptionsInfo["Overwrite"]:
 1142             MiscUtil.PrintError("The output directory, %s, already exists. Use option \"--ov\" or \"--overwrite\" and try again." % OutfilesDir)
 1143         MiscUtil.PrintInfo("Using existing outout dir %s..." % OutfilesDir)
 1144     else:
 1145         MiscUtil.PrintInfo("Creating new output dir %s..." % OutfilesDir)
 1146         os.mkdir(OutfilesDir)
 1147     
 1148     OptionsInfo["Outfile"] = Outfile
 1149     OptionsInfo["OutfilesDir"] = OutfilesDir
 1150     
 1151     OptionsInfo["PMLOutfile"] = Outfile
 1152     OptionsInfo["PMLOutfilePath"] = os.path.join(OutfilesDir, Outfile)
 1153     
 1154 def ProcessOptions():
 1155     """Process and validate command line arguments and options"""
 1156 
 1157     MiscUtil.PrintInfo("Processing options...")
 1158     
 1159     # Validate options...
 1160     ValidateOptions()
 1161     
 1162     OptionsInfo["Align"] = True if re.match("^Yes$", Options["--align"], re.I) else False
 1163     OptionsInfo["AlignMethod"] = Options["--alignMethod"].lower()
 1164     OptionsInfo["AlignMode"] = Options["--alignMode"]
 1165     
 1166     OptionsInfo["FpocketPropertiesAppend"] = True if re.match("^Yes$", Options["--fpocketPropertiesAppend"], re.I) else False
 1167     
 1168     OptionsInfo["Infiles"] = Options["--infiles"]
 1169     OptionsInfo["InfilesNames"] =  Options["--infileNames"]
 1170 
 1171     OptionsInfo["AlignRefFile"] = Options["--alignRefFile"]
 1172     if re.match("^FirstInputFile$", Options["--alignRefFile"], re.I):
 1173         OptionsInfo["RefFileName"] = OptionsInfo["InfilesNames"][0]
 1174     else:
 1175         OptionsInfo["RefFileName"] = Options["--alignRefFile"]
 1176 
 1177     OptionsInfo["ChainIDs"] = Options["--chainIDs"]
 1178     
 1179     OptionsInfo["FpocketMode"] = Options["--fpocketMode"]
 1180     OptionsInfo["FpocketIDs"] = Options["--fpocketIDsList"]
 1181     
 1182     OptionsInfo["Overwrite"] = Options["--overwrite"]
 1183     
 1184     OptionsInfo["LabelFontID"] = int(Options["--labelFontID"])
 1185 
 1186     OptionsInfo["PocketColorByPocketNum"] = True if re.match("^Yes$", Options["--pocketColorByPocketNum"], re.I) else False
 1187     OptionsInfo["PocketLabel"] = True if re.match("^Yes$", Options["--pocketLabel"], re.I) else False
 1188     OptionsInfo["PocketLabelType"] = Options["--pocketLabelType"]
 1189     OptionsInfo["ThreeLetterPocketLabelType"] = True if re.match("^ThreeLetter$", Options["--pocketLabelType"], re.I) else False
 1190 
 1191     OptionsInfo["PocketNumOneColor"] = "gray80"
 1192     
 1193     OptionsInfo["PocketSurface"] = True if re.match("^Yes$", Options["--pocketSurface"], re.I) else False
 1194     OptionsInfo["SurfaceChain"] = True if re.match("^Yes$", Options["--surfaceChain"], re.I) else False
 1195     
 1196     OptionsInfo["SurfaceColor"] = Options["--surfaceColor"]
 1197     OptionsInfo["SurfaceColorPalette"] = Options["--surfaceColorPalette"]
 1198     OptionsInfo["SurfaceAtomTypesColors"] = Options["--surfaceAtomTypesColors"]
 1199     ProcessSurfaceAtomTypesColors()
 1200     
 1201     OptionsInfo["SphereScale"] = float(Options["--sphereScale"])
 1202     OptionsInfo["SphereTransparency"] = float(Options["--sphereTransparency"])
 1203     
 1204     OptionsInfo["SurfaceTransparency"] = float(Options["--surfaceTransparency"])
 1205 
 1206     # Check and setup outfile dir before processing input files...
 1207     CheckAndSetupOutfilesDir()
 1208     
 1209     RetrieveInfilesInfo()
 1210     RetrieveRefFileInfo()
 1211     RetrieveFpocketResultFilesInfo()
 1212     
 1213     # Process specified chain and pocket IDs..
 1214     ProcessChainAndPocketIDs()
 1215 
 1216 def RetrieveOptions(): 
 1217     """Retrieve command line arguments and options"""
 1218     
 1219     # Get options...
 1220     global Options
 1221     Options = docopt(_docoptUsage_)
 1222     
 1223     # Set current working directory to the specified directory...
 1224     WorkingDir = Options["--workingdir"]
 1225     if WorkingDir:
 1226         os.chdir(WorkingDir)
 1227     
 1228     # Handle examples option...
 1229     if "--examples" in Options and Options["--examples"]:
 1230         MiscUtil.PrintInfo(MiscUtil.GetExamplesTextFromDocOptText(__doc__))
 1231         sys.exit(0)
 1232 
 1233 def ValidateOptions():
 1234     """Validate option values"""
 1235     
 1236     MiscUtil.ValidateOptionTextValue("--align", Options["--align"], "yes no")
 1237     MiscUtil.ValidateOptionTextValue("--alignMethod", Options["--alignMethod"], "align cealign super")
 1238     MiscUtil.ValidateOptionTextValue("--alignMode", Options["--alignMode"], "FirstChain Complex")
 1239     
 1240     MiscUtil.ValidateOptionTextValue("--fpocketPropertiesAppend", Options["--fpocketPropertiesAppend"], "yes no")
 1241     
 1242     # Expand infiles to handle presence of multiple input files...
 1243     InfileNames = MiscUtil.ExpandFileNames(Options["--infiles"], ",")
 1244     if not len(InfileNames):
 1245         MiscUtil.PrintError("No input files specified for \"-i, --infiles\" option")
 1246 
 1247     # Validate file extensions...
 1248     for Infile in InfileNames:
 1249         MiscUtil.ValidateOptionFilePath("-i, --infiles", Infile)
 1250         MiscUtil.ValidateOptionFileExt("-i, --infiles", Infile, "pdb")
 1251         MiscUtil.ValidateOptionsDistinctFileNames("-i, --infiles", Infile, "-o, --outfile", Options["--outfile"])
 1252     Options["--infileNames"] = InfileNames
 1253 
 1254     MiscUtil.ValidateOptionFileExt("-o, --outfile", Options["--outfile"], "pml")
 1255 
 1256     if re.match("^yes$", Options["--align"], re.I):
 1257         if not re.match("^FirstInputFile$", Options["--alignRefFile"], re.I):
 1258             AlignRefFile = Options["--alignRefFile"]
 1259             MiscUtil.ValidateOptionFilePath("--alignRefFile", AlignRefFile)
 1260             MiscUtil.ValidateOptionFileExt("--alignRefFile", AlignRefFile, "pdb")
 1261             MiscUtil.ValidateOptionsDistinctFileNames("--AlignRefFile", AlignRefFile, "-o, --outfile", Options["--outfile"])
 1262     
 1263     MiscUtil.ValidateOptionTextValue("--fpocketMode", Options["--fpocketMode"], "All TopN Specify")
 1264     
 1265     FpocketIDsList = []
 1266     if re.match("^(TopN|Specify)$", Options["--fpocketMode"], re.I):
 1267         if Options["--fpocketIDs"] is None:
 1268             MiscUtil.PrintError("No value specified for \"--fpocketIDs\" during \"%s\" of \"-f, --fpocketMode\" option." % (Options["--fpocketMode"]))
 1269         
 1270         FpocketIDs = re.sub(" ", "", Options["--fpocketIDs"])
 1271         if not FpocketIDs:
 1272             MiscUtil.PrintError("No valid value specified for \"--fpocketIDs\" during \"%s\" of \"-f, --fpocketMode\" option." % (Options["--fpocketMode"]))
 1273         FpocketIDsWords = FpocketIDs.split(",")
 1274         if len(FpocketIDsWords) == 0:
 1275             MiscUtil.PrintError("No valid value specified for \"--fpocketIDs\" during \"%s\" of \"-f, --fpocketMode\" option." % (Options["--fpocketMode"]))
 1276             
 1277         if re.match("^TopN$", Options["--fpocketMode"], re.I):
 1278             if len(FpocketIDsWords) > 1:
 1279                 MiscUtil.PrintError("Number of values specified for \"--fpocketIDs\" must be 1 during \"TopN\" of  \"-f, --fpocketMode\" option.")
 1280         
 1281         for FpocketID in FpocketIDsWords:
 1282             MiscUtil.ValidateOptionIntegerValue("--fpocketIDs", FpocketID, {">": 0})
 1283             FpocketIDsList.append(FpocketID)
 1284     
 1285     Options["--fpocketIDsList"] = FpocketIDsList
 1286         
 1287     MiscUtil.ValidateOptionIntegerValue("--labelFontID", Options["--labelFontID"], {})
 1288 
 1289     MiscUtil.ValidateOptionTextValue("--pocketColorByPocketNum", Options["--pocketColorByPocketNum"], "yes no")
 1290     MiscUtil.ValidateOptionTextValue("--pocketLabel", Options["--pocketLabel"], "yes no")
 1291     MiscUtil.ValidateOptionTextValue("--pocketLabelType", Options["--pocketLabelType"], "OneLetter ThreeLetter")
 1292     
 1293     MiscUtil.ValidateOptionTextValue("--pocketSurface", Options["--pocketSurface"], "yes no")
 1294     MiscUtil.ValidateOptionTextValue("--surfaceChain", Options["--surfaceChain"], "yes no")
 1295 
 1296     MiscUtil.ValidateOptionFloatValue("--sphereScale", Options["--sphereScale"], {">": 0.0})
 1297     MiscUtil.ValidateOptionFloatValue("--sphereTransparency", Options["--sphereTransparency"], {">=": 0.0, "<=": 1.0})
 1298     
 1299     MiscUtil.ValidateOptionTextValue("--surfaceColorPalette", Options["--surfaceColorPalette"], "RedToWhite WhiteToGreen")
 1300     MiscUtil.ValidateOptionFloatValue("--surfaceTransparency", Options["--surfaceTransparency"], {">=": 0.0, "<=": 1.0})
 1301     
 1302 # Setup a usage string for docopt...
 1303 _docoptUsage_ = """
 1304 PyMOLVisualizeFpockets.py - Visualize fpockets for macromolecules.
 1305 
 1306 Usage:
 1307     PyMOLVisualizeFpockets.py [--align <yes or no>] [--alignMethod <align, cealign, super>]
 1308                               [--alignMode <FirstChain or Complex>] [--alignRefFile <filename>]
 1309                               [--chainIDs <First, All or ID1,ID2...>] [--fpocketMode <All, TopN, or Specify>]
 1310                               [--fpocketIDs <Value or Value1,Value2...>] [--fpocketPropertiesAppend <yes or no>]
 1311                               [--labelFontID <number>] [--outfilesDir <outfilesDir>] [--pocketColorByPocketNum <yes or no>]
 1312                               [--pocketLabel <yes or no>] [--pocketLabelType <OneLetter or ThreeLetter>]
 1313                               [--pocketSurface <yes or no>] [--sphereScale <number>] [--sphereTransparency <number>]
 1314                               [--surfaceChain <yes or no>] [--surfaceAtomTypesColors <ColorType,ColorSpec,...>]
 1315                               [--surfaceColor <ColorName>] [--surfaceColorPalette <RedToWhite or WhiteToGreen>]
 1316                               [--surfaceTransparency <number>] [--overwrite] [-w <dir>] -i <infile1,infile2,infile3...> -o <outfile>
 1317     PyMOLVisualizeFpockets.py -h | --help | -e | --examples
 1318 
 1319 Description:
 1320     Generate a PyMOL visualization file for visualizing pockets in macromolecules
 1321     detected by an open source package named Fpocket [ Ref 166 ].
 1322 
 1323     The results of Fpocket calculations must be available in the current directory
 1324     for all input files. A complete set of expected results is shown below:
 1325     
 1326         Dir: <PDBFileRoot>_out
 1327             <PDBFileRoot>_out.pdb
 1328                ... .. ...
 1329             Dir: pockets
 1330                <PDBFileRoot><PocketID>_atm.pdb
 1331                ... .. ...
 1332     
 1333     The supported input file format is: PDB (.pdb)
 1334 
 1335     The supported output file formats is: PyMOL script file (.pml)
 1336 
 1337     The following directory and files are created for the visualization of pockets
 1338     detected by Fpocket:
 1339     
 1340         Dir: <OutFileRoot>_out_PyMOL or <OutfilesDir>
 1341             <OutfileRoot>.pml 
 1342             <PDBFileRoot>.pdb
 1343             <PDBFileRoot>_out.pdb
 1344     
 1345     You may visualize pockets in PyMOL by loading <OutfileRoot>.pml from
 1346     <OutfileRoot>_out_PyMOL or <OutfilesDir> directory.
 1347 
 1348     A variety of PyMOL groups and objects may be  created for visualization of
 1349     fpockets in macromolecules. These groups and objects correspond to complexes,
 1350     chains, fpockets, and surfaces. A complete hierarchy of all possible PyMOL
 1351     groups and objects is shown below:
 1352     
 1353         <PDBFileRoot>
 1354             .Complex
 1355                 .Initial_PDB
 1356                 .Fpocket_PDB
 1357             .Chain<ID>
 1358                 .Complex
 1359                     .Complex
 1360                 .Chain
 1361                     .Chain
 1362                     .Surface
 1363                         .Surface
 1364                         .Hydrophobicity
 1365                         .Hydrophobicity_Charge
 1366                 .FPocket<ID>
 1367                     .FPocket
 1368                     .Residues
 1369                     .Surface
 1370                         .Surface
 1371                         .Hydrophobicity
 1372                         .Hydrophobicity_Charge
 1373             .Chain<ID>
 1374                     ... ... ...
 1375                 .FPocket<ID>
 1376                     ... ... ...
 1377                 .FPocket<ID>
 1378                     ... ... ...
 1379             .Chain<ID>
 1380                 ... ... ...
 1381         <PDBFileRoot>
 1382             .Complex
 1383                 ... ... ...
 1384             .Chain<ID>
 1385                 ... ... ...
 1386                 .FPocket<ID>
 1387                     ... ... ...
 1388                 .FPocket<ID>
 1389                     ... ... ...
 1390             .Chain<ID>
 1391                 ... ... ...
 1392 
 1393 Options:
 1394     -a, --align <yes or no>  [default: no]
 1395         Align input files to a reference file before visualization.
 1396     --alignMethod <align, cealign, super>  [default: super]
 1397         Alignment methodology to use for aligning input files to a
 1398         reference file.
 1399     --alignMode <FirstChain or Complex>  [default: FirstChain]
 1400         Portion of input and reference files to use for spatial alignment of
 1401         input files against reference file.  Possible values: FirstChain or
 1402         Complex.
 1403         
 1404         The FirstChain mode allows alignment of the first chain in each input
 1405         file to the first chain in the reference file along with moving the rest
 1406         of the complex to coordinate space of the reference file. The complete
 1407         complex in each input file is aligned to the complete complex in reference
 1408         file for the Complex mode.
 1409     --alignRefFile <filename>  [default: FirstInputFile]
 1410         Reference input file name. The default is to use the first input file
 1411         name specified using '-i, --infiles' option.
 1412     -c, --chainIDs <First, All or ID1,ID2...>  [default: First]
 1413         List of chain IDs to use for visualizing fpockets in macromolecules. Possible
 1414         values: First, All, or a comma delimited list of chain IDs. The default is to
 1415         use the chain ID for the first chain in each input file.
 1416     -e, --examples
 1417         Print examples.
 1418     -f, --fpocketMode <All, TopN, or Specify>  [default: All]
 1419         Fpockets specification mode for visualizing fpockets across chains in
 1420         macromolecules. Possible values: All, TopN, or specify. By default, all
 1421         available fpockets are visualized across specified chains.
 1422         
 1423         The fpocket IDs must be specified using '--fpocketIDs' option for 'TopN'
 1424         and 'Specifiy' value of '--fpocketMode '.
 1425     --fpocketIDs <Value or Value1,Value2...>
 1426         List of Fpocket IDs for visualizing fpockets across chains. This value is
 1427         dependent on the value of '--fpocketMode'. The possible values are
 1428         either a number or a comma delimited list of number for 'TopN' and 
 1429         'Specify' value '--fpocketMode' option. For example:
 1430         
 1431         This option is ignored during 'All' value of '--fpocketMode' option.
 1432     --fpocketPropertiesAppend <yes or no>  [default: yes]
 1433         Append fpocket properties to names of PyMOL fpocket groups and
 1434         objects. The following properties are appended to the names of PyMOL
 1435          groups using their abbreviations and values:  PocketScore - S; DrugScore - D;
 1436          PocketVolume - V; HydrophobicityScore - H;  PolarityScore - P.
 1437          For example:
 1438          
 1439          Fpocket1_S0p50_D0p00_V638p81_Hneg6p67_P11p00.Fpocket
 1440     -h, --help
 1441         Print this help message.
 1442     -i, --infiles <infile1,infile2,infile3...>
 1443         Input PDB file names. The current directory must contain the results from
 1444         Fpocket calculations for all the input PDB files.
 1445     --labelFontID <number>  [default: 7]
 1446         Font ID for drawing labels. Default: 7 (Sans Bold). Valid values: 5 to 16.
 1447         The specified value must be a valid PyMOL font ID. No validation is
 1448         performed. The complete lists of valid font IDs is available at:
 1449         pymolwiki.org/index.php/Label_font_id. Examples: 5 - Sans;
 1450         7 - Sans Bold; 9 - Serif; 10 - Serif Bold.
 1451     -o, --outfile <outfile>
 1452         PML output file name for visualizing fpockets. The PML outfile is created
 1453         in a new output directory named <OutfileRoot>_out_PyMOL. In addition, the
 1454         output directory contains all appropriate PDB files generated by Fpocket for
 1455         visualization of fpockets in PyMOL.
 1456     --outfilesDir <outfilesDir>  [default: auto]
 1457         Output files directory name. Default: <OutfileRoot>_out_PyMOL.
 1458     --pocketColorByPocketNum <yes or no>  [default: yes]
 1459         Color fpocket residues and residue labels by pocket number. Otherwise,
 1460         the pocket residues are colored by element names using default PyMOL
 1461         color scheme. No color is set for residue labels.
 1462     --pocketLabel <yes or no>  [default: yes]
 1463         Display residue labels on fpocket residues. The residue number is always
 1464         appended to residue label. You may specify a one or thee letter residue
 1465         labels using '--pocketLabelType' option.
 1466     --pocketLabelType <OneLetter or ThreeLetter>  [default: OneLetter]
 1467         Display one or three letter residue labels on fpocket residues
 1468     --pocketSurface <yes or no>  [default: yes]
 1469         Surfaces around fpocket residues colored by hydrophobicity alone and
 1470         both hydrophobicity and charge. The hydrophobicity surface is colored
 1471         at residue level using Eisenberg hydrophobicity scale for residues and color
 1472         gradient specified by '--surfaceColorPalette' option. The  hydrophobicity and
 1473         charge surface is colored at atom level using colors specified for
 1474         groups of atoms by '--surfaceAtomTypesColors' option. This scheme allows
 1475         simultaneous mapping of hyrophobicity and charge values on the surfaces.
 1476         
 1477         In addition, generic surfaces colored by '--surfaceColor' are always created
 1478         for pockets.
 1479     --sphereScale <number>  [default: 0.4]
 1480         Scaling factor for spheres used to display fpocket alpha spheres.
 1481     --sphereTransparency <number>  [default: 0.25]
 1482         Transparency for spheres used to display fpocket alpha spheres.
 1483     --surfaceChain <yes or no>  [default: yes]
 1484         Surfaces around individual chain colored by hydrophobicity alone and
 1485         both hydrophobicity and charge. The hydrophobicity surface is colored
 1486         at residue level using Eisenberg hydrophobicity scale for residues and color
 1487         gradient specified by '--surfaceColorPalette' option. The  hydrophobicity and
 1488         charge surface is colored at atom level using colors specified for
 1489         groups of atoms by '--surfaceAtomTypesColors' option. This scheme allows
 1490         simultaneous mapping of hyrophobicity and charge values on the surfaces.
 1491         
 1492         In addition, generic surfaces colored by '--surfaceColor' are always created
 1493         for chains.
 1494     --surfaceAtomTypesColors <ColorType,ColorSpec,...>  [default: auto]
 1495         Atom colors for generating surfaces colored by hyrophobicity and charge
 1496         around chains and pockets in proteins. It's a pairwise comma delimited list
 1497         of atom color type and color specification for groups of atoms.
 1498         
 1499         The default values for color types  along wth color specifications
 1500         are shown below: 
 1501             
 1502             HydrophobicAtomsColor, yellow,
 1503             NegativelyChargedAtomsColor, red,
 1504             PositivelyChargedAtomsColor, blue,
 1505             OtherAtomsColor, gray90
 1506             
 1507         The color names must be valid PyMOL names.
 1508         
 1509         The color values may also be specified as space delimited RGB triplets:
 1510              
 1511             HydrophobicAtomsColor, 0.95 0.78 0.0,
 1512             NegativelyChargedAtomsColor, 1.0 0.4 0.4,
 1513             PositivelyChargedAtomsColor, 0.2 0.5 0.8,
 1514             OtherAtomsColor, 0.95 0.95 0.95
 1515             
 1516     --surfaceColor <ColorName>  [default: lightblue]
 1517         Color name for surfaces around chains and pockets. This color is not used
 1518         for surfaces colored by hydrophobicity and charge. The color name must be
 1519         a valid PyMOL name.
 1520     --surfaceColorPalette <RedToWhite or WhiteToGreen>  [default: RedToWhite]
 1521         Color palette for hydrophobic surfaces around chains and pockets in proteins.
 1522         Possible values: RedToWhite or WhiteToGreen from most hydrophobic amino
 1523         acid to least hydrophobic. The colors values for amino acids are taken from
 1524         color_h script available as part of the Script Library at PyMOL Wiki.
 1525     --surfaceTransparency <number>  [default: 0.25]
 1526         Surface transparency for molecular surfaces.
 1527     --overwrite
 1528         Overwrite existing files.
 1529     -w, --workingdir <dir>
 1530         Location of working directory which defaults to the current directory.
 1531 
 1532 Examples:
 1533     To visualize all fpockets available in a directory <PDBRoot>_out for the first
 1534     chain, along pocket residues and surfaces, in a PDB file, and generate a PML
 1535     file in a new directory <PDBRoot>_out_pymol, type:
 1536 
 1537         % PyMOLVisualizeFpockets.py -i Sample5.pdb -o Sample5.pml
 1538 
 1539     To rerun the first example without displaying pocket residue labels,
 1540     coloring pockets by element type, and write out a PML file, type:
 1541 
 1542         % PyMOLVisualizeFpockets.py --pocketColorByPocketNum no
 1543           --pocketLabel no -i Sample5.pdb -o Sample5.pml
 1544 
 1545     To rerun the first example to visualize only top 5 fpockets and write out a
 1546     PML file, type:
 1547 
 1548         % PyMOLVisualizeFpockets.py -f TopN --fpocketIDs 5 -i Sample5.pdb
 1549           -o Sample5.pml
 1550 
 1551     To rerun the first example to visualize a specific set of fpockets and write
 1552     out a PML file, type:
 1553 
 1554         % PyMOLVisualizeFpockets.py -f Specify --fpocketIDs "1,2,3" -i Sample5.pdb
 1555           -o Sample5.pml
 1556 
 1557    To rerun the first example to visualize all fpockets across all chains and write
 1558    out a PML file, type:
 1559 
 1560         % PyMOLVisualizeFpockets.py -c All -f All -i Sample5.pdb -o Sample5.pml
 1561 
 1562     To rerun the first example without displaying hydrophobic and charge surfaces
 1563     around chain and pockets and and write out a PML file, type:
 1564 
 1565         % PyMOLVisualizeFpockets.py --surfaceChain no  --pocketSurface no
 1566           -i Sample5.pdb -o Sample5.pml
 1567 
 1568     To visualize top 5 fpockets available in a directories <PDBRoot>_out for the
 1569     first chain, along pocket residues and surfaces, in PDB files, aligning first
 1570     fchain in each input file to the first chain in first input file, and generate a
 1571     PML file in a new directory <PDBRoot>_out_pymol, type:
 1572 
 1573         % PyMOLVisualizeFpockets.py -f TopN --fpocketIDs 5 --align yes
 1574           -i "Sample5.pdb,Sample6.pdb" -o Sample5Aligned.pml
 1575 
 1576     To visualize top 5 fpockets available in a directories <PDBRoot>_out for the
 1577     first chain, along pocket residues and surfaces, in PDB files, aligning first
 1578     chain in each input file to the first chain in first chain in a specified PDB
 1579     file using a specified alignment method,, and generate a PML file in a new
 1580     directory <PDBRoot>_out_pymol, type:
 1581 
 1582         % PyMOLVisualizeFpockets.py -f TopN --fpocketIDs 5 --align yes
 1583           --alignMode FirstChain --alignRefFile Sample6.pdb --alignMethod super 
 1584           -i "Sample5.pdb,Sample6.pdb" -o Sample5Aligned.pml
 1585 
 1586 Author:
 1587     Manish Sud
 1588 
 1589 Collaborators:
 1590     Joann Prescott-Roy and Pat Walters
 1591 
 1592 See also:
 1593     DownloadPDBFiles.pl, PyMOLVisualizeCavities.py,
 1594     PyMOLVisualizeCryoEMDensity.py, PyMOLVisualizeElectronDensity.py,
 1595     PyMOLVisualizeInterfaces.py, PyMOLVisualizeMacromolecules.py,
 1596     PyMOLVisualizeSurfaceAndBuriedResidues.py
 1597 
 1598 Copyright:
 1599     Copyright (C) 2024 Manish Sud. All rights reserved.
 1600 
 1601     The functionality available in this script is implemented using PyMOL, a
 1602     molecular visualization system on an open source foundation originally
 1603     developed by Warren DeLano.
 1604 
 1605     This file is part of MayaChemTools.
 1606 
 1607     MayaChemTools is free software; you can redistribute it and/or modify it under
 1608     the terms of the GNU Lesser General Public License as published by the Free
 1609     Software Foundation; either version 3 of the License, or (at your option) any
 1610     later version.
 1611 
 1612 """
 1613 
 1614 if __name__ == "__main__":
 1615     main()