MayaChemTools

    1 #!/bin/env python
    2 #
    3 # File: PyMOLVisualizeCavities.py
    4 # Author: Manish Sud <msud@san.rr.com>
    5 #
    6 # Copyright (C) 2024 Manish Sud. All rights reserved.
    7 #
    8 # The functionality available in this script is implemented using PyMOL, a
    9 # molecular visualization system on an open source foundation originally
   10 # developed by Warren DeLano.
   11 #
   12 # This file is part of MayaChemTools.
   13 #
   14 # MayaChemTools is free software; you can redistribute it and/or modify it under
   15 # the terms of the GNU Lesser General Public License as published by the Free
   16 # Software Foundation; either version 3 of the License, or (at your option) any
   17 # later version.
   18 #
   19 # MayaChemTools is distributed in the hope that it will be useful, but without
   20 # any warranty; without even the implied warranty of merchantability of fitness
   21 # for a particular purpose.  See the GNU Lesser General Public License for more
   22 # details.
   23 #
   24 # You should have received a copy of the GNU Lesser General Public License
   25 # along with MayaChemTools; if not, see <http://www.gnu.org/licenses/> or
   26 # write to the Free Software Foundation Inc., 59 Temple Place, Suite 330,
   27 # Boston, MA, 02111-1307, USA.
   28 #
   29 
   30 from __future__ import print_function
   31 
   32 # Add local python path to the global path and import standard library modules...
   33 import os
   34 import sys;  sys.path.insert(0, os.path.join(os.path.dirname(sys.argv[0]), "..", "lib", "Python"))
   35 import time
   36 import re
   37 
   38 # PyMOL imports...
   39 try:
   40     import pymol
   41     # Finish launching PyMOL in  a command line mode for batch processing (-c)
   42     # along with the following options:  disable loading of pymolrc and plugins (-k);
   43     # suppress start up messages (-q)
   44     pymol.finish_launching(['pymol', '-ckq'])
   45 except ImportError as ErrMsg:
   46     sys.stderr.write("\nFailed to import PyMOL module/package: %s\n" % ErrMsg)
   47     sys.stderr.write("Check/update your PyMOL environment and try again.\n\n")
   48     sys.exit(1)
   49 
   50 # MayaChemTools imports...
   51 try:
   52     from docopt import docopt
   53     import MiscUtil
   54     import PyMOLUtil
   55 except ImportError as ErrMsg:
   56     sys.stderr.write("\nFailed to import MayaChemTools module/package: %s\n" % ErrMsg)
   57     sys.stderr.write("Check/update your MayaChemTools environment and try again.\n\n")
   58     sys.exit(1)
   59 
   60 ScriptName = os.path.basename(sys.argv[0])
   61 Options = {}
   62 OptionsInfo = {}
   63 
   64 def main():
   65     """Start execution of the script."""
   66     
   67     MiscUtil.PrintInfo("\n%s (PyMOL v%s; MayaChemTools v%s; %s): Starting...\n" % (ScriptName, pymol.cmd.get_version()[0], MiscUtil.GetMayaChemToolsVersion(), time.asctime()))
   68     
   69     (WallClockTime, ProcessorTime) = MiscUtil.GetWallClockAndProcessorTime()
   70     
   71     # Retrieve command line arguments and options...
   72     RetrieveOptions()
   73     
   74     # Process and validate command line arguments and options...
   75     ProcessOptions()
   76 
   77     # Perform actions required by the script...
   78     GenerateCavitiesVisualization()
   79     
   80     MiscUtil.PrintInfo("\n%s: Done...\n" % ScriptName)
   81     MiscUtil.PrintInfo("Total time: %s" % MiscUtil.GetFormattedElapsedTime(WallClockTime, ProcessorTime))
   82 
   83 def GenerateCavitiesVisualization():
   84     """Generate visualization for cavities."""
   85 
   86     Outfile = OptionsInfo["PMLOutfile"]
   87     OutFH = open(Outfile, "w")
   88     if OutFH is None:
   89         MiscUtil.PrintError("Failed to open output fie %s " % Outfile)
   90     
   91     MiscUtil.PrintInfo("\nGenerating file %s..." % Outfile)
   92 
   93     # Setup header...
   94     WritePMLHeader(OutFH, ScriptName)
   95     WritePyMOLParameters(OutFH)
   96     
   97     # Load reffile for alignment..
   98     if OptionsInfo["Align"]:
   99         WriteAlignReference(OutFH)
  100 
  101     # Setup view for each input file...
  102     FirstComplex = True
  103     FirstComplexFirstChainName = None
  104     for FileIndex in range(0, len(OptionsInfo["InfilesInfo"]["InfilesNames"])):
  105         # Setup PyMOL object names...
  106         PyMOLObjectNames = SetupPyMOLObjectNames(FileIndex)
  107 
  108         # Setup complex view...
  109         WriteComplexView(OutFH, FileIndex, PyMOLObjectNames, FirstComplex)
  110         
  111         SpecifiedChainsAndLigandsInfo = OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"][FileIndex]
  112         FirstChain = True
  113         for ChainID in SpecifiedChainsAndLigandsInfo["ChainIDs"]:
  114             if FirstComplex and FirstChain:
  115                 FirstComplexFirstChainName = PyMOLObjectNames["Chains"][ChainID]["ChainAlone"]
  116                 
  117             WriteChainView(OutFH, FileIndex, PyMOLObjectNames, ChainID)
  118             
  119             # Setup ligand views...
  120             FirstLigand = True
  121             for LigandID in SpecifiedChainsAndLigandsInfo["LigandIDs"][ChainID]:
  122                 WriteChainLigandView(OutFH, FileIndex, PyMOLObjectNames, ChainID, LigandID)
  123                 
  124                 # Set up ligand level group...
  125                 Enable, Action = [False, "close"]
  126                 if FirstLigand:
  127                     FirstLigand = False
  128                     Enable, Action = [True, "open"]
  129                 GenerateAndWritePMLForGroup(OutFH, PyMOLObjectNames["Ligands"][ChainID][LigandID]["ChainLigandGroup"], PyMOLObjectNames["Ligands"][ChainID][LigandID]["ChainLigandGroupMembers"], Enable, Action)
  130             
  131             # Setup Chain level group...
  132             Enable, Action = [False, "close"]
  133             if FirstChain:
  134                 FirstChain = False
  135                 Enable, Action = [True, "open"]
  136             GenerateAndWritePMLForGroup(OutFH, PyMOLObjectNames["Chains"][ChainID]["ChainGroup"], PyMOLObjectNames["Chains"][ChainID]["ChainGroupMembers"], Enable, Action)
  137     
  138         # Set up complex level group...
  139         Enable, Action = [False, "close"]
  140         if FirstComplex:
  141             FirstComplex = False
  142             Enable, Action = [True, "open"]
  143         GenerateAndWritePMLForGroup(OutFH, PyMOLObjectNames["PDBGroup"], PyMOLObjectNames["PDBGroupMembers"], Enable, Action)
  144         
  145         # Delete empty PyMOL objects...
  146         DeleteEmptyPyMOLObjects(OutFH, FileIndex, PyMOLObjectNames)
  147         
  148     if OptionsInfo["Align"]:
  149         DeleteAlignReference(OutFH)
  150 
  151     if FirstComplexFirstChainName is not None:
  152         OutFH.write("""\ncmd.orient("%s", animate = -1)\n""" % FirstComplexFirstChainName)
  153     else:
  154         OutFH.write("""\ncmd.orient("visible", animate = -1)\n""")
  155     
  156     OutFH.close()
  157 
  158     # Generate PSE file as needed...
  159     if OptionsInfo["PSEOut"]:
  160         GeneratePyMOLSessionFile()
  161 
  162 def WritePMLHeader(OutFH, ScriptName):
  163     """Write out PML setting up complex view."""
  164 
  165     HeaderInfo = PyMOLUtil.SetupPMLHeaderInfo(ScriptName)
  166     OutFH.write("%s\n" % HeaderInfo)
  167 
  168 def WritePyMOLParameters(OutFH):
  169     """Write out PyMOL global parameters."""
  170 
  171     PMLCmds = []
  172     PMLCmds.append("""cmd.set("transparency", %.2f, "", 0)""" % (OptionsInfo["SurfaceTransparency"]))
  173     PMLCmds.append("""cmd.set("label_font_id", %s)""" % (OptionsInfo["LabelFontID"]))
  174 
  175     PMLCmds.append("""cmd.set("cavity_cull", %.1f, "", 0)""" % (OptionsInfo["CavityCullSize"]))
  176     PMLCmds.append("""cmd.set("surface_cavity_radius", -%.1f, "", 0)""" % (OptionsInfo["CavityRadius"]))
  177     PMLCmds.append("""cmd.set("surface_cavity_cutoff", -%.1f, "", 0)""" % (OptionsInfo["CavityCutoff"]))
  178     
  179     PML = "\n".join(PMLCmds)
  180     
  181     OutFH.write("""\n""\n"Setting up PyMOL gobal parameters..."\n""\n""")
  182     OutFH.write("%s\n" % PML)
  183     
  184 def WriteAlignReference(OutFH):
  185     """Setup object for alignment reference."""
  186 
  187     RefFileInfo = OptionsInfo["RefFileInfo"]
  188     RefFile = RefFileInfo["RefFileName"]
  189     RefName = RefFileInfo["PyMOLObjectName"]
  190     
  191     PMLCmds = []
  192     PMLCmds.append("""cmd.load("%s", "%s")""" % (RefFile, RefName))
  193     PMLCmds.append("""cmd.hide("everything", "%s")""" % (RefName))
  194     PMLCmds.append("""cmd.disable("%s")""" % (RefName))
  195     PML = "\n".join(PMLCmds)
  196     
  197     OutFH.write("""\n""\n"Loading %s and setting up view for align reference..."\n""\n""" % RefFile)
  198     OutFH.write("%s\n" % PML)
  199     
  200 def WriteAlignComplex(OutFH, FileIndex, PyMOLObjectNames):
  201     """Setup alignment of complex to reference."""
  202 
  203     RefFileInfo = OptionsInfo["RefFileInfo"]
  204     RefName = RefFileInfo["PyMOLObjectName"]
  205     
  206     ComplexName = PyMOLObjectNames["Complex"]
  207     
  208     if re.match("^FirstChain$", OptionsInfo["AlignMode"], re.I):
  209         RefFirstChainID = RefFileInfo["ChainsAndLigandsInfo"]["ChainIDs"][0]
  210         RefAlignSelection = "%s and chain %s" % (RefName, RefFirstChainID)
  211         
  212         ComplexFirstChainID = RetrieveFirstChainID(FileIndex)
  213         ComplexAlignSelection = "%s and chain %s" % (ComplexName, ComplexFirstChainID)
  214     else:
  215         RefAlignSelection = RefName
  216         ComplexAlignSelection = ComplexName
  217 
  218     PML = PyMOLUtil.SetupPMLForAlignment(OptionsInfo["AlignMethod"], RefAlignSelection, ComplexAlignSelection)
  219     OutFH.write("""\n""\n"Aligning %s against reference %s ..."\n""\n""" % (ComplexAlignSelection, RefAlignSelection))
  220     OutFH.write("%s\n" % PML)
  221     
  222 def DeleteAlignReference(OutFH):
  223     """Delete alignment reference object."""
  224     
  225     RefName = OptionsInfo["RefFileInfo"]["PyMOLObjectName"]
  226     OutFH.write("""\n""\n"Deleting alignment reference object %s..."\n""\n""" % RefName)
  227     OutFH.write("""cmd.delete("%s")\n""" % RefName)
  228 
  229 def WriteComplexView(OutFH, FileIndex, PyMOLObjectNames, FirstComplex):
  230     """Write out PML for viewing polymer complex."""
  231 
  232     # Setup complex...
  233     Infile = OptionsInfo["InfilesInfo"]["InfilesNames"][FileIndex]
  234     PML = PyMOLUtil.SetupPMLForPolymerComplexView(PyMOLObjectNames["Complex"], Infile, True)
  235     OutFH.write("""\n""\n"Loading %s and setting up view for complex..."\n""\n""" % Infile)
  236     OutFH.write("%s\n" % PML)
  237 
  238     if OptionsInfo["Align"]:
  239         # No need to align complex on to itself...
  240         if not (re.match("^FirstInputFile$", OptionsInfo["AlignRefFile"], re.I) and FirstComplex):
  241             WriteAlignComplex(OutFH, FileIndex, PyMOLObjectNames)
  242     
  243     if OptionsInfo["SurfaceComplex"]:
  244         # Setup hydrophobic surface...
  245         PML = PyMOLUtil.SetupPMLForHydrophobicSurfaceView(PyMOLObjectNames["ComplexHydrophobicSurface"], PyMOLObjectNames["Complex"], ColorPalette = OptionsInfo["SurfaceColorPalette"], Enable = False)
  246         OutFH.write("\n%s\n" % PML)
  247     
  248     # Setup complex group...
  249     GenerateAndWritePMLForGroup(OutFH, PyMOLObjectNames["ComplexGroup"], PyMOLObjectNames["ComplexGroupMembers"], False, "close")
  250 
  251 def WriteChainView(OutFH, FileIndex, PyMOLObjectNames, ChainID):
  252     """Write out PML for viewing chain."""
  253     
  254     OutFH.write("""\n""\n"Setting up views for chain %s..."\n""\n""" % ChainID)
  255     
  256     ChainComplexName = PyMOLObjectNames["Chains"][ChainID]["ChainComplex"]
  257     
  258     # Setup chain complex group view...
  259     WriteChainComplexViews(OutFH, FileIndex, PyMOLObjectNames, ChainID)
  260 
  261     # Setup chain view...
  262     WriteChainAloneViews(OutFH, FileIndex, PyMOLObjectNames, ChainID)
  263     
  264     # Setup chain solvent view...
  265     PML = PyMOLUtil.SetupPMLForSolventView(PyMOLObjectNames["Chains"][ChainID]["Solvent"], ChainComplexName, False)
  266     OutFH.write("\n%s\n" % PML)
  267 
  268     # Setup chain inorganic view...
  269     PML = PyMOLUtil.SetupPMLForInorganicView(PyMOLObjectNames["Chains"][ChainID]["Inorganic"], ChainComplexName, False)
  270     OutFH.write("\n%s\n" % PML)
  271 
  272 def WriteChainComplexViews(OutFH, FileIndex, PyMOLObjectNames, ChainID):
  273     """Write chain complex views."""
  274     
  275     # Setup chain complex...
  276     ChainComplexName = PyMOLObjectNames["Chains"][ChainID]["ChainComplex"]
  277     PML = PyMOLUtil.SetupPMLForPolymerChainComplexView(ChainComplexName, PyMOLObjectNames["Complex"], ChainID, True)
  278     OutFH.write("%s\n" % PML)
  279 
  280     if OptionsInfo["SurfaceChainComplex"]:
  281         # Setup hydrophobic surface...
  282         PML = PyMOLUtil.SetupPMLForHydrophobicSurfaceView(PyMOLObjectNames["Chains"][ChainID]["ChainComplexHydrophobicSurface"], ChainComplexName, ColorPalette = OptionsInfo["SurfaceColorPalette"], Enable = False)
  283         OutFH.write("\n%s\n" % PML)
  284     
  285     # Setup chain complex group...
  286     GenerateAndWritePMLForGroup(OutFH, PyMOLObjectNames["Chains"][ChainID]["ChainComplexGroup"], PyMOLObjectNames["Chains"][ChainID]["ChainComplexGroupMembers"], False, "close")
  287     
  288 def WriteChainAloneViews(OutFH, FileIndex, PyMOLObjectNames, ChainID):
  289     """Write individual chain views."""
  290 
  291     ChainComplexName = PyMOLObjectNames["Chains"][ChainID]["ChainComplex"]
  292     
  293     # Setup chain view...
  294     ChainName = PyMOLObjectNames["Chains"][ChainID]["ChainAlone"]
  295     PML = PyMOLUtil.SetupPMLForPolymerChainView(ChainName, ChainComplexName, True)
  296     OutFH.write("\n%s\n" % PML)
  297 
  298     WriteChainAloneResidueTypesView(OutFH,  FileIndex, PyMOLObjectNames, ChainID)
  299     WriteChainAloneCavitiesAndSurfacesView(OutFH,  FileIndex, PyMOLObjectNames, ChainID)
  300 
  301     # Setup chain group...
  302     GenerateAndWritePMLForGroup(OutFH, PyMOLObjectNames["Chains"][ChainID]["ChainAloneGroup"], PyMOLObjectNames["Chains"][ChainID]["ChainAloneGroupMembers"], True, "open")
  303 
  304 def WriteChainLigandView(OutFH, FileIndex, PyMOLObjectNames, ChainID, LigandID):
  305     """Write out PML for viewing ligand in a chain."""
  306 
  307     GroupID = "Ligand"
  308     ComplexName = PyMOLObjectNames["Chains"][ChainID]["ChainComplex"]
  309     LigandName = PyMOLObjectNames["Ligands"][ChainID][LigandID]["Ligand"]
  310     
  311     # Setup main object...
  312     GroupTypeObjectID = "%s" % (GroupID)
  313     GroupTypeObjectName = PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupTypeObjectID]
  314     
  315     OutFH.write("""\n""\n"Setting up views for ligand %s in chain %s..."\n""\n""" % (LigandID, ChainID))
  316     PML = PyMOLUtil.SetupPMLForLigandView(GroupTypeObjectName, ComplexName, LigandID, Enable = True, IgnoreHydrogens = OptionsInfo["IgnoreHydrogens"])
  317     OutFH.write("%s\n" % PML)
  318     
  319     # Setup ball and stick view...
  320     BallAndStickNameID = "%sBallAndStick" % (GroupID)
  321     BallAndStickName = PyMOLObjectNames["Ligands"][ChainID][LigandID][BallAndStickNameID]
  322     PML = PyMOLUtil.SetupPMLForBallAndStickView(BallAndStickName, GroupTypeObjectName, Enable = False)
  323     OutFH.write("\n%s\n" % PML)
  324             
  325     # Setup group....
  326     GroupNameID = "%sGroup" % (GroupID)
  327     GroupMembersID = "%sGroupMembers" % (GroupID)
  328     GroupName = PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupNameID]
  329     GroupMembers = PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupMembersID]
  330 
  331     Action = "close"
  332     Enable = True
  333     GenerateAndWritePMLForGroup(OutFH, GroupName, GroupMembers, Enable, Action)
  334 
  335 def WriteChainAloneCavitiesAndSurfacesView(OutFH,  FileIndex, PyMOLObjectNames, ChainID):
  336     """Write out PML for viewing cavities and pockets in chains."""
  337 
  338     if not GetChainAloneContainsSurfacesStatus(FileIndex, ChainID):
  339         return
  340     
  341     ChainName = PyMOLObjectNames["Chains"][ChainID]["ChainAlone"]
  342     
  343     for SubGroupType in ["Cavities", "Surface"]:
  344         SubGroupID = "ChainAlone%sGroup" % (SubGroupType)
  345         SubGroupMembersID = "%sMembers" % (SubGroupID)
  346         
  347         ProcessingCavities = True if re.match("^Cavities$", SubGroupType, re.I) else False
  348         
  349         # Turn off lines display for cavity surfaces...
  350         DisplayStyle = None if ProcessingCavities else "cartoon"
  351         
  352         # Setup a generic color surface...
  353         SurfaceID = "%sSurface" % (SubGroupID)
  354         SurfaceName = PyMOLObjectNames["Chains"][ChainID][SurfaceID]
  355         ColorName =  OptionsInfo["SurfaceCavityColor"] if ProcessingCavities else OptionsInfo["SurfaceColor"]
  356         EnableStatus =  True if ProcessingCavities else False
  357         PML = PyMOLUtil.SetupPMLForSurfaceView(SurfaceName, ChainName,  Enable = EnableStatus, Color = ColorName)
  358         OutFH.write("\n%s\n" % PML)
  359         
  360         if ProcessingCavities:
  361             OutFH.write("""cmd.set("surface_cavity_mode", %d, "%s")\n""" % (OptionsInfo["SurfaceCavityMode"], SurfaceName))
  362         
  363         if GetChainAloneSurfaceChainStatus(FileIndex, ChainID):
  364             # Setup surface colored by hydrophobicity...
  365             HydrophobicSurfaceID = "%sHydrophobicSurface" % (SubGroupID)
  366             HydrophobicSurfaceName = PyMOLObjectNames["Chains"][ChainID][HydrophobicSurfaceID]
  367             PML = PyMOLUtil.SetupPMLForHydrophobicSurfaceView(HydrophobicSurfaceName, ChainName, ColorPalette = OptionsInfo["SurfaceColorPalette"], Enable = False)
  368             OutFH.write("\n%s\n" % PML)
  369             
  370             if ProcessingCavities:
  371                 OutFH.write("""cmd.set("surface_cavity_mode", %d, "%s")\n""" % (OptionsInfo["SurfaceCavityMode"], HydrophobicSurfaceName))
  372             
  373             # Setup surface colored by hyrdophobicity and charge...
  374             HydrophobicChargeSurfaceID = "%sHydrophobicChargeSurface" % (SubGroupID)
  375             HydrophobicChargeSurfaceName = PyMOLObjectNames["Chains"][ChainID][HydrophobicChargeSurfaceID]
  376             PML = PyMOLUtil.SetupPMLForHydrophobicAndChargeSurfaceView(HydrophobicChargeSurfaceName, ChainName, OptionsInfo["AtomTypesColorNames"]["HydrophobicAtomsColor"], OptionsInfo["AtomTypesColorNames"]["NegativelyChargedAtomsColor"], OptionsInfo["AtomTypesColorNames"]["PositivelyChargedAtomsColor"], OptionsInfo["AtomTypesColorNames"]["OtherAtomsColor"], Enable = False, DisplayAs = None)
  377             OutFH.write("\n%s\n" % PML)
  378             
  379             if ProcessingCavities:
  380                 OutFH.write("""cmd.set("surface_cavity_mode", %d, "%s")\n""" % (OptionsInfo["SurfaceCavityMode"], HydrophobicChargeSurfaceName))
  381         
  382         if GetChainAloneSurfaceChainElectrostaticsStatus(FileIndex, ChainID):
  383             # Setup electrostatics surface...
  384             ElectrostaticsGroupID = "%sElectrostaticsGroup" % (SubGroupID)
  385             ElectrostaticsGroupMembersID = "%sElectrostaticsGroupMembers" % (SubGroupID)
  386             ElectrostaticsGroupName = PyMOLObjectNames["Chains"][ChainID][ElectrostaticsGroupID]
  387             ElectrostaticsGroupMembers = PyMOLObjectNames["Chains"][ChainID][ElectrostaticsGroupMembersID]
  388             WriteSurfaceElectrostaticsView(SubGroupType, OutFH, ChainName, ElectrostaticsGroupName, ElectrostaticsGroupMembers, DisplayAs = DisplayStyle, SurfaceCavityMode = OptionsInfo["SurfaceCavityMode"])
  389 
  390         # Setup surface group...
  391         GenerateAndWritePMLForGroup(OutFH, PyMOLObjectNames["Chains"][ChainID][SubGroupID], PyMOLObjectNames["Chains"][ChainID][SubGroupMembersID], True, "open")
  392 
  393 def WriteChainAloneResidueTypesView(OutFH,  FileIndex, PyMOLObjectNames, ChainID):
  394     """Write out PML for viewing residue types for a chain."""
  395 
  396     if not GetChainAloneResidueTypesStatus(FileIndex, ChainID):
  397         return
  398     
  399     ChainName = PyMOLObjectNames["Chains"][ChainID]["ChainAlone"]
  400     
  401     # Setup residue types objects...
  402     ResiduesGroupIDPrefix = "ChainAloneResidues"
  403     for SubGroupType in ["Aromatic", "Hydrophobic", "Polar", "Positively_Charged", "Negatively_Charged", "Other"]:
  404         SubGroupID = re.sub("_", "", SubGroupType)
  405 
  406         ResiduesObjectID = "%s%sResidues" % (ResiduesGroupIDPrefix, SubGroupID)
  407         ResiduesObjectName = PyMOLObjectNames["Chains"][ChainID][ResiduesObjectID]
  408 
  409         ResiduesSurfaceObjectID = "%s%sSurface" % (ResiduesGroupIDPrefix, SubGroupID)
  410         ResiduesSurfaceObjectName = PyMOLObjectNames["Chains"][ChainID][ResiduesSurfaceObjectID]
  411 
  412         ResiduesColor = OptionsInfo["ResidueTypesParams"][SubGroupType]["Color"] 
  413         ResiduesNames = OptionsInfo["ResidueTypesParams"][SubGroupType]["Residues"]
  414 
  415         NegateResidueNames = True if re.match("^Other$", SubGroupType, re.I) else False
  416         WriteResidueTypesResiduesAndSurfaceView(OutFH, ChainName, ResiduesObjectName, ResiduesSurfaceObjectName, ResiduesColor, ResiduesNames, NegateResidueNames)
  417 
  418         # Setup sub groups for residue types..
  419         ResiduesSubGroupID = "%s%sGroup" % (ResiduesGroupIDPrefix, SubGroupID)
  420         ResiduesSubGroupMembersID = "%s%sGroupMembers" % (ResiduesGroupIDPrefix, SubGroupID)
  421 
  422         # Setup residue type sub groups...
  423         GenerateAndWritePMLForGroup(OutFH, PyMOLObjectNames["Chains"][ChainID][ResiduesSubGroupID], PyMOLObjectNames["Chains"][ChainID][ResiduesSubGroupMembersID], True, "close")
  424         
  425     # Setup residue types group...
  426     GenerateAndWritePMLForGroup(OutFH, PyMOLObjectNames["Chains"][ChainID]["ChainAloneResiduesGroup"], PyMOLObjectNames["Chains"][ChainID]["ChainAloneResiduesGroupMembers"], False, "close")
  427 
  428 def WriteResidueTypesResiduesAndSurfaceView(OutFH, SelectionObjectName, Name, SurfaceName, ResiduesColor, ResiduesNames, NegateResidueNames):
  429     """Write residue types residues and surface view."""
  430 
  431     ResidueNamesSelection = "+".join(ResiduesNames)
  432     if NegateResidueNames:
  433         Selection = "%s and (not resn %s)" % (SelectionObjectName, ResidueNamesSelection)
  434     else:
  435         Selection = "%s and (resn %s)" % (SelectionObjectName, ResidueNamesSelection)
  436 
  437     # Setup residues...
  438     PML = PyMOLUtil.SetupPMLForSelectionDisplayView(Name, Selection, "lines", ResiduesColor, True)
  439     OutFH.write("\n%s\n" % PML)
  440 
  441     # Setup surface...
  442     PML = PyMOLUtil.SetupPMLForSelectionDisplayView(SurfaceName, Selection, "surface", ResiduesColor, True)
  443     OutFH.write("\n%s\n" % PML)
  444     
  445 def WriteSurfaceElectrostaticsView(Mode, OutFH, SelectionObjectName, ElectrostaticsGroupName, ElectrostaticsGroupMembers, DisplayAs = None, SurfaceCavityMode = 2):
  446     """Write out PML for viewing surface electrostatics."""
  447 
  448     if len(ElectrostaticsGroupMembers) == 5:
  449         Name, ContactPotentialName, MapName, LegendName, VolumeName = ElectrostaticsGroupMembers
  450     else:
  451         Name, ContactPotentialName, MapName, LegendName = ElectrostaticsGroupMembers
  452         VolumeName = None
  453 
  454     PMLCmds = []
  455 
  456     # Setup chain...
  457     PMLCmds.append("""cmd.create("%s", "(%s)")""" % (Name, SelectionObjectName))
  458 
  459     # Setup vacuum electrostatics surface along with associated objects...
  460     PMLCmds.append("""util.protein_vacuum_esp("%s", mode=2, quiet=0, _self=cmd)""" % (Name))
  461     PMLCmds.append("""cmd.set_name("%s_e_chg", "%s")""" % (Name, ContactPotentialName))
  462     
  463     if DisplayAs is not None:
  464         PMLCmds.append("""cmd.show("%s", "(%s)")""" % (DisplayAs, ContactPotentialName))
  465 
  466     if re.match("^Cavities$", Mode, re.I):
  467         if SurfaceCavityMode is not None:
  468             PMLCmds.append("""cmd.set("surface_cavity_mode", %d, "%s")\n""" % (SurfaceCavityMode, ContactPotentialName))
  469         
  470     PMLCmds.append(PyMOLUtil.SetupPMLForEnableDisable(ContactPotentialName, Enable = True))
  471     
  472     PMLCmds.append("""cmd.set_name("%s_e_map", "%s")""" % (Name, MapName))
  473     PMLCmds.append(PyMOLUtil.SetupPMLForEnableDisable(MapName, Enable = False))
  474     
  475     PMLCmds.append("""cmd.set_name("%s_e_pot", "%s")""" % (Name, LegendName))
  476     PMLCmds.append(PyMOLUtil.SetupPMLForEnableDisable(LegendName, Enable = False))
  477 
  478     if VolumeName is not None:
  479         PMLCmds.append("""cmd.volume("%s", "%s", "%s", "(%s)")""" % (VolumeName, MapName, "esp", Name))
  480         PMLCmds.append(PyMOLUtil.SetupPMLForEnableDisable(VolumeName, Enable = False))
  481     
  482     # Delete name and take it out from the group membership. It is
  483     # is already part of ContactPotential object.
  484     PMLCmds.append("""cmd.delete("%s")""" % (Name))
  485     ElectrostaticsGroupMembers.pop(0)
  486     
  487     PML = "\n".join(PMLCmds)
  488     
  489     OutFH.write("\n%s\n" % PML)
  490     
  491     # Setup group...
  492     GenerateAndWritePMLForGroup(OutFH, ElectrostaticsGroupName, ElectrostaticsGroupMembers, False, "close")
  493 
  494 def GenerateAndWritePMLForGroup(OutFH, GroupName, GroupMembers, Enable = False, Action = "close"):
  495     """Generate and write PML for group."""
  496     
  497     PML = PyMOLUtil.SetupPMLForGroup(GroupName, GroupMembers, Enable, Action)
  498     OutFH.write("""\n""\n"Setting up group %s..."\n""\n""" % GroupName)
  499     OutFH.write("%s\n" % PML)
  500 
  501 def GeneratePyMOLSessionFile():
  502     """Generate PME file from PML file."""
  503 
  504     PSEOutfile = OptionsInfo["PSEOutfile"]
  505     PMLOutfile = OptionsInfo["PMLOutfile"]
  506     
  507     MiscUtil.PrintInfo("\nGenerating file %s..." % PSEOutfile)
  508     
  509     PyMOLUtil.ConvertPMLFileToPSEFile(PMLOutfile, PSEOutfile)
  510     
  511     if not os.path.exists(PSEOutfile):
  512         MiscUtil.PrintWarning("Failed to generate PSE file, %s..." % (PSEOutfile))
  513     
  514     if not OptionsInfo["PMLOut"]:
  515         MiscUtil.PrintInfo("Deleting file %s..." % PMLOutfile)
  516         os.remove(PMLOutfile)
  517 
  518 def DeleteEmptyPyMOLObjects(OutFH, FileIndex, PyMOLObjectNames):
  519     """Delete empty PyMOL objects."""
  520     
  521     if OptionsInfo["AllowEmptyObjects"]:
  522         return
  523     
  524     SpecifiedChainsAndLigandsInfo = OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"][FileIndex]
  525     for ChainID in SpecifiedChainsAndLigandsInfo["ChainIDs"]:
  526         OutFH.write("""\n""\n"Checking and deleting empty objects for chain %s..."\n""\n""" % (ChainID))
  527         
  528         # Delete any chain level objects...
  529         WritePMLToCheckAndDeleteEmptyObjects(OutFH, PyMOLObjectNames["Chains"][ChainID]["Solvent"])
  530         WritePMLToCheckAndDeleteEmptyObjects(OutFH, PyMOLObjectNames["Chains"][ChainID]["Inorganic"])
  531 
  532         # Delete residue type objects...
  533         DeleteEmptyChainResidueTypesObjects(OutFH, FileIndex, PyMOLObjectNames, ChainID)
  534 
  535 def DeleteEmptyChainResidueTypesObjects(OutFH, FileIndex, PyMOLObjectNames, ChainID):
  536     """Delete empty chain residue objects."""
  537     
  538     if not GetChainAloneResidueTypesStatus(FileIndex, ChainID):
  539         return
  540     
  541     ResiduesGroupIDPrefix = "ChainAloneResidues"
  542     for GroupType in ["Aromatic", "Hydrophobic", "Polar", "Positively_Charged", "Negatively_Charged", "Other"]:
  543         GroupID = re.sub("_", "", GroupType)
  544         
  545         ResiduesGroupID = "%s%sGroup" % (ResiduesGroupIDPrefix, GroupID)
  546         GroupName = PyMOLObjectNames["Chains"][ChainID][ResiduesGroupID]
  547         
  548         GroupObjectNamesList = []
  549         
  550         ResiduesObjectID = "%s%sResidues" % (ResiduesGroupIDPrefix, GroupID)
  551         ResiduesObjectName = PyMOLObjectNames["Chains"][ChainID][ResiduesObjectID]
  552         GroupObjectNamesList.append(ResiduesObjectName)
  553         
  554         ResiduesSurfaceObjectID = "%s%sSurface" % (ResiduesGroupIDPrefix, GroupID)
  555         ResiduesSurfaceObjectName = PyMOLObjectNames["Chains"][ChainID][ResiduesSurfaceObjectID]
  556         GroupObjectNamesList.append(ResiduesSurfaceObjectName)
  557         
  558         GroupObjectNames = ",".join(GroupObjectNamesList)
  559         WritePMLToCheckAndDeleteEmptyObjects(OutFH, GroupObjectNames, GroupName)
  560 
  561 def WritePMLToCheckAndDeleteEmptyObjects(OutFH, ObjectName, ParentObjectName = None):
  562     """Write PML to check and delete empty PyMOL objects."""
  563     
  564     if ParentObjectName is None:
  565         PML = """CheckAndDeleteEmptyObjects("%s")""" % (ObjectName)
  566     else:
  567         PML = """CheckAndDeleteEmptyObjects("%s", "%s")""" % (ObjectName, ParentObjectName)
  568     
  569     OutFH.write("%s\n" % PML)
  570     
  571 def SetupPyMOLObjectNames(FileIndex):
  572     """Setup hierarchy of PyMOL groups and objects for ligand centric views of
  573     chains and ligands present in input file.
  574     """
  575 
  576     PyMOLObjectNames = {}
  577     PyMOLObjectNames["Chains"] = {}
  578     PyMOLObjectNames["Ligands"] = {}
  579 
  580     # Setup groups and objects for complex...
  581     SetupPyMOLObjectNamesForComplex(FileIndex, PyMOLObjectNames)
  582     
  583     # Setup groups and objects for chain...
  584     SpecifiedChainsAndLigandsInfo = OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"][FileIndex]
  585     for ChainID in SpecifiedChainsAndLigandsInfo["ChainIDs"]:
  586         SetupPyMOLObjectNamesForChain(FileIndex, PyMOLObjectNames, ChainID)
  587         
  588         # Setup groups and objects for ligand...
  589         for LigandID in SpecifiedChainsAndLigandsInfo["LigandIDs"][ChainID]:
  590             SetupPyMOLObjectNamesForLigand(FileIndex, PyMOLObjectNames, ChainID, LigandID)
  591 
  592     return PyMOLObjectNames
  593 
  594 def SetupPyMOLObjectNamesForComplex(FileIndex, PyMOLObjectNames):
  595     """Setup groups and objects for complex."""
  596     
  597     PDBFileRoot = OptionsInfo["InfilesInfo"]["InfilesRoots"][FileIndex]
  598     
  599     PDBGroupName = "%s" % PDBFileRoot
  600     PyMOLObjectNames["PDBGroup"] = PDBGroupName
  601     PyMOLObjectNames["PDBGroupMembers"] = []
  602 
  603     ComplexGroupName = "%s.Complex" % PyMOLObjectNames["PDBGroup"]
  604     PyMOLObjectNames["ComplexGroup"] = ComplexGroupName
  605     PyMOLObjectNames["PDBGroupMembers"].append(ComplexGroupName)
  606     
  607     PyMOLObjectNames["Complex"] = "%s.Complex" % ComplexGroupName
  608     if OptionsInfo["SurfaceComplex"]:
  609         PyMOLObjectNames["ComplexHydrophobicSurface"] = "%s.Surface" % ComplexGroupName
  610 
  611     PyMOLObjectNames["ComplexGroupMembers"] = []
  612     PyMOLObjectNames["ComplexGroupMembers"].append(PyMOLObjectNames["Complex"])
  613     if OptionsInfo["SurfaceComplex"]:
  614         PyMOLObjectNames["ComplexGroupMembers"].append(PyMOLObjectNames["ComplexHydrophobicSurface"])
  615     
  616 def SetupPyMOLObjectNamesForChain(FileIndex, PyMOLObjectNames, ChainID):
  617     """Setup groups and objects for chain."""
  618     
  619     PDBGroupName = PyMOLObjectNames["PDBGroup"]
  620     
  621     PyMOLObjectNames["Chains"][ChainID] = {}
  622     PyMOLObjectNames["Ligands"][ChainID] = {}
  623     
  624     # Set up chain group and chain objects...
  625     ChainGroupName = "%s.Chain%s" % (PDBGroupName, ChainID)
  626     PyMOLObjectNames["Chains"][ChainID]["ChainGroup"] = ChainGroupName
  627     PyMOLObjectNames["PDBGroupMembers"].append(ChainGroupName)
  628     PyMOLObjectNames["Chains"][ChainID]["ChainGroupMembers"] = []
  629     
  630     # Setup chain complex group and objects...
  631     ChainComplexGroupName = "%s.Complex" % (ChainGroupName)
  632     PyMOLObjectNames["Chains"][ChainID]["ChainComplexGroup"] = ChainComplexGroupName
  633     PyMOLObjectNames["Chains"][ChainID]["ChainGroupMembers"].append(ChainComplexGroupName)
  634 
  635     PyMOLObjectNames["Chains"][ChainID]["ChainComplexGroupMembers"] = []
  636     
  637     Name = "%s.Complex" % (ChainComplexGroupName)
  638     PyMOLObjectNames["Chains"][ChainID]["ChainComplex"] = Name
  639     PyMOLObjectNames["Chains"][ChainID]["ChainComplexGroupMembers"].append(Name)
  640     
  641     if OptionsInfo["SurfaceChainComplex"]:
  642         Name = "%s.Surface" % (ChainComplexGroupName)
  643         PyMOLObjectNames["Chains"][ChainID]["ChainComplexHydrophobicSurface"] = Name
  644         PyMOLObjectNames["Chains"][ChainID]["ChainComplexGroupMembers"].append(Name)
  645 
  646     # Setup up a group for individual chains...
  647     ChainAloneGroupName = "%s.Chain" % (ChainGroupName)
  648     PyMOLObjectNames["Chains"][ChainID]["ChainAloneGroup"] = ChainAloneGroupName
  649     PyMOLObjectNames["Chains"][ChainID]["ChainGroupMembers"].append(ChainAloneGroupName)
  650         
  651     PyMOLObjectNames["Chains"][ChainID]["ChainAloneGroupMembers"] = []
  652         
  653     Name = "%s.Chain" % (ChainAloneGroupName)
  654     PyMOLObjectNames["Chains"][ChainID]["ChainAlone"] = Name
  655     PyMOLObjectNames["Chains"][ChainID]["ChainAloneGroupMembers"].append(Name)
  656 
  657     if GetChainAloneResidueTypesStatus(FileIndex, ChainID):
  658         # Setup residue type group and its subgroups...
  659         ResiduesGroupName = "%s.Residues" % (ChainAloneGroupName)
  660         
  661         ResiduesGroupIDPrefix = "ChainAloneResidues"
  662         ResiduesGroupID = "%sGroup" % ResiduesGroupIDPrefix
  663 
  664         # Add residue group to chain alone group...
  665         PyMOLObjectNames["Chains"][ChainID][ResiduesGroupID] = ResiduesGroupName
  666         PyMOLObjectNames["Chains"][ChainID]["ChainAloneGroupMembers"].append(ResiduesGroupName)
  667         
  668         # Initialize residue group members...
  669         ResiduesGroupMembersID = "%sGroupMembers" % ResiduesGroupIDPrefix
  670         PyMOLObjectNames["Chains"][ChainID][ResiduesGroupMembersID] = []
  671 
  672         # Setup residues sub groups and its members...
  673         for SubGroupType in ["Aromatic", "Hydrophobic", "Polar", "Positively_Charged", "Negatively_Charged", "Other"]:
  674             SubGroupID = re.sub("_", "", SubGroupType)
  675 
  676             ResiduesSubGroupName = "%s.%s" % (ResiduesGroupName, SubGroupType)
  677             ResiduesSubGroupID = "%s%sGroup" % (ResiduesGroupIDPrefix, SubGroupID)
  678 
  679             # Add sub group to residues group...
  680             PyMOLObjectNames["Chains"][ChainID][ResiduesSubGroupID] = ResiduesSubGroupName
  681             PyMOLObjectNames["Chains"][ChainID][ResiduesGroupMembersID].append(ResiduesSubGroupName)
  682 
  683             # Initialize sub group members...
  684             ResiduesSubGroupMembersID = "%s%sGroupMembers" % (ResiduesGroupIDPrefix, SubGroupID)
  685             PyMOLObjectNames["Chains"][ChainID][ResiduesSubGroupMembersID] = []
  686             
  687             # Add sub group members to subgroup...
  688             for MemberType in ["Residues", "Surface"]:
  689                 MemberID = re.sub("_", "", MemberType)
  690 
  691                 SubGroupMemberName = "%s.%s" % (ResiduesSubGroupName, MemberType)
  692                 SubGroupMemberID = "%s%s%s" % (ResiduesGroupIDPrefix, SubGroupID, MemberID)
  693                 
  694                 PyMOLObjectNames["Chains"][ChainID][SubGroupMemberID] = SubGroupMemberName
  695                 PyMOLObjectNames["Chains"][ChainID][ResiduesSubGroupMembersID].append(SubGroupMemberName)
  696 
  697     if GetChainAloneContainsSurfacesStatus(FileIndex, ChainID):
  698         # Setup cavity and surface groups...
  699         for SubGroupType in ["Cavities", "Surface"]:
  700             SubGroupName = "%s.%s" % (ChainAloneGroupName, SubGroupType)
  701             SubGroupID = "ChainAlone%sGroup" % (SubGroupType)
  702             SubGroupMembersID = "%sMembers" % (SubGroupID)
  703 
  704             PyMOLObjectNames["Chains"][ChainID][SubGroupID] = SubGroupName
  705             PyMOLObjectNames["Chains"][ChainID]["ChainAloneGroupMembers"].append(SubGroupName)
  706             
  707             PyMOLObjectNames["Chains"][ChainID][SubGroupMembersID] = []
  708             
  709             # Setup a generic color surface...
  710             SurfaceName = "%s.Surface" % (SubGroupName)
  711             SurfaceID = "%sSurface" % (SubGroupID)
  712             PyMOLObjectNames["Chains"][ChainID][SurfaceID] = SurfaceName
  713             PyMOLObjectNames["Chains"][ChainID][SubGroupMembersID].append(SurfaceName)
  714         
  715             if GetChainAloneSurfaceChainStatus(FileIndex, ChainID):
  716                 # Setup hydrophobicity surface...
  717                 HydrophobicSurfaceName = "%s.Hydrophobicity" % (SubGroupName)
  718                 HydrophobicSurfaceID = "%sHydrophobicSurface" % (SubGroupID)
  719                 PyMOLObjectNames["Chains"][ChainID][HydrophobicSurfaceID] = HydrophobicSurfaceName
  720                 PyMOLObjectNames["Chains"][ChainID][SubGroupMembersID].append(HydrophobicSurfaceName)
  721                 
  722                 # Setup hydrophobicity and charge surface...
  723                 HydrophobicChargeSurfaceName = "%s.Hydrophobicity_Charge" % (SubGroupName)
  724                 HydrophobicChargeSurfaceID = "%sHydrophobicChargeSurface" % (SubGroupID)
  725                 PyMOLObjectNames["Chains"][ChainID][HydrophobicChargeSurfaceID] = HydrophobicChargeSurfaceName
  726                 PyMOLObjectNames["Chains"][ChainID][SubGroupMembersID].append(HydrophobicChargeSurfaceName)
  727                 
  728             if GetChainAloneSurfaceChainElectrostaticsStatus(FileIndex, ChainID):
  729                 # Setup electrostatics group...
  730                 ElectrostaticsGroupName = "%s.Vacuum_Electrostatics" % (SubGroupName)
  731                 ElectrostaticsGroupID = "%sElectrostaticsGroup" % (SubGroupID)
  732                 ElectrostaticsGroupMembersID = "%sElectrostaticsGroupMembers" % (SubGroupID)
  733                 
  734                 PyMOLObjectNames["Chains"][ChainID][ElectrostaticsGroupID] = ElectrostaticsGroupName
  735                 PyMOLObjectNames["Chains"][ChainID][SubGroupMembersID].append(ElectrostaticsGroupName)
  736                 
  737                 # Setup electrostatics group members...
  738                 PyMOLObjectNames["Chains"][ChainID][ElectrostaticsGroupMembersID] = []
  739                         
  740                 for MemberType in ["Chain", "Contact_Potential", "Map", "Legend"]:
  741                     MemberID = re.sub("_", "", MemberType)
  742                     
  743                     Name = "%s.%s" % (ElectrostaticsGroupName, MemberType)
  744                     NameID = "%s%s" % (ElectrostaticsGroupID, MemberID)
  745                 
  746                     PyMOLObjectNames["Chains"][ChainID][NameID] = Name
  747                     PyMOLObjectNames["Chains"][ChainID][ElectrostaticsGroupMembersID].append(Name)
  748     
  749     # Setup solvent and inorganic objects for chain...
  750     for NameID in ["Solvent", "Inorganic"]:
  751         Name = "%s.%s" % (ChainGroupName, NameID)
  752         PyMOLObjectNames["Chains"][ChainID][NameID] = Name
  753         PyMOLObjectNames["Chains"][ChainID]["ChainGroupMembers"].append(Name)
  754     
  755 def SetupPyMOLObjectNamesForLigand(FileIndex, PyMOLObjectNames, ChainID, LigandID):
  756     """Stetup groups and objects for ligand."""
  757 
  758     PyMOLObjectNames["Ligands"][ChainID][LigandID] = {}
  759     
  760     ChainGroupName = PyMOLObjectNames["Chains"][ChainID]["ChainGroup"]
  761     
  762     # Setup a chain level ligand group...
  763     ChainLigandGroupName = "%s.Ligand%s" % (ChainGroupName, LigandID)
  764     PyMOLObjectNames["Ligands"][ChainID][LigandID]["ChainLigandGroup"] = ChainLigandGroupName
  765     PyMOLObjectNames["Chains"][ChainID]["ChainGroupMembers"].append(ChainLigandGroupName)
  766     
  767     PyMOLObjectNames["Ligands"][ChainID][LigandID]["ChainLigandGroupMembers"] = []
  768 
  769     # Set up ligand group and its members...
  770     GroupName = "%s.Ligand" % (ChainLigandGroupName)
  771     GroupNameID = "LigandGroup"
  772     GroupMembersID = "LigandGroupMembers"
  773     
  774     PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupNameID] = GroupName
  775     PyMOLObjectNames["Ligands"][ChainID][LigandID]["ChainLigandGroupMembers"].append(GroupName)
  776     
  777     LigandName = "%s.Ligand" % (GroupName)
  778     LigandNameID = "Ligand"
  779     PyMOLObjectNames["Ligands"][ChainID][LigandID][LigandNameID] = LigandName
  780     
  781     PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupMembersID] = []
  782     PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupMembersID].append(LigandName)
  783     
  784     # Add ball and stick...
  785     BallAndStickName = "%s.BallAndStick" % (GroupName)
  786     BallAndStickID = "LigandBallAndStick"
  787     PyMOLObjectNames["Ligands"][ChainID][LigandID][BallAndStickID] = BallAndStickName
  788     PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupMembersID].append(BallAndStickName)
  789 
  790 def RetrieveInfilesInfo():
  791     """Retrieve information for input files."""
  792 
  793     InfilesInfo = {}
  794     
  795     InfilesInfo["InfilesNames"] = []
  796     InfilesInfo["InfilesRoots"] = []
  797     InfilesInfo["ChainsAndLigandsInfo"] = []
  798     
  799     for Infile in OptionsInfo["InfilesNames"]:
  800         FileDir, FileName, FileExt = MiscUtil.ParseFileName(Infile)
  801         InfileRoot = FileName
  802         
  803         ChainsAndLigandInfo = PyMOLUtil.GetChainsAndLigandsInfo(Infile, InfileRoot)
  804         
  805         InfilesInfo["InfilesNames"].append(Infile)
  806         InfilesInfo["InfilesRoots"].append(InfileRoot)
  807         InfilesInfo["ChainsAndLigandsInfo"].append(ChainsAndLigandInfo)
  808     
  809     OptionsInfo["InfilesInfo"] = InfilesInfo
  810 
  811 def RetrieveRefFileInfo():
  812     """Retrieve information for ref file."""
  813 
  814     RefFileInfo = {}
  815     if not OptionsInfo["Align"]:
  816         OptionsInfo["RefFileInfo"] = RefFileInfo
  817         return
  818 
  819     RefFile = OptionsInfo["RefFileName"]
  820     
  821     FileDir, FileName, FileExt = MiscUtil.ParseFileName(RefFile)
  822     RefFileRoot = FileName
  823     
  824     if re.match("^FirstInputFile$", OptionsInfo["AlignRefFile"], re.I):
  825         ChainsAndLigandInfo = OptionsInfo["InfilesInfo"]["ChainsAndLigandsInfo"][0]
  826     else:
  827         MiscUtil.PrintInfo("\nRetrieving chain and ligand information for alignment reference file %s..." % RefFile)
  828         ChainsAndLigandInfo = PyMOLUtil.GetChainsAndLigandsInfo(RefFile, RefFileRoot)
  829 
  830     RefFileInfo["RefFileName"] = RefFile
  831     RefFileInfo["RefFileRoot"] = RefFileRoot
  832     RefFileInfo["PyMOLObjectName"] = "AlignRef_%s" % RefFileRoot
  833     RefFileInfo["ChainsAndLigandsInfo"] = ChainsAndLigandInfo
  834     
  835     OptionsInfo["RefFileInfo"] = RefFileInfo
  836 
  837 def ProcessChainAndLigandIDs():
  838     """Process specified chain and ligand IDs for infiles."""
  839     
  840     OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"] = []
  841     
  842     for FileIndex in range(0, len(OptionsInfo["InfilesInfo"]["InfilesNames"])):
  843         MiscUtil.PrintInfo("\nProcessing specified chain and ligand IDs for input file %s..." % OptionsInfo["InfilesInfo"]["InfilesNames"][FileIndex])
  844         
  845         ChainsAndLigandsInfo = OptionsInfo["InfilesInfo"]["ChainsAndLigandsInfo"][FileIndex]
  846         SpecifiedChainsAndLigandsInfo = PyMOLUtil.ProcessChainsAndLigandsOptionsInfo(ChainsAndLigandsInfo, "-c, --chainIDs", OptionsInfo["ChainIDs"], "-l, --ligandIDs", OptionsInfo["LigandIDs"])
  847         ProcessResidueTypesAndSurfaceOptions(FileIndex, SpecifiedChainsAndLigandsInfo)
  848         OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"].append(SpecifiedChainsAndLigandsInfo)
  849         
  850         CheckPresenceOfValidLigandIDs(ChainsAndLigandsInfo, SpecifiedChainsAndLigandsInfo)
  851         
  852 def ProcessResidueTypesAndSurfaceOptions(FileIndex, SpecifiedChainsAndLigandsInfo):
  853     """Process residue types and surface options for chains."""
  854 
  855     SpecifiedChainsAndLigandsInfo["ChainSurfaces"] = {}
  856     SpecifiedChainsAndLigandsInfo["SurfaceChain"] = {}
  857     SpecifiedChainsAndLigandsInfo["SurfaceChainElectrostatics"] = {}
  858     
  859     SpecifiedChainsAndLigandsInfo["ResidueTypesChain"] = {}
  860 
  861     # Load infile...
  862     Infile = OptionsInfo["InfilesInfo"]["InfilesNames"][FileIndex]
  863     MolName = OptionsInfo["InfilesInfo"]["InfilesRoots"][FileIndex]
  864     pymol.cmd.load(Infile, MolName)
  865     
  866     for ChainID in SpecifiedChainsAndLigandsInfo["ChainIDs"]:
  867         AminoAcidsPresent = PyMOLUtil.AreAminoAcidResiduesPresent(MolName, ChainID)
  868 
  869         # Process surfaces for chains...
  870         if re.match("^auto$", OptionsInfo["SurfaceChain"], re.I):
  871             SurfaceChain = True if AminoAcidsPresent else False
  872         else:
  873             SurfaceChain = True if re.match("^yes$", OptionsInfo["SurfaceChain"], re.I) else False
  874         SpecifiedChainsAndLigandsInfo["SurfaceChain"][ChainID] = SurfaceChain
  875 
  876         if re.match("^auto$", OptionsInfo["SurfaceChainElectrostatics"], re.I):
  877             SurfaceChainElectrostatics = True if AminoAcidsPresent else False
  878         else:
  879             SurfaceChainElectrostatics = True if re.match("^yes$", OptionsInfo["SurfaceChainElectrostatics"], re.I) else False
  880         SpecifiedChainsAndLigandsInfo["SurfaceChainElectrostatics"][ChainID] = SurfaceChainElectrostatics
  881 
  882         # A generic color surface is always created...
  883         ChainSurfaces = True
  884         SpecifiedChainsAndLigandsInfo["ChainSurfaces"][ChainID] = ChainSurfaces
  885         
  886         # Process residue types for chains...
  887         if re.match("^auto$", OptionsInfo["ResidueTypesChain"], re.I):
  888             ResidueTypesChain = True if AminoAcidsPresent else False
  889         else:
  890             ResidueTypesChain = True if re.match("^yes$", OptionsInfo["ResidueTypesChain"], re.I) else False
  891         SpecifiedChainsAndLigandsInfo["ResidueTypesChain"][ChainID] = ResidueTypesChain
  892 
  893     # Delete loaded object...
  894     pymol.cmd.delete(MolName)
  895 
  896 def GetChainAloneResidueTypesStatus(FileIndex, ChainID):
  897     """Get status of residue types for chain alone object."""
  898 
  899     Status = True if OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"][FileIndex]["ResidueTypesChain"][ChainID] else False
  900     
  901     return Status
  902 
  903 def GetChainAloneContainsSurfacesStatus(FileIndex, ChainID):
  904     """Get status of surfaces present in chain alone object."""
  905 
  906     return OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"][FileIndex]["ChainSurfaces"][ChainID]
  907 
  908 def GetChainAloneSurfaceChainStatus(FileIndex, ChainID):
  909     """Get status of hydrophobic surfaces for chain alone object."""
  910 
  911     return OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"][FileIndex]["SurfaceChain"][ChainID]
  912 
  913 def GetChainAloneSurfaceChainElectrostaticsStatus(FileIndex, ChainID):
  914     """Get status of electrostatics surfaces for chain alone object."""
  915 
  916     return OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"][FileIndex]["SurfaceChainElectrostatics"][ChainID]
  917 
  918 def CheckPresenceOfValidLigandIDs(ChainsAndLigandsInfo, SpecifiedChainsAndLigandsInfo):
  919     """Check presence of valid ligand IDs."""
  920 
  921     MiscUtil.PrintInfo("\nSpecified chain IDs: %s" % (", ".join(SpecifiedChainsAndLigandsInfo["ChainIDs"])))
  922     
  923     for ChainID in SpecifiedChainsAndLigandsInfo["ChainIDs"]:
  924         if len (SpecifiedChainsAndLigandsInfo["LigandIDs"][ChainID]):
  925             MiscUtil.PrintInfo("Chain ID: %s; Specified LigandIDs: %s" % (ChainID, ", ".join(SpecifiedChainsAndLigandsInfo["LigandIDs"][ChainID])))
  926         else:
  927             MiscUtil.PrintInfo("Chain IDs: %s; Specified LigandIDs: None" % (ChainID))
  928             MiscUtil.PrintWarning("No valid ligand IDs found for chain ID, %s. PyMOL groups and objects related to ligand and binding pockect won't be created." % (ChainID))
  929 
  930 def RetrieveFirstChainID(FileIndex):
  931     """Get first chain ID."""
  932     
  933     ChainsAndLigandsInfo = OptionsInfo["InfilesInfo"]["ChainsAndLigandsInfo"][FileIndex]
  934     
  935     FirstChainID = None
  936     if len(ChainsAndLigandsInfo["ChainIDs"]):
  937         FirstChainID = ChainsAndLigandsInfo["ChainIDs"][0]
  938     
  939     return FirstChainID
  940 
  941 def ProcessResidueTypes():
  942     """Process residue types."""
  943 
  944     ResidueTypesNamesInfo, ResidueTypesParamsInfo = PyMOLUtil.ProcessResidueTypesOptionsInfo("-r, --residueTypes", OptionsInfo["ResidueTypes"])
  945     OptionsInfo["ResidueTypesNames"] = ResidueTypesNamesInfo
  946     OptionsInfo["ResidueTypesParams"] = ResidueTypesParamsInfo
  947     
  948 def ProcessSurfaceAtomTypesColors():
  949     """Process surface atom types colors."""
  950 
  951     AtomTypesColorNamesInfo = PyMOLUtil.ProcessSurfaceAtomTypesColorsOptionsInfo("--surfaceAtomTypesColors", OptionsInfo["SurfaceAtomTypesColors"])
  952     OptionsInfo["AtomTypesColorNames"] = AtomTypesColorNamesInfo
  953 
  954 def ProcessOptions():
  955     """Process and validate command line arguments and options."""
  956 
  957     MiscUtil.PrintInfo("Processing options...")
  958     
  959     # Validate options...
  960     ValidateOptions()
  961     
  962     OptionsInfo["Align"] = True if re.match("^Yes$", Options["--align"], re.I) else False
  963     OptionsInfo["AlignMethod"] = Options["--alignMethod"].lower()
  964     OptionsInfo["AlignMode"] = Options["--alignMode"]
  965     
  966     OptionsInfo["AllowEmptyObjects"] = True if re.match("^Yes$", Options["--allowEmptyObjects"], re.I) else False
  967 
  968     OptionsInfo["CavityCulled"] = True if re.match("^Yes$", Options["--cavityCulled"], re.I) else False
  969     OptionsInfo["SurfaceCavityMode"] = 2 if OptionsInfo["CavityCulled"] else 1
  970     
  971     OptionsInfo["CavityCullSize"] = float(Options["--cavityCullSize"])
  972     OptionsInfo["CavityCutoff"] = float(Options["--cavityCutoff"])
  973     OptionsInfo["CavityRadius"] = float(Options["--cavityRadius"])
  974     
  975     OptionsInfo["Infiles"] = Options["--infiles"]
  976     OptionsInfo["InfilesNames"] =  Options["--infileNames"]
  977 
  978     OptionsInfo["AlignRefFile"] = Options["--alignRefFile"]
  979     if re.match("^FirstInputFile$", Options["--alignRefFile"], re.I):
  980         OptionsInfo["RefFileName"] = OptionsInfo["InfilesNames"][0]
  981     else:
  982         OptionsInfo["RefFileName"] = Options["--alignRefFile"]
  983     
  984     OptionsInfo["IgnoreHydrogens"] = True if re.match("^Yes$", Options["--ignoreHydrogens"], re.I) else False
  985     
  986     OptionsInfo["Overwrite"] = Options["--overwrite"]
  987     OptionsInfo["PMLOut"] = True if re.match("^Yes$", Options["--PMLOut"], re.I) else False
  988     
  989     OptionsInfo["Outfile"] = Options["--outfile"]
  990     FileDir, FileName, FileExt = MiscUtil.ParseFileName(OptionsInfo["Outfile"])
  991     OptionsInfo["PSEOut"] = False 
  992     if re.match("^pml$", FileExt, re.I):
  993         OptionsInfo["PMLOutfile"] = OptionsInfo["Outfile"] 
  994         OptionsInfo["PMEOutfile"] = re.sub(".pml$", ".pme", OptionsInfo["Outfile"]) 
  995     elif re.match("^pse$", FileExt, re.I):
  996         OptionsInfo["PSEOut"] = True 
  997         OptionsInfo["PSEOutfile"] = OptionsInfo["Outfile"] 
  998         OptionsInfo["PMLOutfile"] = re.sub(".pse$", ".pml", OptionsInfo["Outfile"]) 
  999         if os.path.exists(OptionsInfo["PMLOutfile"]) and (not OptionsInfo["Overwrite"]):
 1000             MiscUtil.PrintError("The intermediate output file to be generated, %s, already exist. Use option \"--ov\" or \"--overwrite\" and try again." % OptionsInfo["PMLOutfile"] )
 1001 
 1002     OptionsInfo["LabelFontID"] = int(Options["--labelFontID"])
 1003     
 1004     OptionsInfo["ResidueTypesChain"] = Options["--residueTypesChain"]
 1005     OptionsInfo["ResidueTypes"] = Options["--residueTypes"]
 1006     ProcessResidueTypes()
 1007     
 1008     OptionsInfo["SurfaceChain"] = Options["--surfaceChain"]
 1009     OptionsInfo["SurfaceChainElectrostatics"] = Options["--surfaceChainElectrostatics"]
 1010     
 1011     OptionsInfo["SurfaceChainComplex"] = True if re.match("^Yes$", Options["--surfaceChainComplex"], re.I) else False
 1012     OptionsInfo["SurfaceComplex"] = True if re.match("^Yes$", Options["--surfaceComplex"], re.I) else False
 1013     
 1014     # Retrieve surface colors for generic surfaces..
 1015     SurfaceColors = re.sub(" ", "", Options["--surfaceColors"])
 1016     SurfaceColorsWords = SurfaceColors.split(",")
 1017     if len(SurfaceColorsWords) != 2:
 1018         MiscUtil.PrintError("The number of comma delinited color names, %d, specified using \"--surfaceColors\" option, \"%s\",  must be a 2." % (len(SurfaceColorsWords), Options["--surfaceColors"]))
 1019     OptionsInfo["SurfaceColors"] = SurfaceColors
 1020     OptionsInfo["SurfaceCavityColor"] = SurfaceColorsWords[0]
 1021     OptionsInfo["SurfaceColor"] = SurfaceColorsWords[1]
 1022     
 1023     OptionsInfo["SurfaceColorPalette"] = Options["--surfaceColorPalette"]
 1024     OptionsInfo["SurfaceAtomTypesColors"] = Options["--surfaceAtomTypesColors"]
 1025     ProcessSurfaceAtomTypesColors()
 1026     
 1027     OptionsInfo["SurfaceTransparency"] = float(Options["--surfaceTransparency"])
 1028     
 1029     RetrieveInfilesInfo()
 1030     RetrieveRefFileInfo()
 1031     
 1032     OptionsInfo["ChainIDs"] = Options["--chainIDs"]
 1033     OptionsInfo["LigandIDs"] = Options["--ligandIDs"]
 1034     
 1035     ProcessChainAndLigandIDs()
 1036 
 1037 def RetrieveOptions(): 
 1038     """Retrieve command line arguments and options."""
 1039     
 1040     # Get options...
 1041     global Options
 1042     Options = docopt(_docoptUsage_)
 1043 
 1044     # Set current working directory to the specified directory...
 1045     WorkingDir = Options["--workingdir"]
 1046     if WorkingDir:
 1047         os.chdir(WorkingDir)
 1048     
 1049     # Handle examples option...
 1050     if "--examples" in Options and Options["--examples"]:
 1051         MiscUtil.PrintInfo(MiscUtil.GetExamplesTextFromDocOptText(_docoptUsage_))
 1052         sys.exit(0)
 1053 
 1054 def ValidateOptions():
 1055     """Validate option values."""
 1056     
 1057     MiscUtil.ValidateOptionTextValue("--align", Options["--align"], "yes no")
 1058     MiscUtil.ValidateOptionTextValue("--alignMethod", Options["--alignMethod"], "align cealign super")
 1059     MiscUtil.ValidateOptionTextValue("--alignMode", Options["--alignMode"], "FirstChain Complex")
 1060     
 1061     MiscUtil.ValidateOptionTextValue("--allowEmptyObjects", Options["--allowEmptyObjects"], "yes no")
 1062 
 1063     MiscUtil.ValidateOptionTextValue("--cavityCulled", Options["--cavityCulled"], "yes no")
 1064     MiscUtil.ValidateOptionFloatValue("--cavityCullSize", Options["--cavityCullSize"], {">": 0.0})
 1065     MiscUtil.ValidateOptionFloatValue("--cavityCutoff", Options["--cavityCutoff"], {">": 0.0})
 1066     MiscUtil.ValidateOptionFloatValue("--cavityRadius", Options["--cavityRadius"], {">": 0.0})
 1067     
 1068     # Expand infiles to handle presence of multiple input files...
 1069     InfileNames = MiscUtil.ExpandFileNames(Options["--infiles"], ",")
 1070     if not len(InfileNames):
 1071         MiscUtil.PrintError("No input files specified for \"-i, --infiles\" option")
 1072 
 1073     # Validate file extensions...
 1074     for Infile in InfileNames:
 1075         MiscUtil.ValidateOptionFilePath("-i, --infiles", Infile)
 1076         MiscUtil.ValidateOptionFileExt("-i, --infiles", Infile, "pdb cif")
 1077         MiscUtil.ValidateOptionsDistinctFileNames("-i, --infiles", Infile, "-o, --outfile", Options["--outfile"])
 1078     Options["--infileNames"] = InfileNames
 1079     
 1080     MiscUtil.ValidateOptionFileExt("-o, --outfile", Options["--outfile"], "pml pse")
 1081     MiscUtil.ValidateOptionsOutputFileOverwrite("-o, --outfile", Options["--outfile"], "--overwrite", Options["--overwrite"])
 1082 
 1083     if re.match("^yes$", Options["--align"], re.I):
 1084         if not re.match("^FirstInputFile$", Options["--alignRefFile"], re.I):
 1085             AlignRefFile = Options["--alignRefFile"]
 1086             MiscUtil.ValidateOptionFilePath("--alignRefFile", AlignRefFile)
 1087             MiscUtil.ValidateOptionFileExt("--alignRefFile", AlignRefFile, "pdb cif")
 1088             MiscUtil.ValidateOptionsDistinctFileNames("--AlignRefFile", AlignRefFile, "-o, --outfile", Options["--outfile"])
 1089     
 1090     MiscUtil.ValidateOptionTextValue("--ignoreHydrogens", Options["--ignoreHydrogens"], "yes no")
 1091     
 1092     MiscUtil.ValidateOptionTextValue("--PMLOut", Options["--PMLOut"], "yes no")
 1093     MiscUtil.ValidateOptionIntegerValue("--labelFontID", Options["--labelFontID"], {})
 1094 
 1095     MiscUtil.ValidateOptionTextValue("--residueTypesChain", Options["--residueTypesChain"], "yes no auto")
 1096     
 1097     MiscUtil.ValidateOptionTextValue("--surfaceChain", Options["--surfaceChain"], "yes no auto")
 1098     MiscUtil.ValidateOptionTextValue("--surfaceComplex", Options["--surfaceComplex"], "yes no")
 1099     MiscUtil.ValidateOptionTextValue("--surfaceChainComplex", Options["--surfaceChainComplex"], "yes no")
 1100     MiscUtil.ValidateOptionTextValue("--surfaceChainElectrostatics", Options["--surfaceChainElectrostatics"], "yes no auto")
 1101     
 1102     MiscUtil.ValidateOptionTextValue("--surfaceColorPalette", Options["--surfaceColorPalette"], "RedToWhite WhiteToGreen")
 1103     MiscUtil.ValidateOptionFloatValue("--surfaceTransparency", Options["--surfaceTransparency"], {">=": 0.0, "<=": 1.0})
 1104     
 1105 # Setup a usage string for docopt...
 1106 _docoptUsage_ = """
 1107 PyMOLVisualizeCavities.py - Visualize cavities and pockets in macromolecules
 1108 
 1109 Usage:
 1110     PyMOLVisualizeCavities.py [--align <yes or no>] [--alignMethod <align, cealign, super>]
 1111                                     [--alignMode <FirstChain or Complex>] [--alignRefFile <filename>]
 1112                                     [--allowEmptyObjects <yes or no>] [--cavityCulled <Yes or No>]
 1113                                     [--cavityCullSize <number>] [--cavityCutoff <number>] [--cavityRadius <number>]
 1114                                     [--chainIDs <First, All or ID1,ID2...>] [--labelFontID <number>]
 1115                                     [--ignoreHydrogens <yes or no>] [--ligandIDs <Largest, All or ID1,ID2...> ] [--PMLOut <yes or no>]
 1116                                     [--residueTypes <Type,Color,ResNames,...>] [--residueTypesChain <yes or no>]
 1117                                     [--surfaceChain <yes or no>] [--surfaceChainElectrostatics <yes or no>]
 1118                                     [--surfaceChainComplex <yes or no>] [--surfaceComplex <yes or no>]
 1119                                     [--surfaceAtomTypesColors <ColorType,ColorSpec,...>]
 1120                                     [--surfaceColors <ColorName1,ColorName2>] [--surfaceColorPalette <RedToWhite or WhiteToGreen>]
 1121                                     [--surfaceTransparency <number>] [--overwrite] [-w <dir>] -i <infile1,infile2,infile3...> -o <outfile>
 1122     PyMOLVisualizeCavities.py -h | --help | -e | --examples
 1123 
 1124 Description:
 1125     Generate PyMOL visualization files for viewing cavities and pockets in
 1126     macromolecules including proteins and nucleic acids.
 1127 
 1128     The supported input file format are: PDB (.pdb), CIF (.cif)
 1129 
 1130     The supported output file formats are: PyMOL script file (.pml), PyMOL session
 1131     file (.pse)
 1132 
 1133     A variety of PyMOL groups and objects may be  created for visualization of
 1134     cavities and pockets in macromolecules. These groups and objects correspond
 1135     to complexes, surfaces, chains, ligands, inorganics, cavities, and pockets.
 1136     A complete hierarchy of all possible PyMOL groups and objects is shown below:
 1137     
 1138         <PDBFileRoot>
 1139             .Complex
 1140                 .Complex
 1141                 .Surface
 1142             .Chain<ID>
 1143                 .Complex
 1144                     .Complex
 1145                     .Surface
 1146                 .Chain
 1147                     .Chain
 1148                     .Residues
 1149                         .Aromatic
 1150                             .Residues
 1151                             .Surface
 1152                         .Hydrophobic
 1153                             .Residues
 1154                             .Surface
 1155                         .Polar
 1156                             .Residues
 1157                             .Surface
 1158                         .Positively_Charged
 1159                             .Residues
 1160                             .Surface
 1161                         .Negatively_Charged
 1162                             .Residues
 1163                             .Surface
 1164                         .Other
 1165                             .Residues
 1166                             .Surface
 1167                     .Cavities
 1168                         .Surface
 1169                         .Hydrophobicity
 1170                         .Hydrophobicity_Charge
 1171                         .Vacuum_Electrostatics
 1172                             .Contact_Potentials
 1173                             .Map
 1174                             .Legend
 1175                     .Surface
 1176                         .Surface
 1177                         .Hydrophobicity
 1178                         .Hydrophobicity_Charge
 1179                         .Vacuum_Electrostatics
 1180                             .Contact_Potentials
 1181                             .Map
 1182                             .Legend
 1183                 .Solvent
 1184                 .Inorganic
 1185                 .Ligand<ID>
 1186                     .Ligand
 1187                         .Ligand
 1188                         .BallAndStick
 1189                 .Ligand<ID>
 1190                     .Ligand
 1191                         ... ... ...
 1192             .Chain<ID>
 1193                 ... ... ...
 1194                 .Ligand<ID>
 1195                     ... ... ...
 1196                 .Ligand<ID>
 1197                     ... ... ...
 1198             .Chain<ID>
 1199                 ... ... ...
 1200         <PDBFileRoot>
 1201             .Complex
 1202                 ... ... ...
 1203             .Chain<ID>
 1204                 ... ... ...
 1205                 .Ligand<ID>
 1206                     ... ... ...
 1207                 .Ligand<ID>
 1208                     ... ... ...
 1209             .Chain<ID>
 1210                 ... ... ...
 1211     
 1212     The hydrophobic and electrostatic surfaces are not created for complete complex
 1213     and chain complex in input file(s) by default. A word to the wise: The creation of
 1214     surface objects may slow down loading of PML file and generation of PSE file, based
 1215     on the size of input complexes. The generation of PSE file may also fail.
 1216 
 1217 Options:
 1218     -a, --align <yes or no>  [default: no]
 1219         Align input files to a reference file before visualization.
 1220     --alignMethod <align, cealign, super>  [default: super]
 1221         Alignment methodology to use for aligning input files to a
 1222         reference file.
 1223     --alignMode <FirstChain or Complex>  [default: FirstChain]
 1224         Portion of input and reference files to use for spatial alignment of
 1225         input files against reference file.  Possible values: FirstChain or
 1226         Complex.
 1227         
 1228         The FirstChain mode allows alignment of the first chain in each input
 1229         file to the first chain in the reference file along with moving the rest
 1230         of the complex to coordinate space of the reference file. The complete
 1231         complex in each input file is aligned to the complete complex in reference
 1232         file for the Complex mode.
 1233     --alignRefFile <filename>  [default: FirstInputFile]
 1234         Reference input file name. The default is to use the first input file
 1235         name specified using '-i, --infiles' option.
 1236     --allowEmptyObjects <yes or no>  [default: no]
 1237         Allow creation of empty PyMOL objects corresponding to solvent and
 1238         inorganic atom selections across chains and ligands in input file(s). By
 1239         default, the empty objects are marked for deletion.
 1240     --cavityCulled <Yes or No>  [default: Yes]
 1241         Cull cavities and pockets. The cavities and pockets are culled by default.
 1242         This value is used to set of PyMOL parameter surface_cavity_mode as
 1243         shown below:
 1244         
 1245             No: 1 (Cavities and Pockets Only)
 1246             Yes: 2 (Cavities and Pockets Culled)
 1247         
 1248     --cavityCullSize <number>  [default: 2.0]
 1249         Approximate dimension of the cavity in Angstroms for detecting cavities and
 1250         pockets in the interior of a macromolecule. The higher value makes PyMOL less
 1251         sensitive to detection of smaller cavities.
 1252     --cavityCutoff <number>  [default: 3.0]
 1253         Cavity cutoff in terms of number of solvent radii for detecting cavities
 1254         and pockets. This value is used to set value of PyMOL parameter
 1255         surface_cavity_cutoff.
 1256     --cavityRadius <number>  [default: 5.0]
 1257         Cavity detection radius in terms of number of solvent radii for detecting
 1258         cavities and pockets. The detection of larger pockets is ignored for lower
 1259         value for the cavity radius. This value is used to set of PyMOL parameter
 1260         surface_cavity_radius.
 1261     -c, --chainIDs <First, All or ID1,ID2...>  [default: First]
 1262         List of chain IDs to use for visualizing macromolecules. Possible values:
 1263         First, All, or a comma delimited list of chain IDs. The default is to use the
 1264         chain ID for the first chain in each input file.
 1265     -e, --examples
 1266         Print examples.
 1267     -h, --help
 1268         Print this help message.
 1269     -i, --infiles <infile1,infile2,infile3...>
 1270         Input file names.
 1271     --ignoreHydrogens <yes or no>  [default: yes]
 1272         Ignore hydrogens for ligand views.
 1273     --labelFontID <number>  [default: 7]
 1274         Font ID for drawing labels. Default: 7 (Sans Bold). Valid values: 5 to 16.
 1275         The specified value must be a valid PyMOL font ID. No validation is
 1276         performed. The complete lists of valid font IDs is available at:
 1277         pymolwiki.org/index.php/Label_font_id. Examples: 5 - Sans;
 1278         7 - Sans Bold; 9 - Serif; 10 - Serif Bold.
 1279     -l, --ligandIDs <Largest, All or ID1,ID2...>  [default: All]
 1280         List of ligand IDs to show in chains during visualizing of cavities in
 1281         macromolecules. Possible values: Largest, All, or a comma delimited
 1282         list of ligand IDs. The default is to show all ligands present in all or
 1283         specified chains in each input file.
 1284         
 1285         Ligands are identified using organic selection operator available in PyMOL.
 1286         It'll also  identify buffer molecules as ligands. The largest ligand contains
 1287         the highest number of heavy atoms.
 1288     -o, --outfile <outfile>
 1289         Output file name.
 1290     -p, --PMLOut <yes or no>  [default: yes]
 1291         Save PML file during generation of PSE file.
 1292     -r, --residueTypes <Type,Color,ResNames,...>  [default: auto]
 1293         Residue types, colors, and names to generate for residue groups during
 1294         '--residueTypesChain' option. It is only valid for amino acids.
 1295         
 1296         It is a triplet of comma delimited list of amino acid residues type, residues
 1297         color, and a space delimited list three letter residue names. 
 1298         
 1299         The default values for residue type, color, and name triplets  are shown
 1300         below:
 1301             
 1302             Aromatic,brightorange,HIS PHE TRP TYR,
 1303             Hydrophobic,orange,ALA GLY VAL LEU ILE PRO MET,
 1304             Polar,palegreen,ASN GLN SER THR CYS,
 1305             Positively_Charged,marine,ARG LYS,
 1306             Negatively_Charged,red,ASP GLU
 1307             
 1308         The color name must be a valid PyMOL name. No validation is performed.
 1309         An amino acid name may appear across multiple residue types. All other
 1310         residues are grouped under 'Other'.
 1311     --residueTypesChain <yes or no>  [default: auto]
 1312         Chain residue types. The residue groups are generated using residue types,
 1313         colors, and names specified by '--residueTypes' option. It is only valid for
 1314         amino acids.  By default, the residue type groups are automatically created
 1315         for chains containing amino acids and skipped for chains only containing
 1316         nucleic acids.
 1317     --surfaceChain <yes or no>  [default: auto]
 1318         Surfaces around individual chain colored by hydrophobicity alone and
 1319         both hydrophobicity and charge. The hydrophobicity surface is colored
 1320         at residue level using Eisenberg hydrophobicity scale for residues and color
 1321         gradient specified by '--surfaceColorPalette' option. The  hydrophobicity and
 1322         charge surface is colored [ Ref 140 ] at atom level using colors specified for
 1323         groups of atoms by '--surfaceAtomTypesColors' option. This scheme allows
 1324         simultaneous mapping of hyrophobicity and charge values on the surfaces.
 1325         
 1326         This option is only valid for amino acids. By default, both surfaces are
 1327         automatically created for chains containing amino acids and skipped for
 1328         chains containing only nucleic acids.
 1329         
 1330         In addition, generic surfaces colored by '--surfaceColor' are always created
 1331         for chain residues containing amino acids and nucleic acids.
 1332     --surfaceChainElectrostatics <yes or no>  [default: no]
 1333         Vacuum electrostatics contact potential surface around individual
 1334         chain. A word to the wise from PyMOL documentation: The computed protein
 1335         contact potentials are only qualitatively useful, due to short cutoffs,
 1336         truncation, and lack of solvent "screening".
 1337         
 1338         This option is only valid for amino acids. By default, the electrostatics surface
 1339         is automatically created for chains containing amino acids and
 1340         skipped for chains containing only nucleic acids.
 1341     --surfaceChainComplex <yes or no>  [default: no]
 1342         Hydrophobic surface around chain complex. The  surface is colored by
 1343         hydrophobicity. It is only valid for amino acids.
 1344     --surfaceComplex <yes or no>  [default: no]
 1345         Hydrophobic surface around complete complex. The  surface is colored by
 1346         hydrophobicity. It is only valid for amino acids.
 1347     --surfaceAtomTypesColors <ColorType,ColorSpec,...>  [default: auto]
 1348         Atom colors for generating surfaces colored by hyrophobicity and charge
 1349         around chains and pockets in proteins. It's a pairwise comma delimited list
 1350         of atom color type and color specification for goups of atoms.
 1351         
 1352         The default values for color types [ Ref 140 ] along wth color specifications
 1353         are shown below: 
 1354             
 1355             HydrophobicAtomsColor, yellow,
 1356             NegativelyChargedAtomsColor, red,
 1357             PositivelyChargedAtomsColor, blue,
 1358             OtherAtomsColor, gray90
 1359             
 1360         The color names must be valid PyMOL names.
 1361         
 1362         The color values may also be specified as space delimited RGB triplets:
 1363              
 1364             HydrophobicAtomsColor, 0.95 0.78 0.0,
 1365             NegativelyChargedAtomsColor, 1.0 0.4 0.4,
 1366             PositivelyChargedAtomsColor, 0.2 0.5 0.8,
 1367             OtherAtomsColor, 0.95 0.95 0.95
 1368             
 1369     --surfaceColors <ColorName1,ColorName2>  [default: salmon,lightblue]
 1370         Color names for surfaces around cavities and chains. These colors are not
 1371         used for surfaces and cavities colored by hydrophobicity and charge. The
 1372         color names must be valid PyMOL names.
 1373     --surfaceColorPalette <RedToWhite or WhiteToGreen>  [default: RedToWhite]
 1374         Color palette for hydrophobic surfaces around chains and pockets in proteins.
 1375         Possible values: RedToWhite or WhiteToGreen from most hydrophobic amino
 1376         acid to least hydrophobic. The colors values for amino acids are taken from
 1377         color_h script available as part of the Script Library at PyMOL Wiki.
 1378     --surfaceTransparency <number>  [default: 0.25]
 1379         Surface transparency for molecular surfaces.
 1380     --overwrite
 1381         Overwrite existing files.
 1382     -w, --workingdir <dir>
 1383         Location of working directory which defaults to the current directory.
 1384 
 1385 Examples:
 1386     To visualize cavities in the first chain along with the largest ligand in the
 1387     first chain, solvents, and inorganics, in a PDB file, and generate a PML
 1388     file, type:
 1389 
 1390         % PyMOLVisualizeCavities.py -i Sample4.pdb -o Sample4.pml
 1391 
 1392     To visualize cavities in all chain along with all ligands, solvents,
 1393     and inorganics, in a PDB file, and generate a PML file, type:
 1394 
 1395         % PyMOLVisualizeCavities.py -c All -l All -i Sample4.pdb
 1396           -o Sample4.pml
 1397 
 1398     To visualize cavities in the first chain at a specific cavity radius and cutoff
 1399     using specifc colors for surfaces corresponding to cavities and non-cavities,
 1400     and generate a PML file, type:
 1401 
 1402         % PyMOLVisualizeCavities.py  --cavityRadius 3 --cavityCutoff 5
 1403            --surfaceColors "red,blue" -i Sample4.pdb -o Sample4.pml
 1404 
 1405     To visualize cavities in the first chain along with the largest ligand in the
 1406     first chain, solvents, and inorganics, in PDB files, along with aligning first
 1407     chain in each input file to the first chain inand generate a PML file, type:
 1408 
 1409         % PyMOLVisualizeCavities.py --align yes
 1410           -i "Sample5.pdb,Sample6.pdb,Sample7.pdb"
 1411           -o SampleOut.pml
 1412 
 1413 Author:
 1414     Manish Sud(msud@san.rr.com)
 1415 
 1416 See also:
 1417     DownloadPDBFiles.pl, PyMOLVisualizeCryoEMDensity.py,
 1418     PyMOLVisualizeElectronDensity.py, PyMOLVisualizeInterfaces.py
 1419     PyMOLVisualizeMacromolecules.py, PyMOLVisualizeSurfaceAndBuriedResidues.py
 1420 
 1421 Copyright:
 1422     Copyright (C) 2024 Manish Sud. All rights reserved.
 1423 
 1424     The functionality available in this script is implemented using PyMOL, a
 1425     molecular visualization system on an open source foundation originally
 1426     developed by Warren DeLano.
 1427 
 1428     This file is part of MayaChemTools.
 1429 
 1430     MayaChemTools is free software; you can redistribute it and/or modify it under
 1431     the terms of the GNU Lesser General Public License as published by the Free
 1432     Software Foundation; either version 3 of the License, or (at your option) any
 1433     later version.
 1434 
 1435 """
 1436 
 1437 if __name__ == "__main__":
 1438     main()