MayaChemTools

    1 #!/bin/env python
    2 #
    3 # File: PyMOLVisualizeMacromolecules.py
    4 # Author: Manish Sud <msud@san.rr.com>
    5 #
    6 # Copyright (C) 2026 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 import os
   33 import sys
   34 import time
   35 import re
   36 
   37 # PyMOL imports...
   38 try:
   39     import pymol
   40 
   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 sys.path.insert(0, os.path.join(os.path.dirname(sys.argv[0]), "..", "lib", "Python"))
   52 try:
   53     from docopt import docopt
   54     import MiscUtil
   55     import PyMOLUtil
   56 except ImportError as ErrMsg:
   57     sys.stderr.write("\nFailed to import MayaChemTools module/package: %s\n" % ErrMsg)
   58     sys.stderr.write("Check/update your MayaChemTools environment and try again.\n\n")
   59     sys.exit(1)
   60 
   61 ScriptName = os.path.basename(sys.argv[0])
   62 Options = {}
   63 OptionsInfo = {}
   64 
   65 
   66 def main():
   67     """Start execution of the script."""
   68 
   69     MiscUtil.PrintInfo(
   70         "\n%s (PyMOL v%s; MayaChemTools v%s; %s): Starting...\n"
   71         % (ScriptName, pymol.cmd.get_version()[0], MiscUtil.GetMayaChemToolsVersion(), time.asctime())
   72     )
   73 
   74     (WallClockTime, ProcessorTime) = MiscUtil.GetWallClockAndProcessorTime()
   75 
   76     # Retrieve command line arguments and options...
   77     RetrieveOptions()
   78 
   79     # Process and validate command line arguments and options...
   80     ProcessOptions()
   81 
   82     # Perform actions required by the script...
   83     GenerateMacromolecularVisualization()
   84 
   85     MiscUtil.PrintInfo("\n%s: Done...\n" % ScriptName)
   86     MiscUtil.PrintInfo("Total time: %s" % MiscUtil.GetFormattedElapsedTime(WallClockTime, ProcessorTime))
   87 
   88 
   89 def GenerateMacromolecularVisualization():
   90     """Generate macromolecular visualization."""
   91 
   92     Outfile = OptionsInfo["PMLOutfile"]
   93     OutFH = open(Outfile, "w")
   94     if OutFH is None:
   95         MiscUtil.PrintError("Failed to open output fie %s " % Outfile)
   96 
   97     MiscUtil.PrintInfo("\nGenerating file %s..." % Outfile)
   98 
   99     # Setup header...
  100     WritePMLHeader(OutFH, ScriptName)
  101     WritePyMOLParameters(OutFH)
  102 
  103     # Load reffile for alignment..
  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 trajectories views...
  118         if GetTrajectoriesStatus(FileIndex):
  119             WriteTrajectoriesView(OutFH, FileIndex, PyMOLObjectNames)
  120 
  121         SpecifiedChainsAndLigandsInfo = OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"][FileIndex]
  122         FirstChain = True
  123         for ChainID in SpecifiedChainsAndLigandsInfo["ChainIDs"]:
  124             if FirstComplex and FirstChain:
  125                 FirstComplexFirstChainName = PyMOLObjectNames["Chains"][ChainID]["ChainAlone"]
  126 
  127             WriteChainView(OutFH, FileIndex, PyMOLObjectNames, ChainID)
  128 
  129             # Setup ligand views...
  130             FirstLigand = True
  131             for LigandID in SpecifiedChainsAndLigandsInfo["LigandIDs"][ChainID]:
  132                 WriteChainLigandView(OutFH, FileIndex, PyMOLObjectNames, ChainID, LigandID)
  133 
  134                 # Set up ligand level group...
  135                 Enable, Action = [False, "close"]
  136                 if FirstLigand:
  137                     FirstLigand = False
  138                     Enable, Action = [True, "open"]
  139                 GenerateAndWritePMLForGroup(
  140                     OutFH,
  141                     PyMOLObjectNames["Ligands"][ChainID][LigandID]["ChainLigandGroup"],
  142                     PyMOLObjectNames["Ligands"][ChainID][LigandID]["ChainLigandGroupMembers"],
  143                     Enable,
  144                     Action,
  145                 )
  146 
  147             # Setup docked poses views...
  148             if GetChainAloneDockedPosesStatus(FileIndex, ChainID):
  149                 WriteChainDockedPosesView(OutFH, FileIndex, PyMOLObjectNames, ChainID)
  150 
  151             # Setup Chain level group...
  152             Enable, Action = [False, "close"]
  153             if FirstChain:
  154                 FirstChain = False
  155                 Enable, Action = [True, "open"]
  156             GenerateAndWritePMLForGroup(
  157                 OutFH,
  158                 PyMOLObjectNames["Chains"][ChainID]["ChainGroup"],
  159                 PyMOLObjectNames["Chains"][ChainID]["ChainGroupMembers"],
  160                 Enable,
  161                 Action,
  162             )
  163 
  164         # Set up complex level group...
  165         Enable, Action = [False, "close"]
  166         if FirstComplex:
  167             FirstComplex = False
  168             Enable, Action = [True, "open"]
  169         GenerateAndWritePMLForGroup(
  170             OutFH, PyMOLObjectNames["PDBGroup"], PyMOLObjectNames["PDBGroupMembers"], Enable, Action
  171         )
  172 
  173         # Delete empty PyMOL objects...
  174         DeleteEmptyPyMOLObjects(OutFH, FileIndex, PyMOLObjectNames)
  175 
  176     if OptionsInfo["Align"]:
  177         DeleteAlignReference(OutFH)
  178 
  179     if FirstComplexFirstChainName is not None:
  180         OutFH.write("""\ncmd.orient("%s", animate = -1)\n""" % FirstComplexFirstChainName)
  181     else:
  182         OutFH.write("""\ncmd.orient("visible", animate = -1)\n""")
  183 
  184     OutFH.close()
  185 
  186     # Generate PSE file as needed...
  187     if OptionsInfo["PSEOut"]:
  188         GeneratePyMOLSessionFile()
  189 
  190 
  191 def WritePMLHeader(OutFH, ScriptName):
  192     """Write out PML header."""
  193 
  194     HeaderInfo = PyMOLUtil.SetupPMLHeaderInfo(ScriptName)
  195     OutFH.write("%s\n" % HeaderInfo)
  196 
  197 
  198 def WritePyMOLParameters(OutFH):
  199     """Write out PyMOL global parameters."""
  200 
  201     PMLCmds = []
  202     PMLCmds.append("""cmd.set("transparency", %.2f, "", 0)""" % (OptionsInfo["SurfaceTransparency"]))
  203     PMLCmds.append("""cmd.set("label_font_id", %s)""" % (OptionsInfo["LabelFontID"]))
  204     PML = "\n".join(PMLCmds)
  205 
  206     OutFH.write("""\n""\n"Setting up PyMOL gobal parameters..."\n""\n""")
  207     OutFH.write("%s\n" % PML)
  208 
  209 
  210 def WriteAlignReference(OutFH):
  211     """Setup object for alignment reference."""
  212 
  213     RefFileInfo = OptionsInfo["RefFileInfo"]
  214     RefFile = RefFileInfo["RefFileName"]
  215     RefName = RefFileInfo["PyMOLObjectName"]
  216 
  217     PMLCmds = []
  218     PMLCmds.append("""cmd.load("%s", "%s")""" % (RefFile, RefName))
  219     PMLCmds.append("""cmd.hide("everything", "%s")""" % (RefName))
  220     PMLCmds.append("""cmd.disable("%s")""" % (RefName))
  221     PML = "\n".join(PMLCmds)
  222 
  223     OutFH.write("""\n""\n"Loading %s and setting up view for align reference..."\n""\n""" % RefFile)
  224     OutFH.write("%s\n" % PML)
  225 
  226 
  227 def WriteAlignComplex(OutFH, FileIndex, PyMOLObjectNames):
  228     """Setup alignment of complex to reference."""
  229 
  230     RefFileInfo = OptionsInfo["RefFileInfo"]
  231     RefName = RefFileInfo["PyMOLObjectName"]
  232 
  233     ComplexName = PyMOLObjectNames["Complex"]
  234 
  235     if re.match("^FirstChain$", OptionsInfo["AlignMode"], re.I):
  236         RefFirstChainID = RefFileInfo["ChainsAndLigandsInfo"]["ChainIDs"][0]
  237         RefAlignSelection = "%s and chain %s" % (RefName, RefFirstChainID)
  238 
  239         ComplexFirstChainID = RetrieveFirstChainID(FileIndex)
  240         ComplexAlignSelection = "%s and chain %s" % (ComplexName, ComplexFirstChainID)
  241     else:
  242         RefAlignSelection = RefName
  243         ComplexAlignSelection = ComplexName
  244 
  245     PML = PyMOLUtil.SetupPMLForAlignment(OptionsInfo["AlignMethod"], RefAlignSelection, ComplexAlignSelection)
  246     OutFH.write("""\n""\n"Aligning %s against reference %s ..."\n""\n""" % (ComplexAlignSelection, RefAlignSelection))
  247     OutFH.write("%s\n" % PML)
  248 
  249 
  250 def DeleteAlignReference(OutFH):
  251     """Delete alignment reference object."""
  252 
  253     RefName = OptionsInfo["RefFileInfo"]["PyMOLObjectName"]
  254     OutFH.write("""\n""\n"Deleting alignment reference object %s..."\n""\n""" % RefName)
  255     OutFH.write("""cmd.delete("%s")\n""" % RefName)
  256 
  257 
  258 def WriteComplexView(OutFH, FileIndex, PyMOLObjectNames, FirstComplex):
  259     """Write out PML for viewing polymer complex."""
  260 
  261     # Setup complex...
  262     Infile = OptionsInfo["InfilesInfo"]["InfilesNames"][FileIndex]
  263     PML = PyMOLUtil.SetupPMLForPolymerComplexView(PyMOLObjectNames["Complex"], Infile, True)
  264     OutFH.write("""\n""\n"Loading %s and setting up view for complex..."\n""\n""" % Infile)
  265     OutFH.write("%s\n" % PML)
  266 
  267     if OptionsInfo["Align"]:
  268         # No need to align complex on to itself...
  269         if not (re.match("^FirstInputFile$", OptionsInfo["AlignRefFile"], re.I) and FirstComplex):
  270             WriteAlignComplex(OutFH, FileIndex, PyMOLObjectNames)
  271 
  272     if OptionsInfo["SurfaceComplex"]:
  273         # Setup hydrophobic surface...
  274         PML = PyMOLUtil.SetupPMLForHydrophobicSurfaceView(
  275             PyMOLObjectNames["ComplexHydrophobicSurface"],
  276             PyMOLObjectNames["Complex"],
  277             ColorPalette=OptionsInfo["SurfaceColorPalette"],
  278             Enable=False,
  279         )
  280         OutFH.write("\n%s\n" % PML)
  281 
  282     # Setup complex group...
  283     GenerateAndWritePMLForGroup(
  284         OutFH, PyMOLObjectNames["ComplexGroup"], PyMOLObjectNames["ComplexGroupMembers"], False, "close"
  285     )
  286 
  287 
  288 def WriteChainView(OutFH, FileIndex, PyMOLObjectNames, ChainID):
  289     """Write out PML for viewing chain."""
  290 
  291     OutFH.write("""\n""\n"Setting up views for chain %s..."\n""\n""" % ChainID)
  292 
  293     ChainComplexName = PyMOLObjectNames["Chains"][ChainID]["ChainComplex"]
  294 
  295     # Setup chain complex group view...
  296     WriteChainComplexViews(OutFH, FileIndex, PyMOLObjectNames, ChainID)
  297 
  298     # Setup chain view...
  299     WriteChainAloneViews(OutFH, FileIndex, PyMOLObjectNames, ChainID)
  300 
  301     # Setup chain solvent view...
  302     PML = PyMOLUtil.SetupPMLForSolventView(PyMOLObjectNames["Chains"][ChainID]["Solvent"], ChainComplexName, False)
  303     OutFH.write("\n%s\n" % PML)
  304 
  305     # Setup chain inorganic view...
  306     PML = PyMOLUtil.SetupPMLForInorganicView(PyMOLObjectNames["Chains"][ChainID]["Inorganic"], ChainComplexName, False)
  307     OutFH.write("\n%s\n" % PML)
  308 
  309 
  310 def WriteChainComplexViews(OutFH, FileIndex, PyMOLObjectNames, ChainID):
  311     """Write chain complex views."""
  312 
  313     # Setup chain complex...
  314     ChainComplexName = PyMOLObjectNames["Chains"][ChainID]["ChainComplex"]
  315     PML = PyMOLUtil.SetupPMLForPolymerChainComplexView(ChainComplexName, PyMOLObjectNames["Complex"], ChainID, True)
  316     OutFH.write("%s\n" % PML)
  317 
  318     if OptionsInfo["SurfaceChainComplex"]:
  319         # Setup hydrophobic surface...
  320         PML = PyMOLUtil.SetupPMLForHydrophobicSurfaceView(
  321             PyMOLObjectNames["Chains"][ChainID]["ChainComplexHydrophobicSurface"],
  322             ChainComplexName,
  323             ColorPalette=OptionsInfo["SurfaceColorPalette"],
  324             Enable=False,
  325         )
  326         OutFH.write("\n%s\n" % PML)
  327 
  328     # Setup chain complex group...
  329     GenerateAndWritePMLForGroup(
  330         OutFH,
  331         PyMOLObjectNames["Chains"][ChainID]["ChainComplexGroup"],
  332         PyMOLObjectNames["Chains"][ChainID]["ChainComplexGroupMembers"],
  333         False,
  334         "close",
  335     )
  336 
  337 
  338 def WriteChainAloneViews(OutFH, FileIndex, PyMOLObjectNames, ChainID):
  339     """Write individual chain views."""
  340 
  341     ChainComplexName = PyMOLObjectNames["Chains"][ChainID]["ChainComplex"]
  342 
  343     # Setup chain view...
  344     ChainName = PyMOLObjectNames["Chains"][ChainID]["ChainAlone"]
  345     PML = PyMOLUtil.SetupPMLForPolymerChainView(ChainName, ChainComplexName, True)
  346     OutFH.write("\n%s\n" % PML)
  347 
  348     WriteChainAloneBFactorViews(OutFH, FileIndex, PyMOLObjectNames, ChainID)
  349 
  350     WriteChainAloneChainSelectionsView(OutFH, FileIndex, PyMOLObjectNames, ChainID)
  351     WriteChainAloneResidueTypesView(OutFH, FileIndex, PyMOLObjectNames, ChainID)
  352 
  353     if GetChainAloneContainsSurfacesStatus(FileIndex, ChainID):
  354         # Setup a generic color surface...
  355         PML = PyMOLUtil.SetupPMLForSurfaceView(
  356             PyMOLObjectNames["Chains"][ChainID]["ChainAloneSurface"],
  357             ChainName,
  358             Enable=False,
  359             Color=OptionsInfo["SurfaceColor"],
  360         )
  361         OutFH.write("\n%s\n" % PML)
  362 
  363         if GetChainAloneSurfaceChainStatus(FileIndex, ChainID):
  364             # Setup surface colored by hydrophobicity...
  365             PML = PyMOLUtil.SetupPMLForHydrophobicSurfaceView(
  366                 PyMOLObjectNames["Chains"][ChainID]["ChainAloneHydrophobicSurface"],
  367                 ChainName,
  368                 ColorPalette=OptionsInfo["SurfaceColorPalette"],
  369                 Enable=False,
  370             )
  371             OutFH.write("\n%s\n" % PML)
  372 
  373             # Setup surface colored by hyrdophobicity and charge...
  374             PML = PyMOLUtil.SetupPMLForHydrophobicAndChargeSurfaceView(
  375                 PyMOLObjectNames["Chains"][ChainID]["ChainAloneHydrophobicChargeSurface"],
  376                 ChainName,
  377                 OptionsInfo["AtomTypesColorNames"]["HydrophobicAtomsColor"],
  378                 OptionsInfo["AtomTypesColorNames"]["NegativelyChargedAtomsColor"],
  379                 OptionsInfo["AtomTypesColorNames"]["PositivelyChargedAtomsColor"],
  380                 OptionsInfo["AtomTypesColorNames"]["OtherAtomsColor"],
  381                 Enable=False,
  382                 DisplayAs=None,
  383             )
  384             OutFH.write("\n%s\n" % PML)
  385 
  386         if GetChainAloneSurfaceChainElectrostaticsStatus(FileIndex, ChainID):
  387             # Setup electrostatics surface...
  388             SelectionObjectName = ChainName
  389             ElectrostaticsGroupName = PyMOLObjectNames["Chains"][ChainID]["ChainAloneElectrostaticsGroup"]
  390             ElectrostaticsGroupMembers = PyMOLObjectNames["Chains"][ChainID]["ChainAloneElectrostaticsGroupMembers"]
  391             WriteSurfaceElectrostaticsView(
  392                 "Surface",
  393                 OutFH,
  394                 SelectionObjectName,
  395                 ElectrostaticsGroupName,
  396                 ElectrostaticsGroupMembers,
  397                 DisplayAs="cartoon",
  398             )
  399 
  400         # Setup surface group...
  401         GenerateAndWritePMLForGroup(
  402             OutFH,
  403             PyMOLObjectNames["Chains"][ChainID]["ChainAloneSurfaceGroup"],
  404             PyMOLObjectNames["Chains"][ChainID]["ChainAloneSurfaceGroupMembers"],
  405             True,
  406             "open",
  407         )
  408 
  409         # Setup disulfide group...
  410         WriteChainAloneDisulfideBondsView(OutFH, FileIndex, PyMOLObjectNames, ChainID)
  411 
  412         # Setup salt bridges group...
  413         WriteChainAloneSaltBridgesView(OutFH, FileIndex, PyMOLObjectNames, ChainID)
  414 
  415     # Setup chain group...
  416     GenerateAndWritePMLForGroup(
  417         OutFH,
  418         PyMOLObjectNames["Chains"][ChainID]["ChainAloneGroup"],
  419         PyMOLObjectNames["Chains"][ChainID]["ChainAloneGroupMembers"],
  420         True,
  421         "close",
  422     )
  423 
  424 
  425 def WriteChainLigandView(OutFH, FileIndex, PyMOLObjectNames, ChainID, LigandID):
  426     """Write out PML for viewing ligand in a chain."""
  427 
  428     for GroupID in ["Ligand", "Pocket", "PocketSolvent", "PocketInorganic"]:
  429         ComplexName = PyMOLObjectNames["Chains"][ChainID]["ChainComplex"]
  430         LigandName = PyMOLObjectNames["Ligands"][ChainID][LigandID]["Ligand"]
  431 
  432         # Setup main object...
  433         GroupTypeObjectID = "%s" % (GroupID)
  434         GroupTypeObjectName = PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupTypeObjectID]
  435 
  436         if re.match("^Ligand$", GroupID, re.I):
  437             OutFH.write("""\n""\n"Setting up views for ligand %s in chain %s..."\n""\n""" % (LigandID, ChainID))
  438             PML = PyMOLUtil.SetupPMLForLigandView(
  439                 GroupTypeObjectName, ComplexName, LigandID, Enable=True, IgnoreHydrogens=OptionsInfo["IgnoreHydrogens"]
  440             )
  441             OutFH.write("%s\n" % PML)
  442         elif re.match("^Pocket$", GroupID, re.I):
  443             OutFH.write(
  444                 """\n""\n"Setting up views for pocket around ligand %s in chain %s..."\n""\n""" % (LigandID, ChainID)
  445             )
  446             PML = PyMOLUtil.SetupPMLForLigandPocketView(
  447                 GroupTypeObjectName,
  448                 ComplexName,
  449                 LigandName,
  450                 OptionsInfo["PocketDistanceCutoff"],
  451                 Enable=True,
  452                 IgnoreHydrogens=OptionsInfo["IgnoreHydrogens"],
  453             )
  454             OutFH.write("%s\n" % PML)
  455             OutFH.write(
  456                 """cmd.set("label_color", "%s", "%s")\n""" % (OptionsInfo["PocketLabelColor"], GroupTypeObjectName)
  457             )
  458         elif re.match("^PocketSolvent$", GroupID, re.I):
  459             OutFH.write(
  460                 """\n""\n"Setting up views for solvent in pockect around ligand %s in chain %s..."\n""\n"""
  461                 % (LigandID, ChainID)
  462             )
  463             PML = PyMOLUtil.SetupPMLForLigandPocketSolventView(
  464                 GroupTypeObjectName, ComplexName, LigandName, OptionsInfo["PocketDistanceCutoff"], Enable=True
  465             )
  466             OutFH.write("%s\n" % PML)
  467         elif re.match("^PocketInorganic$", GroupID, re.I):
  468             OutFH.write(
  469                 """\n""\n"Setting up views for inorganic in pockect around ligand %s in chain %s..."\n""\n"""
  470                 % (LigandID, ChainID)
  471             )
  472             PML = PyMOLUtil.SetupPMLForLigandPocketInorganicView(
  473                 GroupTypeObjectName, ComplexName, LigandName, OptionsInfo["PocketDistanceCutoff"], Enable=True
  474             )
  475             OutFH.write("%s\n" % PML)
  476 
  477         # Set up polar contacts...
  478         if re.match("^(Pocket|PocketSolvent|PocketInorganic)$", GroupID, re.I):
  479             PolarContactsID = "%sPolarContacts" % (GroupID)
  480             PolarContactsName = PyMOLObjectNames["Ligands"][ChainID][LigandID][PolarContactsID]
  481 
  482             PolarContactsColor = OptionsInfo["PocketContactsLigandColor"]
  483             if re.match("^PocketSolvent$", GroupID, re.I):
  484                 PolarContactsColor = OptionsInfo["PocketContactsSolventColor"]
  485             elif re.match("^PocketInorganic$", GroupID, re.I):
  486                 PolarContactsColor = OptionsInfo["PocketContactsInorganicColor"]
  487 
  488             PML = PyMOLUtil.SetupPMLForPolarContactsView(
  489                 PolarContactsName,
  490                 LigandName,
  491                 GroupTypeObjectName,
  492                 Enable=False,
  493                 Color=PolarContactsColor,
  494                 Cutoff=OptionsInfo["PocketContactsCutoff"],
  495             )
  496             OutFH.write("\n%s\n" % PML)
  497 
  498             OutFH.write("""cmd.set("label_color", "%s", "%s")\n""" % (PolarContactsColor, PolarContactsName))
  499 
  500         if re.match("^PocketInorganic$", GroupID, re.I):
  501             # Setup pi cation contacts...
  502             PiCationContactsID = "%sPiCationContacts" % (GroupID)
  503             PiCationContactsName = PyMOLObjectNames["Ligands"][ChainID][LigandID][PiCationContactsID]
  504             PiCationContactsColor = OptionsInfo["PocketContactsInorganicPiCationColor"]
  505 
  506             PML = PyMOLUtil.SetupPMLForPiCationContactsView(
  507                 PiCationContactsName,
  508                 LigandName,
  509                 GroupTypeObjectName,
  510                 Enable=False,
  511                 Color=PiCationContactsColor,
  512                 Cutoff=OptionsInfo["PocketContactsCutoff"],
  513             )
  514             OutFH.write("\n%s\n" % PML)
  515             OutFH.write("""cmd.set("label_color", "%s", "%s")\n""" % (PiCationContactsColor, PiCationContactsName))
  516 
  517         if re.match("^Pocket$", GroupID, re.I):
  518             # Setup hydrophobic contacts...
  519             HydrophobicContactsID = "%sHydrophobicContacts" % (GroupID)
  520             HydrophobicContactsName = PyMOLObjectNames["Ligands"][ChainID][LigandID][HydrophobicContactsID]
  521             HydrophobicContactsColor = OptionsInfo["PocketContactsLigandHydrophobicColor"]
  522 
  523             PML = PyMOLUtil.SetupPMLForHydrophobicContactsView(
  524                 HydrophobicContactsName,
  525                 LigandName,
  526                 GroupTypeObjectName,
  527                 Enable=False,
  528                 Color=HydrophobicContactsColor,
  529                 Cutoff=OptionsInfo["PocketContactsCutoff"],
  530             )
  531             OutFH.write("\n%s\n" % PML)
  532             OutFH.write(
  533                 """cmd.set("label_color", "%s", "%s")\n""" % (HydrophobicContactsColor, HydrophobicContactsName)
  534             )
  535 
  536             # Setup pi pi contacts...
  537             PiPiContactsID = "%sPiPiContacts" % (GroupID)
  538             PiPiContactsName = PyMOLObjectNames["Ligands"][ChainID][LigandID][PiPiContactsID]
  539             PiPiContactsColor = OptionsInfo["PocketContactsLigandPiPiColor"]
  540 
  541             PML = PyMOLUtil.SetupPMLForPiPiContactsView(
  542                 PiPiContactsName,
  543                 LigandName,
  544                 GroupTypeObjectName,
  545                 Enable=False,
  546                 Color=PiPiContactsColor,
  547                 Cutoff=OptionsInfo["PocketContactsCutoff"],
  548             )
  549             OutFH.write("\n%s\n" % PML)
  550             OutFH.write("""cmd.set("label_color", "%s", "%s")\n""" % (PiPiContactsColor, PiPiContactsName))
  551 
  552             # Setup pi cation contacts...
  553             PiCationContactsID = "%sPiCationContacts" % (GroupID)
  554             PiCationContactsName = PyMOLObjectNames["Ligands"][ChainID][LigandID][PiCationContactsID]
  555             PiCationContactsColor = OptionsInfo["PocketContactsLigandPiCationColor"]
  556 
  557             PML = PyMOLUtil.SetupPMLForPiCationContactsView(
  558                 PiCationContactsName,
  559                 LigandName,
  560                 GroupTypeObjectName,
  561                 Enable=False,
  562                 Color=PiCationContactsColor,
  563                 Cutoff=OptionsInfo["PocketContactsCutoff"],
  564             )
  565             OutFH.write("\n%s\n" % PML)
  566             OutFH.write("""cmd.set("label_color", "%s", "%s")\n""" % (PiCationContactsColor, PiCationContactsName))
  567 
  568             # Setup halogen contacts...
  569             HalogenContactsID = "%sHalogenContacts" % (GroupID)
  570             HalogenContactsName = PyMOLObjectNames["Ligands"][ChainID][LigandID][HalogenContactsID]
  571             HalogenContactsColor = OptionsInfo["PocketContactsLigandHalogenColor"]
  572 
  573             PML = PyMOLUtil.SetupPMLForHalogenContactsView(
  574                 HalogenContactsName,
  575                 LigandName,
  576                 GroupTypeObjectName,
  577                 Enable=False,
  578                 Color=HalogenContactsColor,
  579                 Cutoff=OptionsInfo["PocketContactsCutoff"],
  580             )
  581             OutFH.write("\n%s\n" % PML)
  582             OutFH.write("""cmd.set("label_color", "%s", "%s")\n""" % (HalogenContactsColor, HalogenContactsName))
  583 
  584             # Setup pocket selections...
  585             WritePocketSelectionsView(OutFH, FileIndex, PyMOLObjectNames, ChainID, LigandID, GroupTypeObjectID)
  586 
  587             # Setup pocket residues...
  588             WritePocketResidueTypesView(OutFH, FileIndex, PyMOLObjectNames, ChainID, LigandID, GroupTypeObjectID)
  589             WritePocketSurfacesTypesView(OutFH, FileIndex, PyMOLObjectNames, ChainID, LigandID, GroupTypeObjectID)
  590 
  591         if re.match("^Ligand$", GroupID, re.I):
  592             # Setup ball and stick view...
  593             BallAndStickNameID = "%sBallAndStick" % (GroupID)
  594             BallAndStickName = PyMOLObjectNames["Ligands"][ChainID][LigandID][BallAndStickNameID]
  595             PML = PyMOLUtil.SetupPMLForBallAndStickView(BallAndStickName, GroupTypeObjectName, Enable=False)
  596             OutFH.write("\n%s\n" % PML)
  597 
  598         # Setup group...
  599         GroupNameID = "%sGroup" % (GroupID)
  600         GroupMembersID = "%sGroupMembers" % (GroupID)
  601         GroupName = PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupNameID]
  602         GroupMembers = PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupMembersID]
  603 
  604         Action = "close"
  605         Enable = False
  606         if re.match("^(Ligand|Pocket)$", GroupID, re.I):
  607             Action = "open"
  608             Enable = True
  609         GenerateAndWritePMLForGroup(OutFH, GroupName, GroupMembers, Enable, Action)
  610 
  611 
  612 def WriteChainDockedPosesView(OutFH, FileIndex, PyMOLObjectNames, ChainID):
  613     """Write out PML for viewing docked poses for input files in a chain."""
  614 
  615     if not GetChainAloneDockedPosesStatus(FileIndex, ChainID):
  616         return
  617 
  618     SpecifiedChainsAndLigandsInfo = OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"][FileIndex]
  619     for InputFileIndex, InputFile in enumerate(SpecifiedChainsAndLigandsInfo["DockedPosesInputFiles"][ChainID]):
  620         WriteChainDockedPosesViewForInputFile(OutFH, FileIndex, PyMOLObjectNames, ChainID, InputFileIndex)
  621 
  622     GenerateAndWritePMLForGroup(
  623         OutFH,
  624         PyMOLObjectNames["Chains"][ChainID]["DockedPosesGroup"],
  625         PyMOLObjectNames["Chains"][ChainID]["DockedPosesGroupMembers"],
  626         False,
  627         "close",
  628     )
  629 
  630 
  631 def WriteChainDockedPosesViewForInputFile(OutFH, PDBFileIndex, PyMOLObjectNames, ChainID, InputFileIndex):
  632     """Write out PML for viewing docked poses for an input file in a chain."""
  633 
  634     DockedPosesInfo = OptionsInfo["DockedPosesInfo"]
  635     DockedPosesDistanceContactsInfo = OptionsInfo["DockedPosesDistanceContactsInfo"]
  636 
  637     LigandID = DockedPosesInfo["LigandID"][PDBFileIndex]
  638     UseInputFileAsLigandID = DockedPosesInfo["UseInputFileAsLigandID"][PDBFileIndex]
  639     InputFile = DockedPosesInfo["InputFiles"][PDBFileIndex][InputFileIndex]
  640     InputFileID = DockedPosesInfo["InputFilesIDs"][PDBFileIndex][InputFileIndex]
  641 
  642     OutFH.write(
  643         """\n""\n"Setting up views for docked poses in input file ID %s for chain %s..."\n""\n"""
  644         % (InputFileID, ChainID)
  645     )
  646 
  647     # Setup poses view...
  648     PosesName = PyMOLObjectNames["DockedPosesInputFile"][ChainID][InputFileID]["Poses"]
  649     PML = PyMOLUtil.SetupPMLForLigandsInputFileView(
  650         PosesName, InputFile, Enable=True, IgnoreHydrogens=OptionsInfo["IgnoreHydrogens"]
  651     )
  652     OutFH.write("%s\n" % PML)
  653 
  654     for GroupID in ["Pocket", "PocketSolvent", "PocketInorganic"]:
  655         ComplexName = PyMOLObjectNames["Chains"][ChainID]["ChainComplex"]
  656         LigandName = PosesName if UseInputFileAsLigandID else PyMOLObjectNames["Ligands"][ChainID][LigandID]["Ligand"]
  657 
  658         # Setup  pocket object...
  659         PocketID = "%sPocket" % (GroupID)
  660         PocketName = PyMOLObjectNames["DockedPosesInputFile"][ChainID][InputFileID][PocketID]
  661 
  662         if re.match("^Pocket$", GroupID, re.I):
  663             PML = PyMOLUtil.SetupPMLForLigandPocketView(
  664                 PocketName,
  665                 ComplexName,
  666                 LigandName,
  667                 OptionsInfo["PocketDistanceCutoff"],
  668                 Enable=True,
  669                 IgnoreHydrogens=OptionsInfo["IgnoreHydrogens"],
  670             )
  671             OutFH.write("%s\n" % PML)
  672             OutFH.write("""cmd.set("label_color", "%s", "%s")\n""" % (OptionsInfo["PocketLabelColor"], PocketName))
  673         elif re.match("^PocketSolvent$", GroupID, re.I):
  674             PML = PyMOLUtil.SetupPMLForLigandPocketSolventView(
  675                 PocketName, ComplexName, LigandName, OptionsInfo["PocketDistanceCutoff"], Enable=True
  676             )
  677             OutFH.write("%s\n" % PML)
  678         elif re.match("^PocketInorganic$", GroupID, re.I):
  679             PML = PyMOLUtil.SetupPMLForLigandPocketInorganicView(
  680                 PocketName, ComplexName, LigandName, OptionsInfo["PocketDistanceCutoff"], Enable=True
  681             )
  682             OutFH.write("%s\n" % PML)
  683 
  684         if DockedPosesInfo["DistanceContacts"] and re.match("^Pocket$", GroupID, re.I):
  685             # Setup distance contacts...
  686             for ContactIndex, ContactID in enumerate(DockedPosesDistanceContactsInfo["ContactIDs"]):
  687                 ContactCutoff = DockedPosesDistanceContactsInfo["ContactCutoff"][ContactID]
  688 
  689                 DistanceContactID = "%sPocketDistanceContacts%s" % (GroupID, ContactID)
  690                 DistanceContactName = PyMOLObjectNames["DockedPosesInputFile"][ChainID][InputFileID][DistanceContactID]
  691 
  692                 DistanceContactsColor = OptionsInfo["DockedPosesDistanceContactsColor"]
  693                 EnableContact = True if ContactIndex == 0 else False
  694                 PML = PyMOLUtil.SetupPMLForDistanceContactsView(
  695                     DistanceContactName,
  696                     PosesName,
  697                     PocketName,
  698                     Enable=EnableContact,
  699                     Color=DistanceContactsColor,
  700                     Cutoff=ContactCutoff,
  701                     IgnoreHydrogens=True,
  702                 )
  703                 OutFH.write("\n%s\n" % PML)
  704 
  705                 OutFH.write("""cmd.set("label_color", "%s", "%s")\n""" % (DistanceContactsColor, DistanceContactName))
  706 
  707             # Setup distance conatcts group...
  708             DistanceContactGroupNameID = "%sDistanceContactsGroup" % GroupID
  709             DistanceContactGroupMembersID = "%sDistanceContactsGroupMembers" % GroupID
  710 
  711             GenerateAndWritePMLForGroup(
  712                 OutFH,
  713                 PyMOLObjectNames["DockedPosesInputFile"][ChainID][InputFileID][DistanceContactGroupNameID],
  714                 PyMOLObjectNames["DockedPosesInputFile"][ChainID][InputFileID][DistanceContactGroupMembersID],
  715                 True,
  716                 "open",
  717             )
  718 
  719         # Setup polar contacts...
  720         if re.match("^(Pocket|PocketSolvent|PocketInorganic)$", GroupID, re.I):
  721             PolarContactsID = "%sPolarContacts" % (GroupID)
  722             PolarContactsName = PyMOLObjectNames["DockedPosesInputFile"][ChainID][InputFileID][PolarContactsID]
  723 
  724             PolarContactsColor = OptionsInfo["PocketContactsLigandColor"]
  725             if re.match("^PocketSolvent$", GroupID, re.I):
  726                 PolarContactsColor = OptionsInfo["PocketContactsSolventColor"]
  727             elif re.match("^PocketInorganic$", GroupID, re.I):
  728                 PolarContactsColor = OptionsInfo["PocketContactsInorganicColor"]
  729 
  730             PML = PyMOLUtil.SetupPMLForPolarContactsView(
  731                 PolarContactsName,
  732                 PosesName,
  733                 PocketName,
  734                 Enable=False,
  735                 Color=PolarContactsColor,
  736                 Cutoff=OptionsInfo["PocketContactsCutoff"],
  737             )
  738             OutFH.write("\n%s\n" % PML)
  739 
  740             OutFH.write("""cmd.set("label_color", "%s", "%s")\n""" % (PolarContactsColor, PolarContactsName))
  741 
  742         if re.match("^PocketInorganic$", GroupID, re.I):
  743             # Setup pi cation contacts...
  744             PiCationContactsID = "%sPiCationContacts" % (GroupID)
  745             PiCationContactsName = PyMOLObjectNames["DockedPosesInputFile"][ChainID][InputFileID][PiCationContactsID]
  746             PiCationContactsColor = OptionsInfo["PocketContactsInorganicPiCationColor"]
  747 
  748             PML = PyMOLUtil.SetupPMLForPiCationContactsView(
  749                 PiCationContactsName,
  750                 PosesName,
  751                 PocketName,
  752                 Enable=False,
  753                 Color=PiCationContactsColor,
  754                 Cutoff=OptionsInfo["PocketContactsCutoff"],
  755             )
  756             OutFH.write("\n%s\n" % PML)
  757 
  758             OutFH.write("""cmd.set("label_color", "%s", "%s")\n""" % (PiCationContactsColor, PiCationContactsName))
  759 
  760         if re.match("^Pocket$", GroupID, re.I):
  761             # Setup hydrophobic contacts...
  762             HydrophobicContactsID = "%sHydrophobicContacts" % (GroupID)
  763             HydrophobicContactsName = PyMOLObjectNames["DockedPosesInputFile"][ChainID][InputFileID][
  764                 HydrophobicContactsID
  765             ]
  766             HydrophobicContactsColor = OptionsInfo["PocketContactsLigandHydrophobicColor"]
  767 
  768             PML = PyMOLUtil.SetupPMLForHydrophobicContactsView(
  769                 HydrophobicContactsName,
  770                 PosesName,
  771                 PocketName,
  772                 Enable=False,
  773                 Color=HydrophobicContactsColor,
  774                 Cutoff=OptionsInfo["PocketContactsCutoff"],
  775             )
  776             OutFH.write("\n%s\n" % PML)
  777             OutFH.write(
  778                 """cmd.set("label_color", "%s", "%s")\n""" % (HydrophobicContactsColor, HydrophobicContactsName)
  779             )
  780 
  781             # Setup pi pi contacts...
  782             PiPiContactsID = "%sPiPiContacts" % (GroupID)
  783             PiPiContactsName = PyMOLObjectNames["DockedPosesInputFile"][ChainID][InputFileID][PiPiContactsID]
  784             PiPiContactsColor = OptionsInfo["PocketContactsLigandPiPiColor"]
  785 
  786             PML = PyMOLUtil.SetupPMLForPiPiContactsView(
  787                 PiPiContactsName,
  788                 PosesName,
  789                 PocketName,
  790                 Enable=False,
  791                 Color=PiPiContactsColor,
  792                 Cutoff=OptionsInfo["PocketContactsCutoff"],
  793             )
  794             OutFH.write("\n%s\n" % PML)
  795             OutFH.write("""cmd.set("label_color", "%s", "%s")\n""" % (PiPiContactsColor, PiPiContactsName))
  796 
  797             # Setup pi cation contacts...
  798             PiCationContactsID = "%sPiCationContacts" % (GroupID)
  799             PiCationContactsName = PyMOLObjectNames["DockedPosesInputFile"][ChainID][InputFileID][PiCationContactsID]
  800             PiCationContactsColor = OptionsInfo["PocketContactsLigandPiCationColor"]
  801 
  802             PML = PyMOLUtil.SetupPMLForPiCationContactsView(
  803                 PiCationContactsName,
  804                 PosesName,
  805                 PocketName,
  806                 Enable=False,
  807                 Color=PiCationContactsColor,
  808                 Cutoff=OptionsInfo["PocketContactsCutoff"],
  809             )
  810             OutFH.write("\n%s\n" % PML)
  811             OutFH.write("""cmd.set("label_color", "%s", "%s")\n""" % (PiCationContactsColor, PiCationContactsName))
  812 
  813             # Setup halogen contacts...
  814             HalogenContactsID = "%sHalogenContacts" % (GroupID)
  815             HalogenContactsName = PyMOLObjectNames["DockedPosesInputFile"][ChainID][InputFileID][HalogenContactsID]
  816             HalogenContactsColor = OptionsInfo["PocketContactsLigandHalogenColor"]
  817 
  818             PML = PyMOLUtil.SetupPMLForHalogenContactsView(
  819                 HalogenContactsName,
  820                 LigandName,
  821                 PocketName,
  822                 Enable=False,
  823                 Color=HalogenContactsColor,
  824                 Cutoff=OptionsInfo["PocketContactsCutoff"],
  825             )
  826             OutFH.write("\n%s\n" % PML)
  827             OutFH.write("""cmd.set("label_color", "%s", "%s")\n""" % (HalogenContactsColor, HalogenContactsName))
  828 
  829         # Setup group for an input file...
  830         GroupNameID = "%sGroup" % (GroupID)
  831         GroupMembersID = "%sGroupMembers" % (GroupID)
  832         Enable = True if re.match("^Pocket$", GroupID, re.I) else False
  833         Action = "open" if re.match("^Pocket$", GroupID, re.I) else "close"
  834 
  835         GenerateAndWritePMLForGroup(
  836             OutFH,
  837             PyMOLObjectNames["DockedPosesInputFile"][ChainID][InputFileID][GroupNameID],
  838             PyMOLObjectNames["DockedPosesInputFile"][ChainID][InputFileID][GroupMembersID],
  839             Enable,
  840             Action,
  841         )
  842 
  843     # Setup docked poses group for an input file...
  844     Action = "open" if InputFileIndex == 0 else "close"
  845     Enable = True if InputFileIndex == 0 else False
  846     GenerateAndWritePMLForGroup(
  847         OutFH,
  848         PyMOLObjectNames["DockedPosesInputFile"][ChainID][InputFileID]["DockedPosesGroupName"],
  849         PyMOLObjectNames["DockedPosesInputFile"][ChainID][InputFileID]["DockedPosesGroupMembers"],
  850         Enable,
  851         Action,
  852     )
  853 
  854 
  855 def WritePocketSelectionsView(OutFH, FileIndex, PyMOLObjectNames, ChainID, LigandID, PocketObjectID):
  856     """Write out PML for viewing selections for a lgand pocket."""
  857 
  858     if not GetPocketContainsSelectionsStatus(FileIndex, ChainID, LigandID):
  859         return
  860 
  861     PocketObjectName = PyMOLObjectNames["Ligands"][ChainID][LigandID][PocketObjectID]
  862     SelectionsGroupIDPrefix = "PocketSelectionsGroup"
  863 
  864     for Index in range(0, len(OptionsInfo["PocketChainSelectionsInfo"]["Names"])):
  865         SelectionName = OptionsInfo["PocketChainSelectionsInfo"]["Names"][Index]
  866         Selection = OptionsInfo["PocketChainSelectionsInfo"]["Selections"][Index]
  867 
  868         SelectionNameGroupID = SelectionName
  869 
  870         # Setup a selection object...
  871         SelectionObjectID = "%s%sSelection" % (SelectionsGroupIDPrefix, SelectionNameGroupID)
  872         SelectionObjectName = PyMOLObjectNames["Ligands"][ChainID][LigandID][SelectionObjectID]
  873         SelectionCmd = "(%s and (%s))" % (PocketObjectName, Selection)
  874         PML = PyMOLUtil.SetupPMLForSelectionDisplayView(
  875             SelectionObjectName,
  876             SelectionCmd,
  877             OptionsInfo["SelectionsPocketStyle"],
  878             Enable=True,
  879             IgnoreHydrogens=OptionsInfo["IgnoreHydrogens"],
  880         )
  881         OutFH.write("\n%s\n" % PML)
  882 
  883         if GetPocketSelectionSurfaceChainStatus(FileIndex, ChainID, LigandID):
  884             # Display style for selection objects in surfaces...
  885             DisplayStyle = "lines"
  886 
  887             # Setup a generic color surface...
  888             SurfaceID = "%s%s%sSurface" % (SelectionsGroupIDPrefix, SelectionNameGroupID, "Surface")
  889             SurfaceName = PyMOLObjectNames["Ligands"][ChainID][LigandID][SurfaceID]
  890             PML = PyMOLUtil.SetupPMLForSurfaceView(
  891                 SurfaceName,
  892                 SelectionObjectName,
  893                 Enable=False,
  894                 Color=OptionsInfo["SurfaceColor"],
  895                 DisplayAs=DisplayStyle,
  896             )
  897             OutFH.write("\n%s\n" % PML)
  898 
  899             # Setup a surface colored by hydrphobicity...
  900             HydrophobicSurfaceID = "%s%sSurfaceHydrophobicity" % (SelectionsGroupIDPrefix, SelectionNameGroupID)
  901             HydrophobicSurfaceName = PyMOLObjectNames["Ligands"][ChainID][LigandID][HydrophobicSurfaceID]
  902             PML = PyMOLUtil.SetupPMLForHydrophobicSurfaceView(
  903                 HydrophobicSurfaceName,
  904                 SelectionObjectName,
  905                 ColorPalette=OptionsInfo["SurfaceColorPalette"],
  906                 Enable=False,
  907                 DisplayAs=DisplayStyle,
  908             )
  909             OutFH.write("\n%s\n" % PML)
  910 
  911             # Setup a surface colored by hydrphobicity and charge...
  912             HydrophobicChargeSurfaceID = "%s%sSurfaceHydrophobicityCharge" % (
  913                 SelectionsGroupIDPrefix,
  914                 SelectionNameGroupID,
  915             )
  916             HydrophobicChargeSurfaceName = PyMOLObjectNames["Ligands"][ChainID][LigandID][HydrophobicChargeSurfaceID]
  917             PML = PyMOLUtil.SetupPMLForHydrophobicAndChargeSurfaceView(
  918                 HydrophobicChargeSurfaceName,
  919                 SelectionObjectName,
  920                 OptionsInfo["AtomTypesColorNames"]["HydrophobicAtomsColor"],
  921                 OptionsInfo["AtomTypesColorNames"]["NegativelyChargedAtomsColor"],
  922                 OptionsInfo["AtomTypesColorNames"]["PositivelyChargedAtomsColor"],
  923                 OptionsInfo["AtomTypesColorNames"]["OtherAtomsColor"],
  924                 Enable=False,
  925                 DisplayAs=DisplayStyle,
  926             )
  927             OutFH.write("\n%s\n" % PML)
  928 
  929             # Setup group for surfaces...
  930             SurfaceGroupID = "%s%sSurfaceGroup" % (SelectionsGroupIDPrefix, SelectionNameGroupID)
  931             SurfaceGroupMembersID = "%s%sSurfaceGroupMembers" % (SelectionsGroupIDPrefix, SelectionNameGroupID)
  932             GenerateAndWritePMLForGroup(
  933                 OutFH,
  934                 PyMOLObjectNames["Ligands"][ChainID][LigandID][SurfaceGroupID],
  935                 PyMOLObjectNames["Ligands"][ChainID][LigandID][SurfaceGroupMembersID],
  936                 True,
  937                 "open",
  938             )
  939 
  940         # Setup groups for named selections...
  941         SelectionsNameGroupID = "%s%sGroup" % (SelectionsGroupIDPrefix, SelectionNameGroupID)
  942         SelectionsNameGroupMembersID = "%s%sGroupMembers" % (SelectionsGroupIDPrefix, SelectionNameGroupID)
  943         GenerateAndWritePMLForGroup(
  944             OutFH,
  945             PyMOLObjectNames["Ligands"][ChainID][LigandID][SelectionsNameGroupID],
  946             PyMOLObjectNames["Ligands"][ChainID][LigandID][SelectionsNameGroupMembersID],
  947             True,
  948             "open",
  949         )
  950 
  951     # Setup a group for selections...
  952     SelectionsGroupID = "%s" % (SelectionsGroupIDPrefix)
  953     SelectionsGroupMembersID = "%sGroupMembers" % (SelectionsGroupIDPrefix)
  954     GenerateAndWritePMLForGroup(
  955         OutFH,
  956         PyMOLObjectNames["Ligands"][ChainID][LigandID][SelectionsGroupID],
  957         PyMOLObjectNames["Ligands"][ChainID][LigandID][SelectionsGroupMembersID],
  958         True,
  959         "close",
  960     )
  961 
  962 
  963 def WritePocketSurfacesTypesView(OutFH, FileIndex, PyMOLObjectNames, ChainID, LigandID, PocketObjectID):
  964     """Write out PML for viewing surfaces for a ligand pocket."""
  965 
  966     if not GetPocketContainsSurfaceStatus(FileIndex, ChainID, LigandID):
  967         return
  968 
  969     PocketObjectName = PyMOLObjectNames["Ligands"][ChainID][LigandID][PocketObjectID]
  970 
  971     SurfacesGroupID = "%sSurfacesGroup" % (PocketObjectID)
  972     SurfacesGroupMembersID = "%sSurfacesGroupMembers" % (PocketObjectID)
  973 
  974     # Cavity modes: 1 or 2.  1: Cavity surfaces; 2: Culled cavity surfaces...
  975     CavityMode = 2
  976 
  977     # Setup surfaces subgroup and its members...
  978     for SubGroupType in ["Surface", "Cavity"]:
  979         ProcessingCavity = True if re.match("^Cavity$", SubGroupType, re.I) else False
  980 
  981         SubGroupID = re.sub("_", "", SubGroupType)
  982         SurfacesSubGroupID = "%s%sGroup" % (SurfacesGroupID, SubGroupID)
  983         SurfacesSubGroupMembersID = "%sMembers" % (SurfacesSubGroupID)
  984 
  985         # Turn off lines display for cavity surfaces...
  986         DisplayStyle = None if ProcessingCavity else "lines"
  987 
  988         # Setup a generic color surface...
  989         SurfaceID = "%sSurface" % (SurfacesSubGroupID)
  990         SurfaceName = PyMOLObjectNames["Ligands"][ChainID][LigandID][SurfaceID]
  991         PML = PyMOLUtil.SetupPMLForSurfaceView(
  992             SurfaceName, PocketObjectName, Enable=False, Color=OptionsInfo["SurfaceColor"], DisplayAs=DisplayStyle
  993         )
  994         OutFH.write("\n%s\n" % PML)
  995 
  996         if ProcessingCavity:
  997             OutFH.write("""cmd.set("surface_cavity_mode", %d, "%s")\n""" % (CavityMode, SurfaceName))
  998 
  999         OutFH.write("""cmd.set("label_color", "%s", "%s")\n""" % (OptionsInfo["PocketLabelColor"], SurfaceName))
 1000 
 1001         if GetPocketSurfaceChainStatus(FileIndex, ChainID, LigandID):
 1002             # Setup a surface colored by hydrphobicity...
 1003             HydrophobicSurfaceID = "%sHydrophobicSurface" % (SurfacesSubGroupID)
 1004             HydrophobicSurfaceName = PyMOLObjectNames["Ligands"][ChainID][LigandID][HydrophobicSurfaceID]
 1005             PML = PyMOLUtil.SetupPMLForHydrophobicSurfaceView(
 1006                 HydrophobicSurfaceName,
 1007                 PocketObjectName,
 1008                 ColorPalette=OptionsInfo["SurfaceColorPalette"],
 1009                 Enable=False,
 1010                 DisplayAs=DisplayStyle,
 1011             )
 1012             OutFH.write("\n%s\n" % PML)
 1013 
 1014             if ProcessingCavity:
 1015                 OutFH.write("""cmd.set("surface_cavity_mode", %d, "%s")\n""" % (CavityMode, HydrophobicSurfaceName))
 1016 
 1017             OutFH.write(
 1018                 """cmd.set("label_color", "%s", "%s")\n""" % (OptionsInfo["PocketLabelColor"], HydrophobicSurfaceName)
 1019             )
 1020 
 1021             # Setup a surface colored by hydrphobicity and charge...
 1022             HydrophobicChargeSurfaceID = "%sHydrophobicChargeSurface" % (SurfacesSubGroupID)
 1023             HydrophobicChargeSurfaceName = PyMOLObjectNames["Ligands"][ChainID][LigandID][HydrophobicChargeSurfaceID]
 1024             PML = PyMOLUtil.SetupPMLForHydrophobicAndChargeSurfaceView(
 1025                 HydrophobicChargeSurfaceName,
 1026                 PocketObjectName,
 1027                 OptionsInfo["AtomTypesColorNames"]["HydrophobicAtomsColor"],
 1028                 OptionsInfo["AtomTypesColorNames"]["NegativelyChargedAtomsColor"],
 1029                 OptionsInfo["AtomTypesColorNames"]["PositivelyChargedAtomsColor"],
 1030                 OptionsInfo["AtomTypesColorNames"]["OtherAtomsColor"],
 1031                 Enable=False,
 1032                 DisplayAs=DisplayStyle,
 1033             )
 1034             OutFH.write("\n%s\n" % PML)
 1035 
 1036             if ProcessingCavity:
 1037                 OutFH.write(
 1038                     """cmd.set("surface_cavity_mode", %d, "%s")\n""" % (CavityMode, HydrophobicChargeSurfaceName)
 1039                 )
 1040 
 1041             OutFH.write(
 1042                 """cmd.set("label_color", "%s", "%s")\n"""
 1043                 % (OptionsInfo["PocketLabelColor"], HydrophobicChargeSurfaceName)
 1044             )
 1045 
 1046             if GetPocketSurfaceChainElectrostaticsStatus(FileIndex, ChainID, LigandID):
 1047                 # Set up a electrostatics surface...
 1048                 ElectrostaticsGroupID = "%sElectrostaticsGroup" % (SurfacesSubGroupID)
 1049                 ElectrostaticsGroupMembersID = "%sElectrostaticsGroupMembers" % (SurfacesSubGroupID)
 1050                 ElectrostaticsGroupName = PyMOLObjectNames["Ligands"][ChainID][LigandID][ElectrostaticsGroupID]
 1051                 ElectrostaticsGroupMembers = PyMOLObjectNames["Ligands"][ChainID][LigandID][
 1052                     ElectrostaticsGroupMembersID
 1053                 ]
 1054                 WriteSurfaceElectrostaticsView(
 1055                     SubGroupType,
 1056                     OutFH,
 1057                     PocketObjectName,
 1058                     ElectrostaticsGroupName,
 1059                     ElectrostaticsGroupMembers,
 1060                     DisplayAs=DisplayStyle,
 1061                     SurfaceCavityMode=CavityMode,
 1062                 )
 1063 
 1064             # Setup surfaces sub group...
 1065             GenerateAndWritePMLForGroup(
 1066                 OutFH,
 1067                 PyMOLObjectNames["Ligands"][ChainID][LigandID][SurfacesSubGroupID],
 1068                 PyMOLObjectNames["Ligands"][ChainID][LigandID][SurfacesSubGroupMembersID],
 1069                 True,
 1070                 "open",
 1071             )
 1072 
 1073     # Setup surface group...
 1074     GenerateAndWritePMLForGroup(
 1075         OutFH,
 1076         PyMOLObjectNames["Ligands"][ChainID][LigandID][SurfacesGroupID],
 1077         PyMOLObjectNames["Ligands"][ChainID][LigandID][SurfacesGroupMembersID],
 1078         True,
 1079         "open",
 1080     )
 1081 
 1082 
 1083 def WritePocketResidueTypesView(OutFH, FileIndex, PyMOLObjectNames, ChainID, LigandID, PocketObjectID):
 1084     """Write out PML for viewing residue types for a ligand pocket."""
 1085 
 1086     if not GetPocketResidueTypesStatus(FileIndex, ChainID, LigandID):
 1087         return
 1088 
 1089     PocketObjectName = PyMOLObjectNames["Ligands"][ChainID][LigandID][PocketObjectID]
 1090 
 1091     ResiduesGroupID = "%sResiduesGroup" % (PocketObjectID)
 1092     ResiduesGroupMembersID = "%sMembers" % (ResiduesGroupID)
 1093 
 1094     # Setup residue types objects...
 1095     for SubGroupType in ["Aromatic", "Hydrophobic", "Polar", "Positively_Charged", "Negatively_Charged", "Other"]:
 1096         SubGroupID = re.sub("_", "", SubGroupType)
 1097 
 1098         ResiduesSubGroupID = "%s%sGroup" % (ResiduesGroupID, SubGroupID)
 1099         ResiduesSubMembersGroupID = "%sMembers" % (ResiduesSubGroupID)
 1100 
 1101         SubGroupMemberID = "%sResidues" % (ResiduesSubGroupID)
 1102         ResiduesObjectName = PyMOLObjectNames["Ligands"][ChainID][LigandID][SubGroupMemberID]
 1103 
 1104         SubGroupMemberID = "%sSurface" % (ResiduesSubGroupID)
 1105         ResiduesSurfaceObjectName = PyMOLObjectNames["Ligands"][ChainID][LigandID][SubGroupMemberID]
 1106 
 1107         ResiduesColor = OptionsInfo["ResidueTypesParams"][SubGroupType]["Color"]
 1108         ResiduesNames = OptionsInfo["ResidueTypesParams"][SubGroupType]["Residues"]
 1109 
 1110         NegateResidueNames = True if re.match("^Other$", SubGroupType, re.I) else False
 1111         WriteResidueTypesResiduesAndSurfaceView(
 1112             OutFH,
 1113             PocketObjectName,
 1114             ResiduesObjectName,
 1115             ResiduesSurfaceObjectName,
 1116             ResiduesColor,
 1117             ResiduesNames,
 1118             NegateResidueNames,
 1119         )
 1120 
 1121         # Setup residue type sub groups...
 1122         GenerateAndWritePMLForGroup(
 1123             OutFH,
 1124             PyMOLObjectNames["Ligands"][ChainID][LigandID][ResiduesSubGroupID],
 1125             PyMOLObjectNames["Ligands"][ChainID][LigandID][ResiduesSubMembersGroupID],
 1126             True,
 1127             "close",
 1128         )
 1129 
 1130     # Setup residue types group...
 1131     GenerateAndWritePMLForGroup(
 1132         OutFH,
 1133         PyMOLObjectNames["Ligands"][ChainID][LigandID][ResiduesGroupID],
 1134         PyMOLObjectNames["Ligands"][ChainID][LigandID][ResiduesGroupMembersID],
 1135         False,
 1136         "close",
 1137     )
 1138 
 1139 
 1140 def WriteChainAloneChainSelectionsView(OutFH, FileIndex, PyMOLObjectNames, ChainID):
 1141     """Write out PML for viewing selections for a chain."""
 1142 
 1143     if not GetChainAloneContainsSelectionsStatus(FileIndex, ChainID):
 1144         return
 1145 
 1146     ChainName = PyMOLObjectNames["Chains"][ChainID]["ChainAlone"]
 1147     SelectionsGroupIDPrefix = "ChainAloneSelections"
 1148 
 1149     for Index in range(0, len(OptionsInfo["ChainSelectionsInfo"]["Names"])):
 1150         SelectionName = OptionsInfo["ChainSelectionsInfo"]["Names"][Index]
 1151         Selection = OptionsInfo["ChainSelectionsInfo"]["Selections"][Index]
 1152 
 1153         SelectionNameGroupID = SelectionName
 1154 
 1155         # Setup a selection object...
 1156         SelectionObjectID = "%s%sSelection" % (SelectionsGroupIDPrefix, SelectionNameGroupID)
 1157         SelectionObjectName = PyMOLObjectNames["Chains"][ChainID][SelectionObjectID]
 1158         SelectionCmd = "(%s and (%s))" % (ChainName, Selection)
 1159         PML = PyMOLUtil.SetupPMLForSelectionDisplayView(
 1160             SelectionObjectName,
 1161             SelectionCmd,
 1162             OptionsInfo["SelectionsChainStyle"],
 1163             Enable=True,
 1164             IgnoreHydrogens=OptionsInfo["IgnoreHydrogens"],
 1165         )
 1166         OutFH.write("\n%s\n" % PML)
 1167 
 1168         if GetChainAloneContainsChainSelectionSurfacesStatus(FileIndex, ChainID):
 1169             # Display style for selection objects in surfaces...
 1170             DisplayStyle = "lines"
 1171 
 1172             # Setup a generic color surface...
 1173             SurfaceID = "%s%s%sSurface" % (SelectionsGroupIDPrefix, SelectionNameGroupID, "Surface")
 1174             SurfaceName = PyMOLObjectNames["Chains"][ChainID][SurfaceID]
 1175             PML = PyMOLUtil.SetupPMLForSurfaceView(
 1176                 SurfaceName,
 1177                 SelectionObjectName,
 1178                 Enable=False,
 1179                 Color=OptionsInfo["SurfaceColor"],
 1180                 DisplayAs=DisplayStyle,
 1181             )
 1182             OutFH.write("\n%s\n" % PML)
 1183 
 1184             if GetChainAloneSurfaceChainSelectionStatus(FileIndex, ChainID):
 1185                 # Setup a surface colored by hydrphobicity...
 1186                 HydrophobicSurfaceID = "%s%sSurfaceHydrophobicity" % (SelectionsGroupIDPrefix, SelectionNameGroupID)
 1187                 HydrophobicSurfaceName = PyMOLObjectNames["Chains"][ChainID][HydrophobicSurfaceID]
 1188                 PML = PyMOLUtil.SetupPMLForHydrophobicSurfaceView(
 1189                     HydrophobicSurfaceName,
 1190                     SelectionObjectName,
 1191                     ColorPalette=OptionsInfo["SurfaceColorPalette"],
 1192                     Enable=False,
 1193                     DisplayAs=DisplayStyle,
 1194                 )
 1195                 OutFH.write("\n%s\n" % PML)
 1196 
 1197                 # Setup a surface colored by hydrphobicity and charge...
 1198                 HydrophobicChargeSurfaceID = "%s%sSurfaceHydrophobicityCharge" % (
 1199                     SelectionsGroupIDPrefix,
 1200                     SelectionNameGroupID,
 1201                 )
 1202                 HydrophobicChargeSurfaceName = PyMOLObjectNames["Chains"][ChainID][HydrophobicChargeSurfaceID]
 1203                 PML = PyMOLUtil.SetupPMLForHydrophobicAndChargeSurfaceView(
 1204                     HydrophobicChargeSurfaceName,
 1205                     SelectionObjectName,
 1206                     OptionsInfo["AtomTypesColorNames"]["HydrophobicAtomsColor"],
 1207                     OptionsInfo["AtomTypesColorNames"]["NegativelyChargedAtomsColor"],
 1208                     OptionsInfo["AtomTypesColorNames"]["PositivelyChargedAtomsColor"],
 1209                     OptionsInfo["AtomTypesColorNames"]["OtherAtomsColor"],
 1210                     Enable=False,
 1211                     DisplayAs=DisplayStyle,
 1212                 )
 1213                 OutFH.write("\n%s\n" % PML)
 1214 
 1215             # Setup group for surfaces...
 1216             SurfaceGroupID = "%s%sSurfaceGroup" % (SelectionsGroupIDPrefix, SelectionNameGroupID)
 1217             SurfaceGroupMembersID = "%s%sSurfaceGroupMembers" % (SelectionsGroupIDPrefix, SelectionNameGroupID)
 1218             GenerateAndWritePMLForGroup(
 1219                 OutFH,
 1220                 PyMOLObjectNames["Chains"][ChainID][SurfaceGroupID],
 1221                 PyMOLObjectNames["Chains"][ChainID][SurfaceGroupMembersID],
 1222                 True,
 1223                 "close",
 1224             )
 1225 
 1226         # Setup groups for named selections...
 1227         SelectionsNameGroupID = "%s%sGroup" % (SelectionsGroupIDPrefix, SelectionNameGroupID)
 1228         SelectionsNameGroupMembersID = "%s%sGroupMembers" % (SelectionsGroupIDPrefix, SelectionNameGroupID)
 1229         GenerateAndWritePMLForGroup(
 1230             OutFH,
 1231             PyMOLObjectNames["Chains"][ChainID][SelectionsNameGroupID],
 1232             PyMOLObjectNames["Chains"][ChainID][SelectionsNameGroupMembersID],
 1233             True,
 1234             "open",
 1235         )
 1236 
 1237     # Setup a group for selections...
 1238     SelectionsGroupID = "%sGroup" % (SelectionsGroupIDPrefix)
 1239     SelectionsGroupMembersID = "%sGroupMembers" % (SelectionsGroupIDPrefix)
 1240     GenerateAndWritePMLForGroup(
 1241         OutFH,
 1242         PyMOLObjectNames["Chains"][ChainID][SelectionsGroupID],
 1243         PyMOLObjectNames["Chains"][ChainID][SelectionsGroupMembersID],
 1244         False,
 1245         "close",
 1246     )
 1247 
 1248 
 1249 def WriteChainAloneResidueTypesView(OutFH, FileIndex, PyMOLObjectNames, ChainID):
 1250     """Write out PML for viewing residue types for a chain."""
 1251 
 1252     if not GetChainAloneResidueTypesStatus(FileIndex, ChainID):
 1253         return
 1254 
 1255     ChainName = PyMOLObjectNames["Chains"][ChainID]["ChainAlone"]
 1256 
 1257     # Setup residue types objects...
 1258     ResiduesGroupIDPrefix = "ChainAloneResidues"
 1259     for SubGroupType in ["Aromatic", "Hydrophobic", "Polar", "Positively_Charged", "Negatively_Charged", "Other"]:
 1260         SubGroupID = re.sub("_", "", SubGroupType)
 1261 
 1262         ResiduesObjectID = "%s%sResidues" % (ResiduesGroupIDPrefix, SubGroupID)
 1263         ResiduesObjectName = PyMOLObjectNames["Chains"][ChainID][ResiduesObjectID]
 1264 
 1265         ResiduesSurfaceObjectID = "%s%sSurface" % (ResiduesGroupIDPrefix, SubGroupID)
 1266         ResiduesSurfaceObjectName = PyMOLObjectNames["Chains"][ChainID][ResiduesSurfaceObjectID]
 1267 
 1268         ResiduesColor = OptionsInfo["ResidueTypesParams"][SubGroupType]["Color"]
 1269         ResiduesNames = OptionsInfo["ResidueTypesParams"][SubGroupType]["Residues"]
 1270 
 1271         NegateResidueNames = True if re.match("^Other$", SubGroupType, re.I) else False
 1272         WriteResidueTypesResiduesAndSurfaceView(
 1273             OutFH,
 1274             ChainName,
 1275             ResiduesObjectName,
 1276             ResiduesSurfaceObjectName,
 1277             ResiduesColor,
 1278             ResiduesNames,
 1279             NegateResidueNames,
 1280         )
 1281 
 1282         # Setup sub groups for residue types..
 1283         ResiduesSubGroupID = "%s%sGroup" % (ResiduesGroupIDPrefix, SubGroupID)
 1284         ResiduesSubGroupMembersID = "%s%sGroupMembers" % (ResiduesGroupIDPrefix, SubGroupID)
 1285 
 1286         # Setup residue type sub groups...
 1287         GenerateAndWritePMLForGroup(
 1288             OutFH,
 1289             PyMOLObjectNames["Chains"][ChainID][ResiduesSubGroupID],
 1290             PyMOLObjectNames["Chains"][ChainID][ResiduesSubGroupMembersID],
 1291             True,
 1292             "close",
 1293         )
 1294 
 1295     # Setup residue types group...
 1296     GenerateAndWritePMLForGroup(
 1297         OutFH,
 1298         PyMOLObjectNames["Chains"][ChainID]["ChainAloneResiduesGroup"],
 1299         PyMOLObjectNames["Chains"][ChainID]["ChainAloneResiduesGroupMembers"],
 1300         False,
 1301         "close",
 1302     )
 1303 
 1304 
 1305 def WriteChainAloneBFactorViews(OutFH, FileIndex, PyMOLObjectNames, ChainID):
 1306     """Write out PML for viewing B factor values for a chain."""
 1307 
 1308     if not GetChainAloneBFactorStatus(FileIndex, ChainID):
 1309         return
 1310 
 1311     ChainName = PyMOLObjectNames["Chains"][ChainID]["ChainAlone"]
 1312 
 1313     # Setup cartoon...
 1314     Name = PyMOLObjectNames["Chains"][ChainID]["ChainAloneBFactorCartoon"]
 1315     PML = PyMOLUtil.SetupPMLForBFactorCartoonView(
 1316         Name, ChainName, ColorPalette=OptionsInfo["BFactorColorPalette"], Enable=False
 1317     )
 1318     OutFH.write("\n%s\n" % PML)
 1319 
 1320     # Setup putty...
 1321     Name = PyMOLObjectNames["Chains"][ChainID]["ChainAloneBFactorPutty"]
 1322     PML = PyMOLUtil.SetupPMLForBFactorPuttyView(
 1323         Name, ChainName, ColorPalette=OptionsInfo["BFactorColorPalette"], Enable=True
 1324     )
 1325     OutFH.write("\n%s\n" % PML)
 1326 
 1327     # Setup B factor group...
 1328     GenerateAndWritePMLForGroup(
 1329         OutFH,
 1330         PyMOLObjectNames["Chains"][ChainID]["ChainAloneBFactorGroup"],
 1331         PyMOLObjectNames["Chains"][ChainID]["ChainAloneBFactorGroupMembers"],
 1332         False,
 1333         "close",
 1334     )
 1335 
 1336 
 1337 def WriteChainAloneDisulfideBondsView(OutFH, FileIndex, PyMOLObjectNames, ChainID):
 1338     """Write out PML for viewing disulfide bonds for a chain."""
 1339 
 1340     if not GetChainAloneDisulfideBondsStatus(FileIndex, ChainID):
 1341         return
 1342 
 1343     ChainName = PyMOLObjectNames["Chains"][ChainID]["ChainAlone"]
 1344     Name = PyMOLObjectNames["Chains"][ChainID]["ChainAloneDisulfideBondsResidues"]
 1345 
 1346     PML = PyMOLUtil.SetupPMLForDisulfideBondsView(Name, ChainName, "sticks", Enable=True)
 1347     OutFH.write("\n%s\n" % PML)
 1348 
 1349     # Setup disulfide bonds group...
 1350     GenerateAndWritePMLForGroup(
 1351         OutFH,
 1352         PyMOLObjectNames["Chains"][ChainID]["ChainAloneDisulfideBondsGroup"],
 1353         PyMOLObjectNames["Chains"][ChainID]["ChainAloneDisulfideBondsGroupMembers"],
 1354         True,
 1355         "close",
 1356     )
 1357 
 1358 
 1359 def WriteChainAloneSaltBridgesView(OutFH, FileIndex, PyMOLObjectNames, ChainID):
 1360     """Write out PML for viewing salt bridges for a chain."""
 1361 
 1362     if not GetChainAloneSaltBridgesStatus(FileIndex, ChainID):
 1363         return
 1364 
 1365     ChainName = PyMOLObjectNames["Chains"][ChainID]["ChainAlone"]
 1366 
 1367     # Seup salt bridges resiudes group...
 1368     PositivelyChargedResiduesName = PyMOLObjectNames["Chains"][ChainID][
 1369         "ChainAloneSaltBridgesResiduesPositivelyCharged"
 1370     ]
 1371     PML = PyMOLUtil.SetupPMLForSaltBridgesResiduesView(
 1372         PositivelyChargedResiduesName,
 1373         ChainName,
 1374         OptionsInfo["SaltBridgesChainResiduesInfo"]["Positively_Charged"],
 1375         "lines",
 1376         Enable=True,
 1377     )
 1378     OutFH.write("\n%s\n" % PML)
 1379 
 1380     NegativelyChargedResiduesName = PyMOLObjectNames["Chains"][ChainID][
 1381         "ChainAloneSaltBridgesResiduesNegativelyCharged"
 1382     ]
 1383     PML = PyMOLUtil.SetupPMLForSaltBridgesResiduesView(
 1384         NegativelyChargedResiduesName,
 1385         ChainName,
 1386         OptionsInfo["SaltBridgesChainResiduesInfo"]["Negatively_Charged"],
 1387         "lines",
 1388         Enable=True,
 1389     )
 1390     OutFH.write("\n%s\n" % PML)
 1391 
 1392     GenerateAndWritePMLForGroup(
 1393         OutFH,
 1394         PyMOLObjectNames["Chains"][ChainID]["ChainAloneSaltBridgesResiduesGroup"],
 1395         PyMOLObjectNames["Chains"][ChainID]["ChainAloneSaltBridgesResiduesGroupMembers"],
 1396         True,
 1397         "open",
 1398     )
 1399 
 1400     # Setup salt bridges contacts...
 1401     ContactsColor = OptionsInfo["SaltBridgesChainContactsColor"]
 1402     ContactsName = PyMOLObjectNames["Chains"][ChainID]["ChainAloneSaltBridgesContacts"]
 1403     PML = PyMOLUtil.SetupPMLForPolarContactsView(
 1404         ContactsName,
 1405         PositivelyChargedResiduesName,
 1406         NegativelyChargedResiduesName,
 1407         Enable=True,
 1408         Color=ContactsColor,
 1409         Cutoff=OptionsInfo["SaltBridgesChainCutoff"],
 1410     )
 1411     OutFH.write("\n%s\n" % PML)
 1412 
 1413     OutFH.write("""cmd.set("label_color", "%s", "%s")\n""" % (ContactsColor, ContactsName))
 1414 
 1415     # Setup salt bridges group...
 1416     GenerateAndWritePMLForGroup(
 1417         OutFH,
 1418         PyMOLObjectNames["Chains"][ChainID]["ChainAloneSaltBridgesGroup"],
 1419         PyMOLObjectNames["Chains"][ChainID]["ChainAloneSaltBridgesGroupMembers"],
 1420         False,
 1421         "close",
 1422     )
 1423 
 1424 
 1425 def WriteResidueTypesResiduesAndSurfaceView(
 1426     OutFH, SelectionObjectName, Name, SurfaceName, ResiduesColor, ResiduesNames, NegateResidueNames
 1427 ):
 1428     """Write residue types residues and surface view."""
 1429 
 1430     ResidueNamesSelection = "+".join(ResiduesNames)
 1431     if NegateResidueNames:
 1432         Selection = "%s and (not resn %s)" % (SelectionObjectName, ResidueNamesSelection)
 1433     else:
 1434         Selection = "%s and (resn %s)" % (SelectionObjectName, ResidueNamesSelection)
 1435 
 1436     # Setup residues...
 1437     PML = PyMOLUtil.SetupPMLForSelectionDisplayView(
 1438         Name, Selection, "lines", ResiduesColor, True, IgnoreHydrogens=OptionsInfo["IgnoreHydrogens"]
 1439     )
 1440     OutFH.write("\n%s\n" % PML)
 1441 
 1442     # Setup surface...
 1443     PML = PyMOLUtil.SetupPMLForSelectionDisplayView(
 1444         SurfaceName, Selection, "surface", ResiduesColor, True, IgnoreHydrogens=OptionsInfo["IgnoreHydrogens"]
 1445     )
 1446     OutFH.write("\n%s\n" % PML)
 1447 
 1448 
 1449 def WriteSurfaceElectrostaticsView(
 1450     Mode,
 1451     OutFH,
 1452     SelectionObjectName,
 1453     ElectrostaticsGroupName,
 1454     ElectrostaticsGroupMembers,
 1455     DisplayAs=None,
 1456     SurfaceCavityMode=2,
 1457 ):
 1458     """Write out PML for viewing surface electrostatics."""
 1459 
 1460     if len(ElectrostaticsGroupMembers) == 5:
 1461         Name, ContactPotentialName, MapName, LegendName, VolumeName = ElectrostaticsGroupMembers
 1462     else:
 1463         Name, ContactPotentialName, MapName, LegendName = ElectrostaticsGroupMembers
 1464         VolumeName = None
 1465 
 1466     PMLCmds = []
 1467 
 1468     # Setup chain...
 1469     PMLCmds.append("""cmd.create("%s", "(%s)")""" % (Name, SelectionObjectName))
 1470 
 1471     # Setup vacuum electrostatics surface along with associated objects...
 1472     PMLCmds.append("""util.protein_vacuum_esp("%s", mode=2, quiet=0, _self=cmd)""" % (Name))
 1473     PMLCmds.append("""cmd.set_name("%s_e_chg", "%s")""" % (Name, ContactPotentialName))
 1474 
 1475     if DisplayAs is not None:
 1476         PMLCmds.append("""cmd.show("%s", "(%s)")""" % (DisplayAs, ContactPotentialName))
 1477 
 1478     if re.match("^Cavity$", Mode, re.I):
 1479         if SurfaceCavityMode is not None:
 1480             PMLCmds.append("""cmd.set("surface_cavity_mode", %d, "%s")\n""" % (SurfaceCavityMode, ContactPotentialName))
 1481 
 1482     PMLCmds.append(PyMOLUtil.SetupPMLForEnableDisable(ContactPotentialName, Enable=True))
 1483 
 1484     PMLCmds.append("""cmd.set_name("%s_e_map", "%s")""" % (Name, MapName))
 1485     PMLCmds.append(PyMOLUtil.SetupPMLForEnableDisable(MapName, Enable=False))
 1486 
 1487     PMLCmds.append("""cmd.set_name("%s_e_pot", "%s")""" % (Name, LegendName))
 1488     PMLCmds.append(PyMOLUtil.SetupPMLForEnableDisable(LegendName, Enable=False))
 1489 
 1490     if VolumeName is not None:
 1491         PMLCmds.append("""cmd.volume("%s", "%s", "%s", "(%s)")""" % (VolumeName, MapName, "esp", Name))
 1492         PMLCmds.append(PyMOLUtil.SetupPMLForEnableDisable(VolumeName, Enable=False))
 1493 
 1494     # Delete name and take it out from the group membership. It is
 1495     # is already part of ContactPotential object.
 1496     PMLCmds.append("""cmd.delete("%s")""" % (Name))
 1497     ElectrostaticsGroupMembers.pop(0)
 1498 
 1499     PML = "\n".join(PMLCmds)
 1500 
 1501     OutFH.write("\n%s\n" % PML)
 1502 
 1503     # Setup group...
 1504     GenerateAndWritePMLForGroup(OutFH, ElectrostaticsGroupName, ElectrostaticsGroupMembers, False, "close")
 1505 
 1506 
 1507 def GenerateAndWritePMLForGroup(OutFH, GroupName, GroupMembers, Enable=False, Action="close"):
 1508     """Generate and write PML for group."""
 1509 
 1510     PML = PyMOLUtil.SetupPMLForGroup(GroupName, GroupMembers, Enable, Action)
 1511     OutFH.write("""\n""\n"Setting up group %s..."\n""\n""" % GroupName)
 1512     OutFH.write("%s\n" % PML)
 1513 
 1514 
 1515 def WriteTrajectoriesView(OutFH, FileIndex, PyMOLObjectNames):
 1516     """Write out PML for viewing trajectories for a PDB file."""
 1517 
 1518     if not GetTrajectoriesStatus(FileIndex):
 1519         return
 1520 
 1521     # Setup topology view...
 1522     Name = PyMOLObjectNames["Trajectories"]["Topology"]
 1523 
 1524     PMLCmds = []
 1525     PMLCmds.append("""cmd.load("%s", "%s")""" % (OptionsInfo["InfilesInfo"]["InfilesNames"][FileIndex], Name))
 1526     PMLCmds.append("""cmd.show("cartoon", "%s")""" % (Name))
 1527     PMLCmds.append("""util.cba(33, "%s", _self = cmd)""" % (Name))
 1528     PMLCmds.append("""cmd.show("sticks", "(organic and (%s))")""" % (Name))
 1529     PMLCmds.append(PyMOLUtil.SetupPMLForEnableDisable(Name, Enable=False))
 1530 
 1531     PML = "\n".join(PMLCmds)
 1532     OutFH.write("\n%s\n" % PML)
 1533 
 1534     # Write view for each trajectory file...
 1535     for TrajFileIndex, TrajFile in enumerate(OptionsInfo["TrajectoriesInfo"]["TrajFiles"][FileIndex]):
 1536         WriteTrajectoryViewTrajectoryFile(OutFH, FileIndex, PyMOLObjectNames, TrajFileIndex)
 1537 
 1538     GenerateAndWritePMLForGroup(
 1539         OutFH,
 1540         PyMOLObjectNames["Trajectories"]["TrajectoriesGroup"],
 1541         PyMOLObjectNames["Trajectories"]["TrajectoriesGroupMembers"],
 1542         False,
 1543         "close",
 1544     )
 1545 
 1546 
 1547 def WriteTrajectoryViewTrajectoryFile(OutFH, PDBFileIndex, PyMOLObjectNames, TrajFileIndex):
 1548     """Write out PML for viewing a trajectory file."""
 1549 
 1550     TrajFile = OptionsInfo["TrajectoriesInfo"]["TrajFiles"][PDBFileIndex][TrajFileIndex]
 1551     TrajFileID = OptionsInfo["TrajectoriesInfo"]["TrajFilesIDs"][PDBFileIndex][TrajFileIndex]
 1552 
 1553     OutFH.write("""\n""\n"Setting up views for trajectory file ID %s..."\n""\n""" % (TrajFileID))
 1554 
 1555     # Setup trajectory view...
 1556     Name = PyMOLObjectNames["Trajectories"][TrajFileID]["Trajectory"]
 1557     PDBFile = OptionsInfo["InfilesInfo"]["InfilesNames"][PDBFileIndex]
 1558 
 1559     PMLCmds = []
 1560     PMLCmds.append("""cmd.load("%s", "%s")""" % (PDBFile, Name))
 1561     PMLCmds.append("""cmd.load_traj("%s", "%s", state = 1)""" % (TrajFile, Name))
 1562     PMLCmds.append("""cmd.show("cartoon", "%s")""" % (Name))
 1563     PMLCmds.append("""util.cba(33, "%s", _self = cmd)""" % (Name))
 1564     PMLCmds.append("""cmd.show("sticks", "(organic and (%s))")""" % (Name))
 1565     PMLCmds.append(PyMOLUtil.SetupPMLForEnableDisable(Name, Enable=True))
 1566 
 1567     PML = "\n".join(PMLCmds)
 1568     OutFH.write("%s\n" % PML)
 1569 
 1570     # Setup group for a trajectory file...
 1571     Action = "open" if TrajFileIndex == 0 else "close"
 1572     Enable = True if TrajFileIndex == 0 else False
 1573     GenerateAndWritePMLForGroup(
 1574         OutFH,
 1575         PyMOLObjectNames["Trajectories"][TrajFileID]["TrajectoryGroup"],
 1576         PyMOLObjectNames["Trajectories"][TrajFileID]["TrajectoryGroupMembers"],
 1577         Enable,
 1578         Action,
 1579     )
 1580 
 1581 
 1582 def GeneratePyMOLSessionFile():
 1583     """Generate PME file from PML file."""
 1584 
 1585     PSEOutfile = OptionsInfo["PSEOutfile"]
 1586     PMLOutfile = OptionsInfo["PMLOutfile"]
 1587 
 1588     MiscUtil.PrintInfo("\nGenerating file %s..." % PSEOutfile)
 1589 
 1590     PyMOLUtil.ConvertPMLFileToPSEFile(PMLOutfile, PSEOutfile)
 1591 
 1592     if not os.path.exists(PSEOutfile):
 1593         MiscUtil.PrintWarning("Failed to generate PSE file, %s..." % (PSEOutfile))
 1594 
 1595     if not OptionsInfo["PMLOut"]:
 1596         MiscUtil.PrintInfo("Deleting file %s..." % PMLOutfile)
 1597         os.remove(PMLOutfile)
 1598 
 1599 
 1600 def DeleteEmptyPyMOLObjects(OutFH, FileIndex, PyMOLObjectNames):
 1601     """Delete empty PyMOL objects."""
 1602 
 1603     if OptionsInfo["AllowEmptyObjects"]:
 1604         return
 1605 
 1606     SpecifiedChainsAndLigandsInfo = OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"][FileIndex]
 1607     for ChainID in SpecifiedChainsAndLigandsInfo["ChainIDs"]:
 1608         OutFH.write("""\n""\n"Checking and deleting empty objects for chain %s..."\n""\n""" % (ChainID))
 1609 
 1610         # Delete any chain level objects...
 1611         WritePMLToCheckAndDeleteEmptyObjects(OutFH, PyMOLObjectNames["Chains"][ChainID]["Solvent"])
 1612         WritePMLToCheckAndDeleteEmptyObjects(OutFH, PyMOLObjectNames["Chains"][ChainID]["Inorganic"])
 1613 
 1614         # Delete chain selection objects...
 1615         DeleteEmptyChainSelectionsObjects(OutFH, FileIndex, PyMOLObjectNames, ChainID)
 1616 
 1617         # Delete residue type objects...
 1618         DeleteEmptyChainResidueTypesObjects(OutFH, FileIndex, PyMOLObjectNames, ChainID)
 1619 
 1620         # Delete disulfide bonds objects...
 1621         DeleteEmptyChainDisulfideBondsObjects(OutFH, FileIndex, PyMOLObjectNames, ChainID)
 1622 
 1623         # Delete salt bridges objects...
 1624         DeleteEmptyChainSaltBridgesObjects(OutFH, FileIndex, PyMOLObjectNames, ChainID)
 1625 
 1626         # Delete ligand objects...
 1627         for LigandID in SpecifiedChainsAndLigandsInfo["LigandIDs"][ChainID]:
 1628             # Delete ligand level objects...
 1629             for GroupID in ["Pocket", "PocketSolvent", "PocketInorganic"]:
 1630                 GroupNameID = "%sGroup" % (GroupID)
 1631                 GroupName = PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupNameID]
 1632 
 1633                 GroupTypeObjectID = "%s" % (GroupID)
 1634                 GroupTypeObjectName = PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupTypeObjectID]
 1635 
 1636                 WritePMLToCheckAndDeleteEmptyObjects(OutFH, GroupTypeObjectName, GroupName)
 1637 
 1638                 if re.match("^Pocket$", GroupID, re.I):
 1639                     DeleteEmptyPocketSelectionsObjects(
 1640                         OutFH, FileIndex, PyMOLObjectNames, ChainID, LigandID, GroupTypeObjectID
 1641                     )
 1642                     DeleteEmptyPocketResidueTypesObjects(
 1643                         OutFH, FileIndex, PyMOLObjectNames, ChainID, LigandID, GroupTypeObjectID
 1644                     )
 1645 
 1646         # Delete docked poses objects...
 1647         DeleteEmptyChainDockedPosesObjects(OutFH, FileIndex, PyMOLObjectNames, ChainID)
 1648 
 1649 
 1650 def DeleteEmptyChainSelectionsObjects(OutFH, FileIndex, PyMOLObjectNames, ChainID):
 1651     """Delete empty chain selection objects"""
 1652 
 1653     if not GetChainAloneContainsSelectionsStatus(FileIndex, ChainID):
 1654         return
 1655 
 1656     SelectionsGroupIDPrefix = "ChainAloneSelections"
 1657 
 1658     for SelectionName in OptionsInfo["ChainSelectionsInfo"]["Names"]:
 1659         SelectionNameGroupID = SelectionName
 1660 
 1661         # Delete surface objects and surface group...
 1662         if GetChainAloneContainsChainSelectionSurfacesStatus(FileIndex, ChainID):
 1663             SurfaceGroupID = "%s%sSurfaceGroup" % (SelectionsGroupIDPrefix, SelectionNameGroupID)
 1664             SurfaceGroupMembersID = "%s%sSurfaceGroupMembers" % (SelectionsGroupIDPrefix, SelectionNameGroupID)
 1665             WritePMLToCheckAndDeleteEmptyObjects(
 1666                 OutFH,
 1667                 ",".join(PyMOLObjectNames["Chains"][ChainID][SurfaceGroupMembersID]),
 1668                 PyMOLObjectNames["Chains"][ChainID][SurfaceGroupID],
 1669             )
 1670 
 1671         # Delete Selection object and selection name group...
 1672         SelectionObjectID = "%s%sSelection" % (SelectionsGroupIDPrefix, SelectionNameGroupID)
 1673         SelectionsGroupID = "%s%sGroup" % (SelectionsGroupIDPrefix, SelectionNameGroupID)
 1674         WritePMLToCheckAndDeleteEmptyObjects(
 1675             OutFH,
 1676             PyMOLObjectNames["Chains"][ChainID][SelectionObjectID],
 1677             PyMOLObjectNames["Chains"][ChainID][SelectionsGroupID],
 1678         )
 1679 
 1680 
 1681 def DeleteEmptyChainResidueTypesObjects(OutFH, FileIndex, PyMOLObjectNames, ChainID):
 1682     """Delete empty chain residue objects."""
 1683 
 1684     if not GetChainAloneResidueTypesStatus(FileIndex, ChainID):
 1685         return
 1686 
 1687     ResiduesGroupIDPrefix = "ChainAloneResidues"
 1688     for GroupType in ["Aromatic", "Hydrophobic", "Polar", "Positively_Charged", "Negatively_Charged", "Other"]:
 1689         GroupID = re.sub("_", "", GroupType)
 1690 
 1691         ResiduesGroupID = "%s%sGroup" % (ResiduesGroupIDPrefix, GroupID)
 1692         GroupName = PyMOLObjectNames["Chains"][ChainID][ResiduesGroupID]
 1693 
 1694         GroupObjectNamesList = []
 1695 
 1696         ResiduesObjectID = "%s%sResidues" % (ResiduesGroupIDPrefix, GroupID)
 1697         ResiduesObjectName = PyMOLObjectNames["Chains"][ChainID][ResiduesObjectID]
 1698         GroupObjectNamesList.append(ResiduesObjectName)
 1699 
 1700         ResiduesSurfaceObjectID = "%s%sSurface" % (ResiduesGroupIDPrefix, GroupID)
 1701         ResiduesSurfaceObjectName = PyMOLObjectNames["Chains"][ChainID][ResiduesSurfaceObjectID]
 1702         GroupObjectNamesList.append(ResiduesSurfaceObjectName)
 1703 
 1704         GroupObjectNames = ",".join(GroupObjectNamesList)
 1705         WritePMLToCheckAndDeleteEmptyObjects(OutFH, GroupObjectNames, GroupName)
 1706 
 1707 
 1708 def DeleteEmptyChainDisulfideBondsObjects(OutFH, FileIndex, PyMOLObjectNames, ChainID):
 1709     """Delete empty chain disulfide bonds objects."""
 1710 
 1711     if not GetChainAloneDisulfideBondsStatus(FileIndex, ChainID):
 1712         return
 1713 
 1714     WritePMLToCheckAndDeleteEmptyObjects(
 1715         OutFH,
 1716         PyMOLObjectNames["Chains"][ChainID]["ChainAloneDisulfideBondsResidues"],
 1717         PyMOLObjectNames["Chains"][ChainID]["ChainAloneDisulfideBondsGroup"],
 1718     )
 1719 
 1720 
 1721 def DeleteEmptyChainSaltBridgesObjects(OutFH, FileIndex, PyMOLObjectNames, ChainID):
 1722     """Delete empty chain salt bridges objects."""
 1723 
 1724     if not GetChainAloneSaltBridgesStatus(FileIndex, ChainID):
 1725         return
 1726 
 1727     Names = []
 1728     Names.append(PyMOLObjectNames["Chains"][ChainID]["ChainAloneSaltBridgesResiduesPositivelyCharged"])
 1729     Names.append(PyMOLObjectNames["Chains"][ChainID]["ChainAloneSaltBridgesResiduesNegativelyCharged"])
 1730 
 1731     WritePMLToCheckAndDeleteEmptyObjects(
 1732         OutFH, ",".join(Names), PyMOLObjectNames["Chains"][ChainID]["ChainAloneSaltBridgesGroup"]
 1733     )
 1734 
 1735 
 1736 def DeleteEmptyPocketSelectionsObjects(OutFH, FileIndex, PyMOLObjectNames, ChainID, LigandID, PocketObjectID):
 1737     """Delete empty pocket selection objects."""
 1738 
 1739     if not GetPocketContainsSelectionsStatus(FileIndex, ChainID, LigandID):
 1740         return
 1741 
 1742     SelectionsGroupIDPrefix = "PocketSelectionsGroup"
 1743 
 1744     for SelectionName in OptionsInfo["PocketChainSelectionsInfo"]["Names"]:
 1745         SelectionNameGroupID = SelectionName
 1746 
 1747         # Delete surface objects and surface group...
 1748         if GetPocketSelectionSurfaceChainStatus(FileIndex, ChainID, LigandID):
 1749             SurfaceGroupID = "%s%sSurfaceGroup" % (SelectionsGroupIDPrefix, SelectionNameGroupID)
 1750             SurfaceGroupMembersID = "%s%sSurfaceGroupMembers" % (SelectionsGroupIDPrefix, SelectionNameGroupID)
 1751             WritePMLToCheckAndDeleteEmptyObjects(
 1752                 OutFH,
 1753                 ",".join(PyMOLObjectNames["Ligands"][ChainID][LigandID][SurfaceGroupMembersID]),
 1754                 PyMOLObjectNames["Ligands"][ChainID][LigandID][SurfaceGroupID],
 1755             )
 1756 
 1757         # Delete Selection object and selection name group...
 1758         SelectionObjectID = "%s%sSelection" % (SelectionsGroupIDPrefix, SelectionNameGroupID)
 1759         SelectionsGroupID = "%s%sGroup" % (SelectionsGroupIDPrefix, SelectionNameGroupID)
 1760         WritePMLToCheckAndDeleteEmptyObjects(
 1761             OutFH,
 1762             PyMOLObjectNames["Ligands"][ChainID][LigandID][SelectionObjectID],
 1763             PyMOLObjectNames["Ligands"][ChainID][LigandID][SelectionsGroupID],
 1764         )
 1765 
 1766 
 1767 def DeleteEmptyPocketResidueTypesObjects(OutFH, FileIndex, PyMOLObjectNames, ChainID, LigandID, PocketObjectID):
 1768     """Delete empty chain residue objects."""
 1769 
 1770     if not GetPocketResidueTypesStatus(FileIndex, ChainID, LigandID):
 1771         return
 1772 
 1773     ResiduesGroupID = "%sResiduesGroup" % (PocketObjectID)
 1774 
 1775     for SubGroupType in ["Aromatic", "Hydrophobic", "Polar", "Positively_Charged", "Negatively_Charged", "Other"]:
 1776         SubGroupID = re.sub("_", "", SubGroupType)
 1777 
 1778         ResiduesSubGroupID = "%s%sGroup" % (ResiduesGroupID, SubGroupID)
 1779         ResiduesSubMembersGroupID = "%sMembers" % (ResiduesSubGroupID)
 1780 
 1781         SubGroupName = PyMOLObjectNames["Ligands"][ChainID][LigandID][ResiduesSubGroupID]
 1782         SubGroupObjectNames = ",".join(PyMOLObjectNames["Ligands"][ChainID][LigandID][ResiduesSubMembersGroupID])
 1783 
 1784         WritePMLToCheckAndDeleteEmptyObjects(OutFH, SubGroupObjectNames, SubGroupName)
 1785 
 1786 
 1787 def DeleteEmptyChainDockedPosesObjects(OutFH, PDBFileIndex, PyMOLObjectNames, ChainID):
 1788     """Delete empty chain docked poses objest."""
 1789 
 1790     if not GetChainAloneDockedPosesStatus(PDBFileIndex, ChainID):
 1791         return
 1792 
 1793     SpecifiedChainsAndLigandsInfo = OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"][PDBFileIndex]
 1794     DockedPosesInfo = OptionsInfo["DockedPosesInfo"]
 1795 
 1796     for InputFileIndex, InputFile in enumerate(SpecifiedChainsAndLigandsInfo["DockedPosesInputFiles"][ChainID]):
 1797         InputFileID = DockedPosesInfo["InputFilesIDs"][PDBFileIndex][InputFileIndex]
 1798         for GroupID in ["Pocket", "PocketSolvent", "PocketInorganic"]:
 1799             GroupNameID = "%sGroup" % (GroupID)
 1800             GroupName = PyMOLObjectNames["DockedPosesInputFile"][ChainID][InputFileID][GroupNameID]
 1801 
 1802             GroupTypeObjectID = "%sPocket" % (GroupID)
 1803             GroupTypeObjectName = PyMOLObjectNames["DockedPosesInputFile"][ChainID][InputFileID][GroupTypeObjectID]
 1804 
 1805             WritePMLToCheckAndDeleteEmptyObjects(OutFH, GroupTypeObjectName, GroupName)
 1806 
 1807 
 1808 def WritePMLToCheckAndDeleteEmptyObjects(OutFH, ObjectName, ParentObjectName=None):
 1809     """Write PML to check and delete empty PyMOL objects."""
 1810 
 1811     if ParentObjectName is None:
 1812         PML = """CheckAndDeleteEmptyObjects("%s")""" % (ObjectName)
 1813     else:
 1814         PML = """CheckAndDeleteEmptyObjects("%s", "%s")""" % (ObjectName, ParentObjectName)
 1815 
 1816     OutFH.write("%s\n" % PML)
 1817 
 1818 
 1819 def SetupPyMOLObjectNames(FileIndex):
 1820     """Setup hierarchy of PyMOL groups and objects for ligand centric views of
 1821     chains and ligands present in input file.
 1822     """
 1823 
 1824     PyMOLObjectNames = {}
 1825     PyMOLObjectNames["Chains"] = {}
 1826     PyMOLObjectNames["Ligands"] = {}
 1827     PyMOLObjectNames["DockedPosesInputFile"] = {}
 1828     PyMOLObjectNames["Trajectories"] = {}
 1829 
 1830     # Setup groups and objects for complex...
 1831     SetupPyMOLObjectNamesForComplex(FileIndex, PyMOLObjectNames)
 1832 
 1833     # Setup groups and object for trajectories...
 1834     if GetTrajectoriesStatus(FileIndex):
 1835         SetupPyMOLObjectNamesForTrajectories(FileIndex, PyMOLObjectNames)
 1836 
 1837     # Setup groups and objects for chain...
 1838     SpecifiedChainsAndLigandsInfo = OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"][FileIndex]
 1839     for ChainID in SpecifiedChainsAndLigandsInfo["ChainIDs"]:
 1840         SetupPyMOLObjectNamesForChain(FileIndex, PyMOLObjectNames, ChainID)
 1841 
 1842         # Setup groups and objects for ligand...
 1843         for LigandID in SpecifiedChainsAndLigandsInfo["LigandIDs"][ChainID]:
 1844             SetupPyMOLObjectNamesForLigand(FileIndex, PyMOLObjectNames, ChainID, LigandID)
 1845 
 1846         # Setup group and objects for docked poses...
 1847         if GetChainAloneDockedPosesStatus(FileIndex, ChainID):
 1848             SetupPyMOLObjectNamesForDockedPoses(FileIndex, PyMOLObjectNames, ChainID)
 1849 
 1850     return PyMOLObjectNames
 1851 
 1852 
 1853 def SetupPyMOLObjectNamesForComplex(FileIndex, PyMOLObjectNames):
 1854     """Setup groups and objects for complex."""
 1855 
 1856     PDBFileRoot = OptionsInfo["InfilesInfo"]["InfilesRoots"][FileIndex]
 1857 
 1858     PDBGroupName = "%s" % PDBFileRoot
 1859     PyMOLObjectNames["PDBGroup"] = PDBGroupName
 1860     PyMOLObjectNames["PDBGroupMembers"] = []
 1861 
 1862     ComplexGroupName = "%s.Complex" % PyMOLObjectNames["PDBGroup"]
 1863     PyMOLObjectNames["ComplexGroup"] = ComplexGroupName
 1864     PyMOLObjectNames["PDBGroupMembers"].append(ComplexGroupName)
 1865 
 1866     PyMOLObjectNames["Complex"] = "%s.Complex" % ComplexGroupName
 1867     if OptionsInfo["SurfaceComplex"]:
 1868         PyMOLObjectNames["ComplexHydrophobicSurface"] = "%s.Surface" % ComplexGroupName
 1869 
 1870     PyMOLObjectNames["ComplexGroupMembers"] = []
 1871     PyMOLObjectNames["ComplexGroupMembers"].append(PyMOLObjectNames["Complex"])
 1872     if OptionsInfo["SurfaceComplex"]:
 1873         PyMOLObjectNames["ComplexGroupMembers"].append(PyMOLObjectNames["ComplexHydrophobicSurface"])
 1874 
 1875 
 1876 def SetupPyMOLObjectNamesForTrajectories(FileIndex, PyMOLObjectNames):
 1877     """Setup groups and objects for a PDB file."""
 1878 
 1879     if not GetTrajectoriesStatus(FileIndex):
 1880         return
 1881 
 1882     # Setup a group for trajectories....
 1883     TrajectoriesGroupName = "%s.Trajectories" % PyMOLObjectNames["PDBGroup"]
 1884     PyMOLObjectNames["Trajectories"]["TrajectoriesGroup"] = TrajectoriesGroupName
 1885     PyMOLObjectNames["PDBGroupMembers"].append(TrajectoriesGroupName)
 1886 
 1887     PyMOLObjectNames["Trajectories"]["TrajectoriesGroupMembers"] = []
 1888 
 1889     # Setup a topolgy object...
 1890     TopologyName = "%s.Topology" % TrajectoriesGroupName
 1891     PyMOLObjectNames["Trajectories"]["Topology"] = TopologyName
 1892     PyMOLObjectNames["Trajectories"]["TrajectoriesGroupMembers"].append(TopologyName)
 1893 
 1894     # Setup trajectory objects...
 1895     for TrajFileIndex, TrajFile in enumerate(OptionsInfo["TrajectoriesInfo"]["TrajFiles"][FileIndex]):
 1896         SetupPyMOLObjectNamesForTrajectoryFile(FileIndex, PyMOLObjectNames, TrajFileIndex)
 1897 
 1898 
 1899 def SetupPyMOLObjectNamesForTrajectoryFile(PDBFileIndex, PyMOLObjectNames, TrajFileIndex):
 1900     """Setup groups and objest for a trajectory file for a PDB file."""
 1901 
 1902     TrajFileID = OptionsInfo["TrajectoriesInfo"]["TrajFilesIDs"][PDBFileIndex][TrajFileIndex]
 1903 
 1904     PyMOLObjectNames["Trajectories"][TrajFileID] = {}
 1905 
 1906     TrajectoriesGroupName = PyMOLObjectNames["Trajectories"]["TrajectoriesGroup"]
 1907 
 1908     # Setup a trajectories level trajectory file group...
 1909     TrajectoryFileGroupName = "%s.%s" % (TrajectoriesGroupName, TrajFileID)
 1910     PyMOLObjectNames["Trajectories"][TrajFileID]["TrajectoryGroup"] = TrajectoryFileGroupName
 1911     PyMOLObjectNames["Trajectories"]["TrajectoriesGroupMembers"].append(TrajectoryFileGroupName)
 1912 
 1913     PyMOLObjectNames["Trajectories"][TrajFileID]["TrajectoryGroupMembers"] = []
 1914 
 1915     # Setup object for a trajectory file...
 1916     TrajectoryName = "%s.Trajectory" % (TrajectoryFileGroupName)
 1917     PyMOLObjectNames["Trajectories"][TrajFileID]["Trajectory"] = TrajectoryName
 1918     PyMOLObjectNames["Trajectories"][TrajFileID]["TrajectoryGroupMembers"].append(TrajectoryName)
 1919 
 1920 
 1921 def SetupPyMOLObjectNamesForChain(FileIndex, PyMOLObjectNames, ChainID):
 1922     """Setup groups and objects for chain."""
 1923 
 1924     PDBGroupName = PyMOLObjectNames["PDBGroup"]
 1925 
 1926     PyMOLObjectNames["Chains"][ChainID] = {}
 1927     PyMOLObjectNames["Ligands"][ChainID] = {}
 1928 
 1929     # Set up chain group and chain objects...
 1930     ChainGroupName = "%s.Chain%s" % (PDBGroupName, ChainID)
 1931     PyMOLObjectNames["Chains"][ChainID]["ChainGroup"] = ChainGroupName
 1932     PyMOLObjectNames["PDBGroupMembers"].append(ChainGroupName)
 1933     PyMOLObjectNames["Chains"][ChainID]["ChainGroupMembers"] = []
 1934 
 1935     # Setup chain complex group and objects...
 1936     ChainComplexGroupName = "%s.Complex" % (ChainGroupName)
 1937     PyMOLObjectNames["Chains"][ChainID]["ChainComplexGroup"] = ChainComplexGroupName
 1938     PyMOLObjectNames["Chains"][ChainID]["ChainGroupMembers"].append(ChainComplexGroupName)
 1939 
 1940     PyMOLObjectNames["Chains"][ChainID]["ChainComplexGroupMembers"] = []
 1941 
 1942     Name = "%s.Complex" % (ChainComplexGroupName)
 1943     PyMOLObjectNames["Chains"][ChainID]["ChainComplex"] = Name
 1944     PyMOLObjectNames["Chains"][ChainID]["ChainComplexGroupMembers"].append(Name)
 1945 
 1946     if OptionsInfo["SurfaceChainComplex"]:
 1947         Name = "%s.Surface" % (ChainComplexGroupName)
 1948         PyMOLObjectNames["Chains"][ChainID]["ChainComplexHydrophobicSurface"] = Name
 1949         PyMOLObjectNames["Chains"][ChainID]["ChainComplexGroupMembers"].append(Name)
 1950 
 1951     # Setup up a group for individual chains...
 1952     ChainAloneGroupName = "%s.Chain" % (ChainGroupName)
 1953     PyMOLObjectNames["Chains"][ChainID]["ChainAloneGroup"] = ChainAloneGroupName
 1954     PyMOLObjectNames["Chains"][ChainID]["ChainGroupMembers"].append(ChainAloneGroupName)
 1955 
 1956     PyMOLObjectNames["Chains"][ChainID]["ChainAloneGroupMembers"] = []
 1957 
 1958     Name = "%s.Chain" % (ChainAloneGroupName)
 1959     PyMOLObjectNames["Chains"][ChainID]["ChainAlone"] = Name
 1960     PyMOLObjectNames["Chains"][ChainID]["ChainAloneGroupMembers"].append(Name)
 1961 
 1962     if GetChainAloneBFactorStatus(FileIndex, ChainID):
 1963         # Setup B factor group and add it to chain alone group...
 1964         BFactorGroupName = "%s.BFactor" % (ChainAloneGroupName)
 1965         PyMOLObjectNames["Chains"][ChainID]["ChainAloneBFactorGroup"] = BFactorGroupName
 1966         PyMOLObjectNames["Chains"][ChainID]["ChainAloneGroupMembers"].append(BFactorGroupName)
 1967 
 1968         PyMOLObjectNames["Chains"][ChainID]["ChainAloneBFactorGroupMembers"] = []
 1969 
 1970         # Setup cartoon...
 1971         Name = "%s.Cartoon" % (BFactorGroupName)
 1972         PyMOLObjectNames["Chains"][ChainID]["ChainAloneBFactorCartoon"] = Name
 1973         PyMOLObjectNames["Chains"][ChainID]["ChainAloneBFactorGroupMembers"].append(Name)
 1974 
 1975         # Setup putty...
 1976         Name = "%s.Putty" % (BFactorGroupName)
 1977         PyMOLObjectNames["Chains"][ChainID]["ChainAloneBFactorPutty"] = Name
 1978         PyMOLObjectNames["Chains"][ChainID]["ChainAloneBFactorGroupMembers"].append(Name)
 1979 
 1980     if GetChainAloneContainsSelectionsStatus(FileIndex, ChainID):
 1981         # Setup selections group and its subgroups..
 1982         SelectionsGroupName = "%s.Selections" % (ChainAloneGroupName)
 1983 
 1984         SelectionsGroupIDPrefix = "ChainAloneSelections"
 1985         SelectionsGroupID = "%sGroup" % SelectionsGroupIDPrefix
 1986 
 1987         # Add selections group to chain alone group...
 1988         PyMOLObjectNames["Chains"][ChainID][SelectionsGroupID] = SelectionsGroupName
 1989         PyMOLObjectNames["Chains"][ChainID]["ChainAloneGroupMembers"].append(SelectionsGroupName)
 1990 
 1991         # Initialize selections group members...
 1992         SelectionsGroupMembersID = "%sGroupMembers" % SelectionsGroupIDPrefix
 1993         PyMOLObjectNames["Chains"][ChainID][SelectionsGroupMembersID] = []
 1994 
 1995         # Setup selections name sub group and its members...
 1996         for SelectionName in OptionsInfo["ChainSelectionsInfo"]["Names"]:
 1997             SelectionNameGroupID = SelectionName
 1998 
 1999             SelectionsNameGroupName = "%s.%s" % (SelectionsGroupName, SelectionName)
 2000             SelectionsNameGroupID = "%s%sGroup" % (SelectionsGroupIDPrefix, SelectionNameGroupID)
 2001 
 2002             # Add selections name sub group to selections group...
 2003             PyMOLObjectNames["Chains"][ChainID][SelectionsNameGroupID] = SelectionsNameGroupName
 2004             PyMOLObjectNames["Chains"][ChainID][SelectionsGroupMembersID].append(SelectionsNameGroupName)
 2005 
 2006             # Initialize selections names sub group members...
 2007             SelectionsNameGroupMembersID = "%s%sGroupMembers" % (SelectionsGroupIDPrefix, SelectionNameGroupID)
 2008             PyMOLObjectNames["Chains"][ChainID][SelectionsNameGroupMembersID] = []
 2009 
 2010             # Add selection member to selections name group...
 2011             SubGroupMemberName = "%s.Selection" % (SelectionsNameGroupName)
 2012             SubGroupMemberID = "%s%sSelection" % (SelectionsGroupIDPrefix, SelectionNameGroupID)
 2013 
 2014             PyMOLObjectNames["Chains"][ChainID][SubGroupMemberID] = SubGroupMemberName
 2015             PyMOLObjectNames["Chains"][ChainID][SelectionsNameGroupMembersID].append(SubGroupMemberName)
 2016 
 2017             if GetChainAloneContainsChainSelectionSurfacesStatus(FileIndex, ChainID):
 2018                 # Setup a surface sub group and add it to selections name group...
 2019 
 2020                 SelectionsNameSurfaceGroupName = "%s.Surface" % (SelectionsNameGroupName)
 2021                 SelectionsNameSurfaceGroupID = "%s%sSurfaceGroup" % (SelectionsGroupIDPrefix, SelectionNameGroupID)
 2022 
 2023                 # Add selection surface group to selection name group...
 2024                 PyMOLObjectNames["Chains"][ChainID][SelectionsNameSurfaceGroupID] = SelectionsNameSurfaceGroupName
 2025                 PyMOLObjectNames["Chains"][ChainID][SelectionsNameGroupMembersID].append(SelectionsNameSurfaceGroupName)
 2026 
 2027                 # Initialize surface names sub group members...
 2028                 SelectionsNameSurfaceGroupMembersID = "%s%sSurfaceGroupMembers" % (
 2029                     SelectionsGroupIDPrefix,
 2030                     SelectionNameGroupID,
 2031                 )
 2032                 PyMOLObjectNames["Chains"][ChainID][SelectionsNameSurfaceGroupMembersID] = []
 2033 
 2034                 # Setup a generic color surface...
 2035                 SubGroupMemberName = "%s.Surface" % (SelectionsNameSurfaceGroupName)
 2036                 SubGroupMemberID = "%s%s%sSurface" % (SelectionsGroupIDPrefix, SelectionNameGroupID, "Surface")
 2037                 PyMOLObjectNames["Chains"][ChainID][SubGroupMemberID] = SubGroupMemberName
 2038                 PyMOLObjectNames["Chains"][ChainID][SelectionsNameSurfaceGroupMembersID].append(SubGroupMemberName)
 2039 
 2040                 if GetChainAloneSurfaceChainSelectionStatus(FileIndex, ChainID):
 2041                     # Setup surfaces...
 2042                     for MemberType in ["Hydrophobicity", "Hydrophobicity_Charge"]:
 2043                         MemberID = re.sub("_", "", MemberType)
 2044 
 2045                         SubGroupMemberName = "%s.%s" % (SelectionsNameSurfaceGroupName, MemberType)
 2046                         SubGroupMemberID = "%s%s%s%s" % (
 2047                             SelectionsGroupIDPrefix,
 2048                             SelectionNameGroupID,
 2049                             "Surface",
 2050                             MemberID,
 2051                         )
 2052 
 2053                         PyMOLObjectNames["Chains"][ChainID][SubGroupMemberID] = SubGroupMemberName
 2054                         PyMOLObjectNames["Chains"][ChainID][SelectionsNameSurfaceGroupMembersID].append(
 2055                             SubGroupMemberName
 2056                         )
 2057 
 2058     if GetChainAloneResidueTypesStatus(FileIndex, ChainID):
 2059         # Setup residue type group and its subgroups...
 2060         ResiduesGroupName = "%s.Residues" % (ChainAloneGroupName)
 2061 
 2062         ResiduesGroupIDPrefix = "ChainAloneResidues"
 2063         ResiduesGroupID = "%sGroup" % ResiduesGroupIDPrefix
 2064 
 2065         # Add residue group to chain alone group...
 2066         PyMOLObjectNames["Chains"][ChainID][ResiduesGroupID] = ResiduesGroupName
 2067         PyMOLObjectNames["Chains"][ChainID]["ChainAloneGroupMembers"].append(ResiduesGroupName)
 2068 
 2069         # Initialize residue group members...
 2070         ResiduesGroupMembersID = "%sGroupMembers" % ResiduesGroupIDPrefix
 2071         PyMOLObjectNames["Chains"][ChainID][ResiduesGroupMembersID] = []
 2072 
 2073         # Setup residues sub groups and its members...
 2074         for SubGroupType in ["Aromatic", "Hydrophobic", "Polar", "Positively_Charged", "Negatively_Charged", "Other"]:
 2075             SubGroupID = re.sub("_", "", SubGroupType)
 2076 
 2077             ResiduesSubGroupName = "%s.%s" % (ResiduesGroupName, SubGroupType)
 2078             ResiduesSubGroupID = "%s%sGroup" % (ResiduesGroupIDPrefix, SubGroupID)
 2079 
 2080             # Add sub group to residues group...
 2081             PyMOLObjectNames["Chains"][ChainID][ResiduesSubGroupID] = ResiduesSubGroupName
 2082             PyMOLObjectNames["Chains"][ChainID][ResiduesGroupMembersID].append(ResiduesSubGroupName)
 2083 
 2084             # Initialize sub group members...
 2085             ResiduesSubGroupMembersID = "%s%sGroupMembers" % (ResiduesGroupIDPrefix, SubGroupID)
 2086             PyMOLObjectNames["Chains"][ChainID][ResiduesSubGroupMembersID] = []
 2087 
 2088             # Add sub group members to subgroup...
 2089             for MemberType in ["Residues", "Surface"]:
 2090                 MemberID = re.sub("_", "", MemberType)
 2091 
 2092                 SubGroupMemberName = "%s.%s" % (ResiduesSubGroupName, MemberType)
 2093                 SubGroupMemberID = "%s%s%s" % (ResiduesGroupIDPrefix, SubGroupID, MemberID)
 2094 
 2095                 PyMOLObjectNames["Chains"][ChainID][SubGroupMemberID] = SubGroupMemberName
 2096                 PyMOLObjectNames["Chains"][ChainID][ResiduesSubGroupMembersID].append(SubGroupMemberName)
 2097 
 2098     if GetChainAloneContainsSurfacesStatus(FileIndex, ChainID):
 2099         # Setup a surface group and add it to chain alone group...
 2100         SurfaceGroupName = "%s.Surface" % (ChainAloneGroupName)
 2101         PyMOLObjectNames["Chains"][ChainID]["ChainAloneSurfaceGroup"] = SurfaceGroupName
 2102         PyMOLObjectNames["Chains"][ChainID]["ChainAloneGroupMembers"].append(SurfaceGroupName)
 2103 
 2104         PyMOLObjectNames["Chains"][ChainID]["ChainAloneSurfaceGroupMembers"] = []
 2105 
 2106         # Setup a generic color surface...
 2107         Name = "%s.Surface" % (SurfaceGroupName)
 2108         PyMOLObjectNames["Chains"][ChainID]["ChainAloneSurface"] = Name
 2109         PyMOLObjectNames["Chains"][ChainID]["ChainAloneSurfaceGroupMembers"].append(Name)
 2110 
 2111         if GetChainAloneSurfaceChainStatus(FileIndex, ChainID):
 2112             # Setup hydrophobicity surface...
 2113             Name = "%s.Hydrophobicity" % (SurfaceGroupName)
 2114             PyMOLObjectNames["Chains"][ChainID]["ChainAloneHydrophobicSurface"] = Name
 2115             PyMOLObjectNames["Chains"][ChainID]["ChainAloneSurfaceGroupMembers"].append(Name)
 2116 
 2117             # Setup hydrophobicity and charge surface...
 2118             Name = "%s.Hydrophobicity_Charge" % (SurfaceGroupName)
 2119             PyMOLObjectNames["Chains"][ChainID]["ChainAloneHydrophobicChargeSurface"] = Name
 2120             PyMOLObjectNames["Chains"][ChainID]["ChainAloneSurfaceGroupMembers"].append(Name)
 2121 
 2122         if GetChainAloneSurfaceChainElectrostaticsStatus(FileIndex, ChainID):
 2123             # Setup electrostatics group...
 2124             GroupName = "%s.Vacuum_Electrostatics" % (SurfaceGroupName)
 2125             PyMOLObjectNames["Chains"][ChainID]["ChainAloneElectrostaticsGroup"] = GroupName
 2126             PyMOLObjectNames["Chains"][ChainID]["ChainAloneSurfaceGroupMembers"].append(GroupName)
 2127 
 2128             # Setup electrostatics group members...
 2129             PyMOLObjectNames["Chains"][ChainID]["ChainAloneElectrostaticsGroupMembers"] = []
 2130 
 2131             for MemberType in ["Chain", "Contact_Potential", "Map", "Legend", "Volume"]:
 2132                 MemberID = re.sub("_", "", MemberType)
 2133 
 2134                 Name = "%s.%s" % (GroupName, MemberType)
 2135                 NameID = "ChainAloneElectrostaticsSurface%s" % MemberID
 2136 
 2137                 PyMOLObjectNames["Chains"][ChainID][NameID] = Name
 2138                 PyMOLObjectNames["Chains"][ChainID]["ChainAloneElectrostaticsGroupMembers"].append(Name)
 2139 
 2140     if GetChainAloneDisulfideBondsStatus(FileIndex, ChainID):
 2141         # Setup disulfide bonds group and add it to chain alone group...
 2142         DisulfideBondsGroupName = "%s.Disulfide_Bonds" % (ChainAloneGroupName)
 2143         PyMOLObjectNames["Chains"][ChainID]["ChainAloneDisulfideBondsGroup"] = DisulfideBondsGroupName
 2144         PyMOLObjectNames["Chains"][ChainID]["ChainAloneGroupMembers"].append(DisulfideBondsGroupName)
 2145 
 2146         PyMOLObjectNames["Chains"][ChainID]["ChainAloneDisulfideBondsGroupMembers"] = []
 2147 
 2148         # Setup a residues object for disulfide bonds...
 2149         Name = "%s.Residues" % (DisulfideBondsGroupName)
 2150         PyMOLObjectNames["Chains"][ChainID]["ChainAloneDisulfideBondsResidues"] = Name
 2151         PyMOLObjectNames["Chains"][ChainID]["ChainAloneDisulfideBondsGroupMembers"].append(Name)
 2152 
 2153     if GetChainAloneSaltBridgesStatus(FileIndex, ChainID):
 2154         # Setup salt bridges group and add it to chain alone group...
 2155         SaltBridgesGroupName = "%s.Salt_Bridges" % (ChainAloneGroupName)
 2156         PyMOLObjectNames["Chains"][ChainID]["ChainAloneSaltBridgesGroup"] = SaltBridgesGroupName
 2157         PyMOLObjectNames["Chains"][ChainID]["ChainAloneGroupMembers"].append(SaltBridgesGroupName)
 2158 
 2159         PyMOLObjectNames["Chains"][ChainID]["ChainAloneSaltBridgesGroupMembers"] = []
 2160 
 2161         # Setup residues group and add it to salt bridges group...
 2162         ResiduesGroupName = "%s.Residues" % (SaltBridgesGroupName)
 2163         PyMOLObjectNames["Chains"][ChainID]["ChainAloneSaltBridgesResiduesGroup"] = ResiduesGroupName
 2164         PyMOLObjectNames["Chains"][ChainID]["ChainAloneSaltBridgesGroupMembers"].append(ResiduesGroupName)
 2165 
 2166         PyMOLObjectNames["Chains"][ChainID]["ChainAloneSaltBridgesResiduesGroupMembers"] = []
 2167 
 2168         # Setup objects for residues group...
 2169         Name = "%s.Positively_Charged" % (ResiduesGroupName)
 2170         PyMOLObjectNames["Chains"][ChainID]["ChainAloneSaltBridgesResiduesPositivelyCharged"] = Name
 2171         PyMOLObjectNames["Chains"][ChainID]["ChainAloneSaltBridgesResiduesGroupMembers"].append(Name)
 2172 
 2173         Name = "%s.Negatively_Charged" % (ResiduesGroupName)
 2174         PyMOLObjectNames["Chains"][ChainID]["ChainAloneSaltBridgesResiduesNegativelyCharged"] = Name
 2175         PyMOLObjectNames["Chains"][ChainID]["ChainAloneSaltBridgesResiduesGroupMembers"].append(Name)
 2176 
 2177         # Add contacts object to salt bridges group...
 2178         Name = "%s.Contacts" % (SaltBridgesGroupName)
 2179         PyMOLObjectNames["Chains"][ChainID]["ChainAloneSaltBridgesContacts"] = Name
 2180         PyMOLObjectNames["Chains"][ChainID]["ChainAloneSaltBridgesGroupMembers"].append(Name)
 2181 
 2182     # Setup solvent and inorganic objects for chain...
 2183     for NameID in ["Solvent", "Inorganic"]:
 2184         Name = "%s.%s" % (ChainGroupName, NameID)
 2185         PyMOLObjectNames["Chains"][ChainID][NameID] = Name
 2186         PyMOLObjectNames["Chains"][ChainID]["ChainGroupMembers"].append(Name)
 2187 
 2188 
 2189 def SetupPyMOLObjectNamesForLigand(FileIndex, PyMOLObjectNames, ChainID, LigandID):
 2190     """Stetup groups and objects for ligand."""
 2191 
 2192     PyMOLObjectNames["Ligands"][ChainID][LigandID] = {}
 2193 
 2194     ChainGroupName = PyMOLObjectNames["Chains"][ChainID]["ChainGroup"]
 2195 
 2196     # Setup a chain level ligand group...
 2197     ChainLigandGroupName = "%s.Ligand%s" % (ChainGroupName, LigandID)
 2198     PyMOLObjectNames["Ligands"][ChainID][LigandID]["ChainLigandGroup"] = ChainLigandGroupName
 2199     PyMOLObjectNames["Chains"][ChainID]["ChainGroupMembers"].append(ChainLigandGroupName)
 2200 
 2201     PyMOLObjectNames["Ligands"][ChainID][LigandID]["ChainLigandGroupMembers"] = []
 2202 
 2203     # Set up groups and objects for a specific ligand group...
 2204     for GroupType in ["Ligand", "Pocket", "Pocket_Solvent", "Pocket_Inorganic"]:
 2205         GroupID = re.sub("_", "", GroupType)
 2206         GroupName = "%s.%s" % (ChainLigandGroupName, GroupType)
 2207 
 2208         GroupNameID = "%sGroup" % (GroupID)
 2209         GroupMembersID = "%sGroupMembers" % (GroupID)
 2210 
 2211         PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupNameID] = GroupName
 2212         PyMOLObjectNames["Ligands"][ChainID][LigandID]["ChainLigandGroupMembers"].append(GroupName)
 2213 
 2214         GroupTypeObjectName = "%s.%s" % (GroupName, GroupType)
 2215         GroupTypeObjectID = "%s" % (GroupID)
 2216         PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupTypeObjectID] = GroupTypeObjectName
 2217 
 2218         PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupMembersID] = []
 2219         PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupMembersID].append(GroupTypeObjectName)
 2220 
 2221         if re.match("^Ligand$", GroupType, re.I):
 2222             # Only need to add ball and stick...
 2223             BallAndStickName = "%s.BallAndStick" % (GroupName)
 2224             BallAndStickID = "%sBallAndStick" % (GroupID)
 2225             PyMOLObjectNames["Ligands"][ChainID][LigandID][BallAndStickID] = BallAndStickName
 2226             PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupMembersID].append(BallAndStickName)
 2227 
 2228         if re.match("^(Pocket|Pocket_Solvent|Pocket_Inorganic)$", GroupType, re.I):
 2229             PolarContactsName = "%s.Polar_Contacts" % (GroupName)
 2230             PolarContactsID = "%sPolarContacts" % (GroupID)
 2231             PyMOLObjectNames["Ligands"][ChainID][LigandID][PolarContactsID] = PolarContactsName
 2232             PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupMembersID].append(PolarContactsName)
 2233 
 2234         if re.match("^Pocket_Inorganic$", GroupType, re.I):
 2235             PiCationContactsName = "%s.Pi_Cation_Contacts" % (GroupName)
 2236             PiCationContactsID = "%sPiCationContacts" % (GroupID)
 2237             PyMOLObjectNames["Ligands"][ChainID][LigandID][PiCationContactsID] = PiCationContactsName
 2238             PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupMembersID].append(PiCationContactsName)
 2239 
 2240         if re.match("^Pocket$", GroupType, re.I):
 2241             HydrophobicContactsName = "%s.Hydrophobic_Contacts" % (GroupName)
 2242             HydrophobicContactsID = "%sHydrophobicContacts" % (GroupID)
 2243             PyMOLObjectNames["Ligands"][ChainID][LigandID][HydrophobicContactsID] = HydrophobicContactsName
 2244             PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupMembersID].append(HydrophobicContactsName)
 2245 
 2246             PiPiContactsName = "%s.Pi_Pi_Contacts" % (GroupName)
 2247             PiPiContactsID = "%sPiPiContacts" % (GroupID)
 2248             PyMOLObjectNames["Ligands"][ChainID][LigandID][PiPiContactsID] = PiPiContactsName
 2249             PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupMembersID].append(PiPiContactsName)
 2250 
 2251             PiCationContactsName = "%s.Pi_Cation_Contacts" % (GroupName)
 2252             PiCationContactsID = "%sPiCationContacts" % (GroupID)
 2253             PyMOLObjectNames["Ligands"][ChainID][LigandID][PiCationContactsID] = PiCationContactsName
 2254             PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupMembersID].append(PiCationContactsName)
 2255 
 2256             PiCationContactsName = "%s.Pi_Cation_Contacts" % (GroupName)
 2257             PiCationContactsID = "%sPiCationContacts" % (GroupID)
 2258             PyMOLObjectNames["Ligands"][ChainID][LigandID][PiCationContactsID] = PiCationContactsName
 2259             PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupMembersID].append(PiCationContactsName)
 2260 
 2261             HalogenContactsName = "%s.Halogen_Contacts" % (GroupName)
 2262             HalogenContactsID = "%sHalogenContacts" % (GroupID)
 2263             PyMOLObjectNames["Ligands"][ChainID][LigandID][HalogenContactsID] = HalogenContactsName
 2264             PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupMembersID].append(HalogenContactsName)
 2265 
 2266             if GetPocketContainsSelectionsStatus(FileIndex, ChainID, LigandID):
 2267                 # Setup selections group and its subgroups..
 2268                 SelectionsGroupName = "%s.Selections" % (GroupName)
 2269                 SelectionsGroupID = "%sSelectionsGroup" % (GroupID)
 2270                 SelectionsGroupMembersID = "%sGroupMembers" % (SelectionsGroupID)
 2271 
 2272                 PyMOLObjectNames["Ligands"][ChainID][LigandID][SelectionsGroupID] = SelectionsGroupName
 2273                 PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupMembersID].append(SelectionsGroupName)
 2274 
 2275                 PyMOLObjectNames["Ligands"][ChainID][LigandID][SelectionsGroupMembersID] = []
 2276 
 2277                 # Setup selections name sub group and its members...
 2278                 for SelectionName in OptionsInfo["PocketChainSelectionsInfo"]["Names"]:
 2279                     SelectionNameGroupID = SelectionName
 2280 
 2281                     SelectionsNameGroupName = "%s.%s" % (SelectionsGroupName, SelectionName)
 2282                     SelectionsNameGroupID = "%s%sGroup" % (SelectionsGroupID, SelectionNameGroupID)
 2283                     SelectionsNameGroupMembersID = "%s%sGroupMembers" % (SelectionsGroupID, SelectionNameGroupID)
 2284 
 2285                     # Add selections name sub group to selections group...
 2286                     PyMOLObjectNames["Ligands"][ChainID][LigandID][SelectionsNameGroupID] = SelectionsNameGroupName
 2287                     PyMOLObjectNames["Ligands"][ChainID][LigandID][SelectionsGroupMembersID].append(
 2288                         SelectionsNameGroupName
 2289                     )
 2290 
 2291                     # Initialize selections names sub group members...
 2292                     PyMOLObjectNames["Ligands"][ChainID][LigandID][SelectionsNameGroupMembersID] = []
 2293 
 2294                     # Add selection member to selections name group...
 2295                     SubGroupMemberName = "%s.Selection" % (SelectionsNameGroupName)
 2296                     SubGroupMemberID = "%s%sSelection" % (SelectionsGroupID, SelectionNameGroupID)
 2297 
 2298                     PyMOLObjectNames["Ligands"][ChainID][LigandID][SubGroupMemberID] = SubGroupMemberName
 2299                     PyMOLObjectNames["Ligands"][ChainID][LigandID][SelectionsNameGroupMembersID].append(
 2300                         SubGroupMemberName
 2301                     )
 2302 
 2303                     if GetPocketSelectionSurfaceChainStatus(FileIndex, ChainID, LigandID):
 2304                         # Setup a surface sub group and add it to selections name group...
 2305                         SelectionsNameSurfaceGroupName = "%s.Surface" % (SelectionsNameGroupName)
 2306                         SelectionsNameSurfaceGroupID = "%s%sSurfaceGroup" % (SelectionsGroupID, SelectionNameGroupID)
 2307 
 2308                         # Add selection surface group to selection name group...
 2309                         PyMOLObjectNames["Ligands"][ChainID][LigandID][SelectionsNameSurfaceGroupID] = (
 2310                             SelectionsNameSurfaceGroupName
 2311                         )
 2312                         PyMOLObjectNames["Ligands"][ChainID][LigandID][SelectionsNameGroupMembersID].append(
 2313                             SelectionsNameSurfaceGroupName
 2314                         )
 2315 
 2316                         # Initialize surface names sub group members...
 2317                         SelectionsNameSurfaceGroupMembersID = "%s%sSurfaceGroupMembers" % (
 2318                             SelectionsGroupID,
 2319                             SelectionNameGroupID,
 2320                         )
 2321                         PyMOLObjectNames["Ligands"][ChainID][LigandID][SelectionsNameSurfaceGroupMembersID] = []
 2322 
 2323                         # Setup surfaces...
 2324                         for MemberType in ["Surface", "Hydrophobicity", "Hydrophobicity_Charge"]:
 2325                             MemberID = re.sub("_", "", MemberType)
 2326 
 2327                             SubGroupMemberName = "%s.%s" % (SelectionsNameSurfaceGroupName, MemberType)
 2328                             SubGroupMemberID = "%s%s%s%s" % (
 2329                                 SelectionsGroupID,
 2330                                 SelectionNameGroupID,
 2331                                 "Surface",
 2332                                 MemberID,
 2333                             )
 2334 
 2335                             PyMOLObjectNames["Ligands"][ChainID][LigandID][SubGroupMemberID] = SubGroupMemberName
 2336                             PyMOLObjectNames["Ligands"][ChainID][LigandID][SelectionsNameSurfaceGroupMembersID].append(
 2337                                 SubGroupMemberName
 2338                             )
 2339 
 2340             if GetPocketResidueTypesStatus(FileIndex, ChainID, LigandID):
 2341                 # Setup residue type group and add to pocket group...
 2342                 ResiduesGroupName = "%s.Residues" % (GroupName)
 2343                 ResiduesGroupID = "%sResiduesGroup" % (GroupID)
 2344                 ResiduesGroupMembersID = "%sMembers" % (ResiduesGroupID)
 2345 
 2346                 PyMOLObjectNames["Ligands"][ChainID][LigandID][ResiduesGroupID] = ResiduesGroupName
 2347                 PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupMembersID].append(ResiduesGroupName)
 2348                 PyMOLObjectNames["Ligands"][ChainID][LigandID][ResiduesGroupMembersID] = []
 2349 
 2350                 # Setup residue group subgroup and its members...
 2351                 for SubGroupType in [
 2352                     "Aromatic",
 2353                     "Hydrophobic",
 2354                     "Polar",
 2355                     "Positively_Charged",
 2356                     "Negatively_Charged",
 2357                     "Other",
 2358                 ]:
 2359                     SubGroupID = re.sub("_", "", SubGroupType)
 2360                     ResiduesSubGroupName = "%s.%s" % (ResiduesGroupName, SubGroupType)
 2361                     ResiduesSubGroupID = "%s%sGroup" % (ResiduesGroupID, SubGroupID)
 2362                     ResiduesSubMembersGroupID = "%sMembers" % (ResiduesSubGroupID)
 2363 
 2364                     # Add sub group to residues group...
 2365                     PyMOLObjectNames["Ligands"][ChainID][LigandID][ResiduesSubGroupID] = ResiduesSubGroupName
 2366                     PyMOLObjectNames["Ligands"][ChainID][LigandID][ResiduesGroupMembersID].append(ResiduesSubGroupName)
 2367                     PyMOLObjectNames["Ligands"][ChainID][LigandID][ResiduesSubMembersGroupID] = []
 2368 
 2369                     # Add sub group members to subgroup...
 2370                     for MemberType in ["Residues", "Surface"]:
 2371                         MemberID = re.sub("_", "", MemberType)
 2372                         SubGroupMemberName = "%s.%s" % (ResiduesSubGroupName, MemberType)
 2373                         SubGroupMemberID = "%s%s" % (ResiduesSubGroupID, MemberID)
 2374 
 2375                         PyMOLObjectNames["Ligands"][ChainID][LigandID][SubGroupMemberID] = SubGroupMemberName
 2376                         PyMOLObjectNames["Ligands"][ChainID][LigandID][ResiduesSubMembersGroupID].append(
 2377                             SubGroupMemberName
 2378                         )
 2379 
 2380             if GetPocketContainsSurfaceStatus(FileIndex, ChainID, LigandID):
 2381                 # Setup a surfaces group and add it to pocket group...
 2382                 SurfacesGroupName = "%s.Surfaces" % (GroupName)
 2383                 SurfacesGroupID = "%sSurfacesGroup" % (GroupID)
 2384                 SurfacesGroupMembersID = "%sMembers" % (SurfacesGroupID)
 2385 
 2386                 PyMOLObjectNames["Ligands"][ChainID][LigandID][SurfacesGroupID] = SurfacesGroupName
 2387                 PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupMembersID].append(SurfacesGroupName)
 2388                 PyMOLObjectNames["Ligands"][ChainID][LigandID][SurfacesGroupMembersID] = []
 2389 
 2390                 # Setup surfaces subgroup and its members...
 2391                 for SubGroupType in ["Surface", "Cavity"]:
 2392                     SubGroupID = re.sub("_", "", SubGroupType)
 2393                     SurfacesSubGroupName = "%s.%s" % (SurfacesGroupName, SubGroupType)
 2394                     SurfacesSubGroupID = "%s%sGroup" % (SurfacesGroupID, SubGroupID)
 2395                     SurfacesSubGroupMembersID = "%sMembers" % (SurfacesSubGroupID)
 2396 
 2397                     # Add sub group to surfaces group...
 2398                     PyMOLObjectNames["Ligands"][ChainID][LigandID][SurfacesSubGroupID] = SurfacesSubGroupName
 2399                     PyMOLObjectNames["Ligands"][ChainID][LigandID][SurfacesGroupMembersID].append(SurfacesSubGroupName)
 2400                     PyMOLObjectNames["Ligands"][ChainID][LigandID][SurfacesSubGroupMembersID] = []
 2401 
 2402                     # Setup a generic color surface...
 2403                     SurfaceName = "%s.Surface" % (SurfacesSubGroupName)
 2404                     SurfaceID = "%sSurface" % (SurfacesSubGroupID)
 2405                     PyMOLObjectNames["Ligands"][ChainID][LigandID][SurfaceID] = SurfaceName
 2406                     PyMOLObjectNames["Ligands"][ChainID][LigandID][SurfacesSubGroupMembersID].append(SurfaceName)
 2407 
 2408                     if GetPocketSurfaceChainStatus(FileIndex, ChainID, LigandID):
 2409                         # Surface colored by hydrophobicity...
 2410                         HydrophobicSurfaceName = "%s.Hydrophobicity" % (SurfacesSubGroupName)
 2411                         HydrophobicSurfaceID = "%sHydrophobicSurface" % (SurfacesSubGroupID)
 2412                         PyMOLObjectNames["Ligands"][ChainID][LigandID][HydrophobicSurfaceID] = HydrophobicSurfaceName
 2413                         PyMOLObjectNames["Ligands"][ChainID][LigandID][SurfacesSubGroupMembersID].append(
 2414                             HydrophobicSurfaceName
 2415                         )
 2416 
 2417                         # Surface colored by hydrophobicity and charge...
 2418                         HydrophobicChargeSurfaceName = "%s.Hydrophobicity_Charge" % (SurfacesSubGroupName)
 2419                         HydrophobicChargeSurfaceID = "%sHydrophobicChargeSurface" % (SurfacesSubGroupID)
 2420                         PyMOLObjectNames["Ligands"][ChainID][LigandID][HydrophobicChargeSurfaceID] = (
 2421                             HydrophobicChargeSurfaceName
 2422                         )
 2423                         PyMOLObjectNames["Ligands"][ChainID][LigandID][SurfacesSubGroupMembersID].append(
 2424                             HydrophobicChargeSurfaceName
 2425                         )
 2426 
 2427                     if GetPocketSurfaceChainElectrostaticsStatus(FileIndex, ChainID, LigandID):
 2428                         ElectrostaticsGroupName = "%s.Vacuum_Electrostatics" % (SurfacesSubGroupName)
 2429                         ElectrostaticsGroupID = "%sElectrostaticsGroup" % (SurfacesSubGroupID)
 2430                         ElectrostaticsGroupMembersID = "%sElectrostaticsGroupMembers" % (SurfacesSubGroupID)
 2431 
 2432                         PyMOLObjectNames["Ligands"][ChainID][LigandID][ElectrostaticsGroupID] = ElectrostaticsGroupName
 2433                         PyMOLObjectNames["Ligands"][ChainID][LigandID][SurfacesSubGroupMembersID].append(
 2434                             ElectrostaticsGroupName
 2435                         )
 2436 
 2437                         # Setup electrostatics group members without the volume object...
 2438                         PyMOLObjectNames["Ligands"][ChainID][LigandID][ElectrostaticsGroupMembersID] = []
 2439 
 2440                         for MemberType in ["Pocket", "Contact_Potential", "Map", "Legend"]:
 2441                             MemberID = re.sub("_", "", MemberType)
 2442 
 2443                             Name = "%s.%s" % (ElectrostaticsGroupName, MemberType)
 2444                             NameID = "%s%s" % (ElectrostaticsGroupID, MemberID)
 2445 
 2446                             PyMOLObjectNames["Ligands"][ChainID][LigandID][NameID] = Name
 2447                             PyMOLObjectNames["Ligands"][ChainID][LigandID][ElectrostaticsGroupMembersID].append(Name)
 2448 
 2449 
 2450 def SetupPyMOLObjectNamesForDockedPoses(FileIndex, PyMOLObjectNames, ChainID):
 2451     """Stetup groups and objects for docked poses in input files for a chain."""
 2452 
 2453     PyMOLObjectNames["DockedPosesInputFile"][ChainID] = {}
 2454 
 2455     if not GetChainAloneDockedPosesStatus(FileIndex, ChainID):
 2456         return
 2457 
 2458     # Setup group for docked poses...
 2459     if "DockedPosesGroup" not in PyMOLObjectNames["Chains"][ChainID]:
 2460         # Setup docked poses group at a chain level...
 2461         ChainGroupName = PyMOLObjectNames["Chains"][ChainID]["ChainGroup"]
 2462         DockedPosesGroupName = "%s.%s" % (ChainGroupName, OptionsInfo["DockedPosesGroupName"])
 2463 
 2464         PyMOLObjectNames["Chains"][ChainID]["DockedPosesGroup"] = DockedPosesGroupName
 2465         PyMOLObjectNames["Chains"][ChainID]["ChainGroupMembers"].append(DockedPosesGroupName)
 2466         PyMOLObjectNames["Chains"][ChainID]["DockedPosesGroupMembers"] = []
 2467 
 2468     SpecifiedChainsAndLigandsInfo = OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"][FileIndex]
 2469     for InputFileIndex, InputFile in enumerate(SpecifiedChainsAndLigandsInfo["DockedPosesInputFiles"][ChainID]):
 2470         SetupPyMOLObjectNamesForDockedPosesInputFile(FileIndex, PyMOLObjectNames, ChainID, InputFileIndex)
 2471 
 2472 
 2473 def SetupPyMOLObjectNamesForDockedPosesInputFile(PDBFileIndex, PyMOLObjectNames, ChainID, InputFileIndex):
 2474     """Stetup groups and objects for docked poses in an input file for a chain."""
 2475 
 2476     DockedPosesInfo = OptionsInfo["DockedPosesInfo"]
 2477     DockedPosesDistanceContactsInfo = OptionsInfo["DockedPosesDistanceContactsInfo"]
 2478 
 2479     InputFileID = DockedPosesInfo["InputFilesIDs"][PDBFileIndex][InputFileIndex]
 2480 
 2481     PyMOLObjectNames["DockedPosesInputFile"][ChainID][InputFileID] = {}
 2482 
 2483     DockedPosesGroupName = PyMOLObjectNames["Chains"][ChainID]["DockedPosesGroup"]
 2484 
 2485     # Setup a docked poses level InputFile group...
 2486     DockedPosesInputFileGroupName = "%s.%s" % (DockedPosesGroupName, InputFileID)
 2487     PyMOLObjectNames["DockedPosesInputFile"][ChainID][InputFileID]["DockedPosesGroupName"] = (
 2488         DockedPosesInputFileGroupName
 2489     )
 2490     PyMOLObjectNames["Chains"][ChainID]["DockedPosesGroupMembers"].append(DockedPosesInputFileGroupName)
 2491 
 2492     PyMOLObjectNames["DockedPosesInputFile"][ChainID][InputFileID]["DockedPosesGroupMembers"] = []
 2493 
 2494     # Setup objects for docked poses...
 2495     PosesName = "%s.%s" % (DockedPosesInputFileGroupName, OptionsInfo["DockedPosesName"])
 2496     PyMOLObjectNames["DockedPosesInputFile"][ChainID][InputFileID]["Poses"] = PosesName
 2497     PyMOLObjectNames["DockedPosesInputFile"][ChainID][InputFileID]["DockedPosesGroupMembers"].append(PosesName)
 2498 
 2499     for GroupType in ["Pocket", "Pocket_Solvent", "Pocket_Inorganic"]:
 2500         GroupID = re.sub("_", "", GroupType)
 2501         GroupName = "%s.%s" % (DockedPosesInputFileGroupName, GroupType)
 2502 
 2503         GroupNameID = "%sGroup" % (GroupID)
 2504         GroupMembersID = "%sGroupMembers" % (GroupID)
 2505 
 2506         PyMOLObjectNames["DockedPosesInputFile"][ChainID][InputFileID][GroupNameID] = GroupName
 2507         PyMOLObjectNames["DockedPosesInputFile"][ChainID][InputFileID]["DockedPosesGroupMembers"].append(GroupName)
 2508 
 2509         PyMOLObjectNames["DockedPosesInputFile"][ChainID][InputFileID][GroupMembersID] = []
 2510 
 2511         PocketID = "%sPocket" % GroupID
 2512         PocketName = "%s.Pocket" % GroupName
 2513         PyMOLObjectNames["DockedPosesInputFile"][ChainID][InputFileID][PocketID] = PocketName
 2514         PyMOLObjectNames["DockedPosesInputFile"][ChainID][InputFileID][GroupMembersID].append(PocketName)
 2515 
 2516         if DockedPosesInfo["DistanceContacts"] and re.match("^Pocket$", GroupType, re.I):
 2517             # Setup distance contacts group and add it to pocket group...
 2518             DistanceContactGroupName = "%s.Distance_Contacts" % GroupName
 2519 
 2520             DistanceContactGroupNameID = "%sDistanceContactsGroup" % GroupID
 2521             DistanceContactGroupMembersID = "%sDistanceContactsGroupMembers" % GroupID
 2522 
 2523             PyMOLObjectNames["DockedPosesInputFile"][ChainID][InputFileID][DistanceContactGroupNameID] = (
 2524                 DistanceContactGroupName
 2525             )
 2526             PyMOLObjectNames["DockedPosesInputFile"][ChainID][InputFileID][GroupMembersID].append(
 2527                 DistanceContactGroupName
 2528             )
 2529 
 2530             # Setup distance contacts group members...
 2531             PyMOLObjectNames["DockedPosesInputFile"][ChainID][InputFileID][DistanceContactGroupMembersID] = []
 2532 
 2533             for ContactID in DockedPosesDistanceContactsInfo["ContactIDs"]:
 2534                 DistanceContactID = "%sPocketDistanceContacts%s" % (GroupID, ContactID)
 2535                 DistanceContactName = "%s.Distance_Contacts.%s" % (GroupName, ContactID)
 2536 
 2537                 PyMOLObjectNames["DockedPosesInputFile"][ChainID][InputFileID][DistanceContactID] = DistanceContactName
 2538                 PyMOLObjectNames["DockedPosesInputFile"][ChainID][InputFileID][DistanceContactGroupMembersID].append(
 2539                     DistanceContactName
 2540                 )
 2541 
 2542         PolarContactsID = "%sPolarContacts" % GroupID
 2543         PolarContactsName = "%s.Polar_Contacts" % GroupName
 2544         PyMOLObjectNames["DockedPosesInputFile"][ChainID][InputFileID][PolarContactsID] = PolarContactsName
 2545         PyMOLObjectNames["DockedPosesInputFile"][ChainID][InputFileID][GroupMembersID].append(PolarContactsName)
 2546 
 2547         if re.match("^Pocket_Inorganic$", GroupType, re.I):
 2548             PiCationContactsID = "%sPiCationContacts" % GroupID
 2549             PiCationContactsName = "%s.Pi_Cation_Contacts" % GroupName
 2550             PyMOLObjectNames["DockedPosesInputFile"][ChainID][InputFileID][PiCationContactsID] = PiCationContactsName
 2551             PyMOLObjectNames["DockedPosesInputFile"][ChainID][InputFileID][GroupMembersID].append(PiCationContactsName)
 2552 
 2553         if re.match("^Pocket$", GroupType, re.I):
 2554             HydrophobicContactsID = "%sHydrophobicContacts" % GroupID
 2555             HydrophobicContactsName = "%s.Hydrophobic_Contacts" % GroupName
 2556             PyMOLObjectNames["DockedPosesInputFile"][ChainID][InputFileID][HydrophobicContactsID] = (
 2557                 HydrophobicContactsName
 2558             )
 2559             PyMOLObjectNames["DockedPosesInputFile"][ChainID][InputFileID][GroupMembersID].append(
 2560                 HydrophobicContactsName
 2561             )
 2562 
 2563             PiPiContactsID = "%sPiPiContacts" % GroupID
 2564             PiPiContactsName = "%s.Pi_Pi_Contacts" % GroupName
 2565             PyMOLObjectNames["DockedPosesInputFile"][ChainID][InputFileID][PiPiContactsID] = PiPiContactsName
 2566             PyMOLObjectNames["DockedPosesInputFile"][ChainID][InputFileID][GroupMembersID].append(PiPiContactsName)
 2567 
 2568             PiCationContactsID = "%sPiCationContacts" % GroupID
 2569             PiCationContactsName = "%s.Pi_Cation_Contacts" % GroupName
 2570             PyMOLObjectNames["DockedPosesInputFile"][ChainID][InputFileID][PiCationContactsID] = PiCationContactsName
 2571             PyMOLObjectNames["DockedPosesInputFile"][ChainID][InputFileID][GroupMembersID].append(PiCationContactsName)
 2572 
 2573             HalogenContactsID = "%sHalogenContacts" % GroupID
 2574             HalogenContactsName = "%s.Halogen_Contacts" % GroupName
 2575             PyMOLObjectNames["DockedPosesInputFile"][ChainID][InputFileID][HalogenContactsID] = HalogenContactsName
 2576             PyMOLObjectNames["DockedPosesInputFile"][ChainID][InputFileID][GroupMembersID].append(HalogenContactsName)
 2577 
 2578 
 2579 def RetrieveInfilesInfo():
 2580     """Retrieve information for input files."""
 2581 
 2582     InfilesInfo = {}
 2583 
 2584     InfilesInfo["InfilesNames"] = []
 2585     InfilesInfo["InfilesRoots"] = []
 2586     InfilesInfo["ChainsAndLigandsInfo"] = []
 2587 
 2588     for Infile in OptionsInfo["InfilesNames"]:
 2589         FileDir, FileName, FileExt = MiscUtil.ParseFileName(Infile)
 2590         InfileRoot = FileName
 2591 
 2592         ChainsAndLigandInfo = PyMOLUtil.GetChainsAndLigandsInfo(Infile, InfileRoot)
 2593 
 2594         InfilesInfo["InfilesNames"].append(Infile)
 2595         InfilesInfo["InfilesRoots"].append(InfileRoot)
 2596         InfilesInfo["ChainsAndLigandsInfo"].append(ChainsAndLigandInfo)
 2597 
 2598     OptionsInfo["InfilesInfo"] = InfilesInfo
 2599 
 2600 
 2601 def RetrieveRefFileInfo():
 2602     """Retrieve information for ref file."""
 2603 
 2604     RefFileInfo = {}
 2605     if not OptionsInfo["Align"]:
 2606         OptionsInfo["RefFileInfo"] = RefFileInfo
 2607         return
 2608 
 2609     RefFile = OptionsInfo["RefFileName"]
 2610 
 2611     FileDir, FileName, FileExt = MiscUtil.ParseFileName(RefFile)
 2612     RefFileRoot = FileName
 2613 
 2614     if re.match("^FirstInputFile$", OptionsInfo["AlignRefFile"], re.I):
 2615         ChainsAndLigandInfo = OptionsInfo["InfilesInfo"]["ChainsAndLigandsInfo"][0]
 2616     else:
 2617         MiscUtil.PrintInfo("\nRetrieving chain and ligand information for alignment reference file %s..." % RefFile)
 2618         ChainsAndLigandInfo = PyMOLUtil.GetChainsAndLigandsInfo(RefFile, RefFileRoot)
 2619 
 2620     RefFileInfo["RefFileName"] = RefFile
 2621     RefFileInfo["RefFileRoot"] = RefFileRoot
 2622     RefFileInfo["PyMOLObjectName"] = "AlignRef_%s" % RefFileRoot
 2623     RefFileInfo["ChainsAndLigandsInfo"] = ChainsAndLigandInfo
 2624 
 2625     OptionsInfo["RefFileInfo"] = RefFileInfo
 2626 
 2627 
 2628 def ProcessChainAndLigandIDs():
 2629     """Process specified chain and ligand IDs for infiles."""
 2630 
 2631     OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"] = []
 2632 
 2633     for FileIndex in range(0, len(OptionsInfo["InfilesInfo"]["InfilesNames"])):
 2634         MiscUtil.PrintInfo(
 2635             "\nProcessing specified chain and ligand IDs for input file %s..."
 2636             % OptionsInfo["InfilesInfo"]["InfilesNames"][FileIndex]
 2637         )
 2638 
 2639         ChainsAndLigandsInfo = OptionsInfo["InfilesInfo"]["ChainsAndLigandsInfo"][FileIndex]
 2640         SpecifiedChainsAndLigandsInfo = PyMOLUtil.ProcessChainsAndLigandsOptionsInfo(
 2641             ChainsAndLigandsInfo, "-c, --chainIDs", OptionsInfo["ChainIDs"], "-l, --ligandIDs", OptionsInfo["LigandIDs"]
 2642         )
 2643         ProcessResidueTypesAndSurfaceAndChainSelectionsOptions(FileIndex, SpecifiedChainsAndLigandsInfo)
 2644 
 2645         OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"].append(SpecifiedChainsAndLigandsInfo)
 2646 
 2647         CheckPresenceOfValidLigandIDs(ChainsAndLigandsInfo, SpecifiedChainsAndLigandsInfo)
 2648 
 2649 
 2650 def ProcessResidueTypesAndSurfaceAndChainSelectionsOptions(FileIndex, SpecifiedChainsAndLigandsInfo):
 2651     """Process residue types, surface, and chian selections options for chains and pockets."""
 2652 
 2653     SpecifiedChainsAndLigandsInfo["ChainSurfaces"] = {}
 2654     SpecifiedChainsAndLigandsInfo["SurfaceChain"] = {}
 2655     SpecifiedChainsAndLigandsInfo["SurfaceChainElectrostatics"] = {}
 2656 
 2657     SpecifiedChainsAndLigandsInfo["PocketChainSelections"] = {}
 2658     SpecifiedChainsAndLigandsInfo["PocketChainSelectionsSurfaces"] = {}
 2659     SpecifiedChainsAndLigandsInfo["SurfacePocketChainSelections"] = {}
 2660 
 2661     SpecifiedChainsAndLigandsInfo["PocketSurfaces"] = {}
 2662     SpecifiedChainsAndLigandsInfo["SurfacePocket"] = {}
 2663     SpecifiedChainsAndLigandsInfo["SurfacePocketElectrostatics"] = {}
 2664 
 2665     SpecifiedChainsAndLigandsInfo["ResidueTypesChain"] = {}
 2666     SpecifiedChainsAndLigandsInfo["ResidueTypesPocket"] = {}
 2667 
 2668     SpecifiedChainsAndLigandsInfo["ChainSelections"] = {}
 2669     SpecifiedChainsAndLigandsInfo["ChainSelectionsSurfaces"] = {}
 2670     SpecifiedChainsAndLigandsInfo["SurfaceChainSelections"] = {}
 2671 
 2672     SpecifiedChainsAndLigandsInfo["DisulfideBondsChain"] = {}
 2673     SpecifiedChainsAndLigandsInfo["SaltBridgesChain"] = {}
 2674 
 2675     SpecifiedChainsAndLigandsInfo["BFactorChain"] = {}
 2676 
 2677     # Load infile...
 2678     Infile = OptionsInfo["InfilesInfo"]["InfilesNames"][FileIndex]
 2679     MolName = OptionsInfo["InfilesInfo"]["InfilesRoots"][FileIndex]
 2680     pymol.cmd.load(Infile, MolName)
 2681 
 2682     for ChainID in SpecifiedChainsAndLigandsInfo["ChainIDs"]:
 2683         AminoAcidsPresent = PyMOLUtil.AreAminoAcidResiduesPresent(MolName, ChainID)
 2684 
 2685         # Process BFactors for chains...
 2686         BFactorChain = True if re.match("^yes$", OptionsInfo["BFactorChain"], re.I) else False
 2687         SpecifiedChainsAndLigandsInfo["BFactorChain"][ChainID] = BFactorChain
 2688 
 2689         # Process surfaces for chains...
 2690         if re.match("^auto$", OptionsInfo["SurfaceChain"], re.I):
 2691             SurfaceChain = True if AminoAcidsPresent else False
 2692         else:
 2693             SurfaceChain = True if re.match("^yes$", OptionsInfo["SurfaceChain"], re.I) else False
 2694         SpecifiedChainsAndLigandsInfo["SurfaceChain"][ChainID] = SurfaceChain
 2695 
 2696         if re.match("^auto$", OptionsInfo["SurfaceChainElectrostatics"], re.I):
 2697             SurfaceChainElectrostatics = True if AminoAcidsPresent else False
 2698         else:
 2699             SurfaceChainElectrostatics = (
 2700                 True if re.match("^yes$", OptionsInfo["SurfaceChainElectrostatics"], re.I) else False
 2701             )
 2702         SpecifiedChainsAndLigandsInfo["SurfaceChainElectrostatics"][ChainID] = SurfaceChainElectrostatics
 2703 
 2704         SpecifiedChainsAndLigandsInfo["ChainSurfaces"][ChainID] = SurfaceChain
 2705 
 2706         # Process disulfide bonds for chains...
 2707         if re.match("^auto$", OptionsInfo["DisulfideBondsChain"], re.I):
 2708             DisulfideBondsChain = True if AminoAcidsPresent else False
 2709         else:
 2710             DisulfideBondsChain = True if re.match("^yes$", OptionsInfo["DisulfideBondsChain"], re.I) else False
 2711         SpecifiedChainsAndLigandsInfo["DisulfideBondsChain"][ChainID] = DisulfideBondsChain
 2712 
 2713         # Process salt bridges bonds for chains...
 2714         if re.match("^auto$", OptionsInfo["SaltBridgesChain"], re.I):
 2715             SaltBridgesChain = True if AminoAcidsPresent else False
 2716         else:
 2717             SaltBridgesChain = True if re.match("^yes$", OptionsInfo["SaltBridgesChain"], re.I) else False
 2718         SpecifiedChainsAndLigandsInfo["SaltBridgesChain"][ChainID] = SaltBridgesChain
 2719 
 2720         # Process residue types for chains...
 2721         if re.match("^auto$", OptionsInfo["ResidueTypesChain"], re.I):
 2722             ResidueTypesChain = True if AminoAcidsPresent else False
 2723         else:
 2724             ResidueTypesChain = True if re.match("^yes$", OptionsInfo["ResidueTypesChain"], re.I) else False
 2725         SpecifiedChainsAndLigandsInfo["ResidueTypesChain"][ChainID] = ResidueTypesChain
 2726 
 2727         # Process chain selections...
 2728         ChainSelections = True if len(OptionsInfo["ChainSelectionsInfo"]["Names"]) else False
 2729         SpecifiedChainsAndLigandsInfo["ChainSelections"][ChainID] = ChainSelections
 2730 
 2731         # Process surfaces for chain selections...
 2732         if re.match("^auto$", OptionsInfo["SelectionsChainSurface"], re.I):
 2733             SurfaceChainSelections = True if AminoAcidsPresent else False
 2734         else:
 2735             SurfaceChainSelections = True if re.match("^yes$", OptionsInfo["SelectionsChainSurface"], re.I) else False
 2736         SpecifiedChainsAndLigandsInfo["SurfaceChainSelections"][ChainID] = SurfaceChainSelections
 2737 
 2738         SpecifiedChainsAndLigandsInfo["ChainSelectionsSurfaces"][ChainID] = SurfaceChainSelections
 2739 
 2740         # Process selections, residue types and surfaces for pockets...
 2741         SpecifiedChainsAndLigandsInfo["PocketChainSelections"][ChainID] = {}
 2742         SpecifiedChainsAndLigandsInfo["PocketChainSelectionsSurfaces"][ChainID] = {}
 2743         SpecifiedChainsAndLigandsInfo["SurfacePocketChainSelections"][ChainID] = {}
 2744 
 2745         SpecifiedChainsAndLigandsInfo["PocketSurfaces"][ChainID] = {}
 2746         SpecifiedChainsAndLigandsInfo["SurfacePocket"][ChainID] = {}
 2747         SpecifiedChainsAndLigandsInfo["SurfacePocketElectrostatics"][ChainID] = {}
 2748 
 2749         SpecifiedChainsAndLigandsInfo["ResidueTypesPocket"][ChainID] = {}
 2750 
 2751         for LigandID in SpecifiedChainsAndLigandsInfo["LigandIDs"][ChainID]:
 2752             # Process pocket chain selections and surfaces...
 2753             PocketChainSelections = True if len(OptionsInfo["PocketChainSelectionsInfo"]["Names"]) else False
 2754             SpecifiedChainsAndLigandsInfo["PocketChainSelections"][ChainID][LigandID] = PocketChainSelections
 2755 
 2756             # Process surfaces for chain selections...
 2757             if re.match("^auto$", OptionsInfo["SelectionsPocketSurface"], re.I):
 2758                 PocketChainSelectionsSurface = True if AminoAcidsPresent else False
 2759             else:
 2760                 PocketChainSelectionsSurface = (
 2761                     True if re.match("^yes$", OptionsInfo["SelectionsPocketSurface"], re.I) else False
 2762                 )
 2763 
 2764             SpecifiedChainsAndLigandsInfo["PocketChainSelectionsSurfaces"][ChainID][LigandID] = (
 2765                 PocketChainSelectionsSurface
 2766             )
 2767 
 2768             SpecifiedChainsAndLigandsInfo["SurfacePocketChainSelections"][ChainID][LigandID] = (
 2769                 PocketChainSelectionsSurface
 2770             )
 2771 
 2772             # Process pocket surfaces...
 2773             if re.match("^auto$", OptionsInfo["PocketSurface"], re.I):
 2774                 PocketSurface = True if AminoAcidsPresent else False
 2775             else:
 2776                 PocketSurface = True if re.match("^yes$", OptionsInfo["PocketSurface"], re.I) else False
 2777             SpecifiedChainsAndLigandsInfo["SurfacePocket"][ChainID][LigandID] = PocketSurface
 2778 
 2779             if re.match("^auto$", OptionsInfo["PocketSurfaceElectrostatics"], re.I):
 2780                 PocketSurfaceElectrostatics = True if AminoAcidsPresent else False
 2781             else:
 2782                 PocketSurfaceElectrostatics = (
 2783                     True if re.match("^yes$", OptionsInfo["PocketSurfaceElectrostatics"], re.I) else False
 2784                 )
 2785             SpecifiedChainsAndLigandsInfo["SurfacePocketElectrostatics"][ChainID][LigandID] = (
 2786                 PocketSurfaceElectrostatics
 2787             )
 2788 
 2789             # Process pocket residue types...
 2790             SpecifiedChainsAndLigandsInfo["PocketSurfaces"][ChainID][LigandID] = PocketSurface
 2791 
 2792             if re.match("^auto$", OptionsInfo["PocketResidueTypes"], re.I):
 2793                 PocketResidueTypes = True if AminoAcidsPresent else False
 2794             else:
 2795                 PocketResidueTypes = True if re.match("^yes$", OptionsInfo["PocketResidueTypes"], re.I) else False
 2796             SpecifiedChainsAndLigandsInfo["ResidueTypesPocket"][ChainID][LigandID] = PocketResidueTypes
 2797 
 2798     # Delete loaded object...
 2799     pymol.cmd.delete(MolName)
 2800 
 2801 
 2802 def GetChainAloneResidueTypesStatus(FileIndex, ChainID):
 2803     """Get status of residue types for chain alone object."""
 2804 
 2805     Status = OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"][FileIndex]["ResidueTypesChain"][ChainID]
 2806 
 2807     return Status
 2808 
 2809 
 2810 def GetChainAloneBFactorStatus(FileIndex, ChainID):
 2811     """Get status of B factors for chain alone object."""
 2812 
 2813     Status = OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"][FileIndex]["BFactorChain"][ChainID]
 2814 
 2815     return Status
 2816 
 2817 
 2818 def GetChainAloneDisulfideBondsStatus(FileIndex, ChainID):
 2819     """Get status of disulfide bonds for chain alone object."""
 2820 
 2821     Status = OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"][FileIndex]["DisulfideBondsChain"][ChainID]
 2822 
 2823     return Status
 2824 
 2825 
 2826 def GetChainAloneSaltBridgesStatus(FileIndex, ChainID):
 2827     """Get status of salt bridges for chain alone object."""
 2828 
 2829     Status = OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"][FileIndex]["SaltBridgesChain"][ChainID]
 2830 
 2831     return Status
 2832 
 2833 
 2834 def GetChainAloneDockedPosesStatus(FileIndex, ChainID):
 2835     """Get status of docked for chain alone object."""
 2836 
 2837     Status = OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"][FileIndex]["DockedPoses"][ChainID]
 2838 
 2839     return Status
 2840 
 2841 
 2842 def GetTrajectoriesStatus(FileIndex):
 2843     """Get status of trajectories for a PDB object."""
 2844 
 2845     if OptionsInfo["TrajectoriesInfo"] is None:
 2846         return False
 2847 
 2848     Status = True if FileIndex in OptionsInfo["TrajectoriesInfo"]["PDBFileIndices"] else False
 2849 
 2850     return Status
 2851 
 2852 
 2853 def GetPocketResidueTypesStatus(FileIndex, ChainID, LigandID):
 2854     """Get status of residue types for a pocket."""
 2855 
 2856     return OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"][FileIndex]["ResidueTypesPocket"][ChainID][
 2857         LigandID
 2858     ]
 2859 
 2860 
 2861 def GetChainAloneContainsSurfacesStatus(FileIndex, ChainID):
 2862     """Get status of surfaces present in chain alone object."""
 2863 
 2864     return OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"][FileIndex]["ChainSurfaces"][ChainID]
 2865 
 2866 
 2867 def GetPocketContainsSelectionsStatus(FileIndex, ChainID, LigandID):
 2868     """Get status of selections present in a pocket."""
 2869 
 2870     return OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"][FileIndex]["PocketChainSelections"][ChainID][
 2871         LigandID
 2872     ]
 2873 
 2874 
 2875 def GetPocketContainsSurfaceStatus(FileIndex, ChainID, LigandID):
 2876     """Get status of surfaces present in a pocket."""
 2877 
 2878     return OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"][FileIndex]["PocketSurfaces"][ChainID][LigandID]
 2879 
 2880 
 2881 def GetChainAloneSurfaceChainStatus(FileIndex, ChainID):
 2882     """Get status of hydrophobic surfaces for chain alone object."""
 2883 
 2884     return OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"][FileIndex]["SurfaceChain"][ChainID]
 2885 
 2886 
 2887 def GetChainAloneSurfaceChainElectrostaticsStatus(FileIndex, ChainID):
 2888     """Get status of electrostatics surfaces for chain alone object."""
 2889 
 2890     return OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"][FileIndex]["SurfaceChainElectrostatics"][ChainID]
 2891 
 2892 
 2893 def GetPocketSelectionSurfaceChainStatus(FileIndex, ChainID, LigandID):
 2894     """Get status of surfaces for a pocket selection in a chain."""
 2895 
 2896     return OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"][FileIndex]["SurfacePocketChainSelections"][
 2897         ChainID
 2898     ][LigandID]
 2899 
 2900 
 2901 def GetPocketSurfaceChainStatus(FileIndex, ChainID, LigandID):
 2902     """Get status of hydrophobic surfaces for a pocket."""
 2903 
 2904     return OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"][FileIndex]["SurfacePocket"][ChainID][LigandID]
 2905 
 2906 
 2907 def GetPocketSurfaceChainElectrostaticsStatus(FileIndex, ChainID, LigandID):
 2908     """Get status of hydrophobic surfaces for a pocket."""
 2909 
 2910     return OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"][FileIndex]["SurfacePocketElectrostatics"][
 2911         ChainID
 2912     ][LigandID]
 2913 
 2914 
 2915 def GetChainAloneContainsSelectionsStatus(FileIndex, ChainID):
 2916     """Get status of selections present in chain alone object."""
 2917     return OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"][FileIndex]["ChainSelections"][ChainID]
 2918 
 2919 
 2920 def GetChainAloneContainsChainSelectionSurfacesStatus(FileIndex, ChainID):
 2921     """Get status of chain selections surfaces present in chain alone object."""
 2922     return OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"][FileIndex]["ChainSelectionsSurfaces"][ChainID]
 2923 
 2924 
 2925 def GetChainAloneSurfaceChainSelectionStatus(FileIndex, ChainID):
 2926     """Get status of hydrophobic surfaces for chain alone object."""
 2927     return OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"][FileIndex]["SurfaceChainSelections"][ChainID]
 2928 
 2929 
 2930 def CheckPresenceOfValidLigandIDs(ChainsAndLigandsInfo, SpecifiedChainsAndLigandsInfo):
 2931     """Check presence of valid ligand IDs."""
 2932 
 2933     MiscUtil.PrintInfo("\nSpecified chain IDs: %s" % (", ".join(SpecifiedChainsAndLigandsInfo["ChainIDs"])))
 2934 
 2935     for ChainID in SpecifiedChainsAndLigandsInfo["ChainIDs"]:
 2936         if len(SpecifiedChainsAndLigandsInfo["LigandIDs"][ChainID]):
 2937             MiscUtil.PrintInfo(
 2938                 "Chain ID: %s; Specified LigandIDs: %s"
 2939                 % (ChainID, ", ".join(SpecifiedChainsAndLigandsInfo["LigandIDs"][ChainID]))
 2940             )
 2941         else:
 2942             MiscUtil.PrintInfo("Chain IDs: %s; Specified LigandIDs: None" % (ChainID))
 2943             MiscUtil.PrintWarning(
 2944                 "No valid ligand IDs found for chain ID, %s. PyMOL groups and objects related to ligand and binding pockect won't be created."
 2945                 % (ChainID)
 2946             )
 2947 
 2948 
 2949 def RetrieveFirstChainID(FileIndex):
 2950     """Get first chain ID."""
 2951 
 2952     ChainsAndLigandsInfo = OptionsInfo["InfilesInfo"]["ChainsAndLigandsInfo"][FileIndex]
 2953 
 2954     FirstChainID = None
 2955     if len(ChainsAndLigandsInfo["ChainIDs"]):
 2956         FirstChainID = ChainsAndLigandsInfo["ChainIDs"][0]
 2957 
 2958     return FirstChainID
 2959 
 2960 
 2961 def ProcessDockedPoses():
 2962     """Process docked poses."""
 2963 
 2964     OptionsInfo["DockedPosesGroupName"] = Options["--dockedPosesGroupName"]
 2965     OptionsInfo["DockedPosesName"] = Options["--dockedPosesName"]
 2966 
 2967     DockedPosesInfo = ProcessDockedPosesOptionsInfo("--dockedPoses", OptionsInfo["DockedPoses"])
 2968     OptionsInfo["DockedPosesInfo"] = DockedPosesInfo
 2969 
 2970     ProcessDockedPosesInfoForInfiles()
 2971 
 2972     OptionsInfo["DockedPosesDistanceContactsCutoffs"] = Options["--dockedPosesDistanceContactsCutoffs"]
 2973     OptionsInfo["DockedPosesDistanceContactsColor"] = Options["--dockedPosesDistanceContactsColor"]
 2974 
 2975     DockedPosesDistanceContactsInfo = ProcessDockedPosesDistanceContactsOptionsInfo()
 2976     OptionsInfo["DockedPosesDistanceContactsInfo"] = DockedPosesDistanceContactsInfo
 2977 
 2978     # Setup distance conatcts status for dockes poses...
 2979     if DockedPosesInfo is not None:
 2980         DockedPosesInfo["DistanceContacts"] = False
 2981         if DockedPosesDistanceContactsInfo is not None:
 2982             if len(DockedPosesDistanceContactsInfo["ContactIDs"]):
 2983                 DockedPosesInfo["DistanceContacts"] = True
 2984 
 2985 
 2986 def ProcessDockedPosesInfoForInfiles():
 2987     """Process docked poses info for infiles."""
 2988 
 2989     DockedPosesInfo = OptionsInfo["DockedPosesInfo"]
 2990     for FileIndex in range(0, len(OptionsInfo["InfilesInfo"]["InfilesNames"])):
 2991         SpecifiedChainsAndLigandsInfo = OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"][FileIndex]
 2992         ProcessDockedPosesInfoForInfileAndChains(FileIndex, SpecifiedChainsAndLigandsInfo, DockedPosesInfo)
 2993 
 2994 
 2995 def ProcessDockedPosesInfoForInfileAndChains(FileIndex, SpecifiedChainsAndLigandsInfo, DockedPosesInfo):
 2996     """Process docked poses info for a specific infile."""
 2997 
 2998     SpecifiedChainsAndLigandsInfo["DockedPoses"] = {}
 2999     SpecifiedChainsAndLigandsInfo["DockedPosesInputFiles"] = {}
 3000 
 3001     for ChainID in SpecifiedChainsAndLigandsInfo["ChainIDs"]:
 3002         DockedPoses = False
 3003         if DockedPosesInfo is not None:
 3004             if FileIndex in DockedPosesInfo["PDBFileIndices"]:
 3005                 if ChainID == DockedPosesInfo["ChainID"][FileIndex]:
 3006                     DockedPoses = True
 3007 
 3008         SpecifiedChainsAndLigandsInfo["DockedPoses"][ChainID] = DockedPoses
 3009 
 3010         SpecifiedChainsAndLigandsInfo["DockedPosesInputFiles"][ChainID] = []
 3011         if DockedPoses:
 3012             SpecifiedChainsAndLigandsInfo["DockedPosesInputFiles"][ChainID].extend(
 3013                 DockedPosesInfo["InputFiles"][FileIndex]
 3014             )
 3015 
 3016 
 3017 def ProcessDockedPosesOptionsInfo(DockedPosesOptionName, DockedPosesOptionValue):
 3018     """Process docked poses options info."""
 3019 
 3020     DockedPoses = DockedPosesOptionValue
 3021     if re.match("^none$", DockedPoses, re.I):
 3022         return None
 3023 
 3024     MiscUtil.PrintInfo("\nProcessing docked poses...")
 3025 
 3026     # Initialize docked poses info...
 3027     DockedPosesInfo = {}
 3028     DockedPosesInfo["PDBFileIndices"] = []
 3029 
 3030     DockedPosesInfo["PDBFile"] = {}
 3031     DockedPosesInfo["ChainID"] = {}
 3032     DockedPosesInfo["LigandID"] = {}
 3033     DockedPosesInfo["UseInputFileAsLigandID"] = {}
 3034     DockedPosesInfo["InputFiles"] = {}
 3035     DockedPosesInfo["InputFilesRoots"] = {}
 3036     DockedPosesInfo["InputFilesIDs"] = {}
 3037 
 3038     # Parse docked poses values...
 3039     DockedPosesWords = DockedPoses.split(",")
 3040     if len(DockedPosesWords) % 4:
 3041         MiscUtil.PrintError(
 3042             'The number of comma delimited docked poses values, %d, specified using "%s" option must be a multple of 4.'
 3043             % (len(DockedPosesWords), DockedPosesOptionName)
 3044         )
 3045 
 3046     # Validate and process specified values...
 3047     for Index in range(0, len(DockedPosesWords), 4):
 3048         PDBFile = DockedPosesWords[Index].strip()
 3049         ChainID = DockedPosesWords[Index + 1].strip()
 3050         LigandID = DockedPosesWords[Index + 2].strip()
 3051         InputFiles = DockedPosesWords[Index + 3].strip()
 3052 
 3053         InputFiles = re.sub("[ ]+", " ", InputFiles)
 3054         InputFiles = InputFiles.split(" ")
 3055 
 3056         # Process PDB file...
 3057         MiscUtil.ValidateOptionFilePath("--dockedPoses", PDBFile)
 3058 
 3059         PDBFileIndex = None
 3060         for FileIndex in range(0, len(OptionsInfo["InfilesInfo"]["InfilesNames"])):
 3061             PDBInfile = OptionsInfo["InfilesInfo"]["InfilesNames"][FileIndex]
 3062             if PDBFile == PDBInfile:
 3063                 PDBFileIndex = FileIndex
 3064                 break
 3065         if PDBFileIndex is None:
 3066             MiscUtil.PrintError(
 3067                 'The PDB file specified, %s, using option "--dockedPoses" is not valid. It must be specified as an input file.'
 3068                 % (PDBFile)
 3069             )
 3070 
 3071         if PDBFileIndex in DockedPosesInfo["PDBFileIndices"]:
 3072             MiscUtil.PrintError(
 3073                 'The PDB file specified, %s, using option "--dockedPoses" is not valid. It is a duplicate and has already been specified.'
 3074                 % (PDBFile)
 3075             )
 3076 
 3077         # Process chain ID...
 3078         SpecifiedChainsAndLigandsInfo = OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"][PDBFileIndex]
 3079         if ChainID not in SpecifiedChainsAndLigandsInfo["ChainIDs"]:
 3080             MiscUtil.PrintError(
 3081                 'The chain ID, %s, specified for PDB file, %s, using option "--dockedPoses" is not valid. It must be present in valid chain IDs corresponding to option "-c, --chainIDs" .'
 3082                 % (ChainID, PDBFile)
 3083             )
 3084 
 3085         # Process ligand ID...
 3086         UseInputFileAsLigandID = True if re.match("^UseInputFile$", LigandID, re.I) else False
 3087         if not UseInputFileAsLigandID:
 3088             if LigandID not in SpecifiedChainsAndLigandsInfo["LigandIDs"][ChainID]:
 3089                 MiscUtil.PrintError(
 3090                     'The ligand ID, %s, specified for chain ID, %s, and PDB file, %s, using option "--dockedPoses" is not valid. It must be present in valid ligand IDs corresponding to option "-l, --ligandIDs" .'
 3091                     % (LigandID, ChainID, PDBFile)
 3092                 )
 3093 
 3094         # Process input files...
 3095         InputFilesRoots = []
 3096         InputFilesIDs = []
 3097         for InputFile in InputFiles:
 3098             MiscUtil.ValidateOptionFilePath("--dockedPoses", InputFile)
 3099             MiscUtil.ValidateOptionFileExt("--dockedPoses", InputFile, "sdf sd")
 3100 
 3101             FileDir, FileName, FileExt = MiscUtil.ParseFileName(InputFile)
 3102             InputFileRoot = FileName
 3103 
 3104             # Clean up input file names for generating PyMOL object names...
 3105             InputFileID = re.sub("[^a-zA-Z0-9]", "_", FileName)
 3106 
 3107             if InputFileRoot in InputFilesRoots:
 3108                 MiscUtil.PrintError(
 3109                     'The input file specified, %s, using option "--dockedPoses" is not valid. It is a duplicate and has already been specified for a PDB file.'
 3110                     % (InputFile)
 3111                 )
 3112 
 3113             InputFilesRoots.append(InputFileRoot)
 3114             InputFilesIDs.append(InputFileID)
 3115 
 3116         # Track values...
 3117         DockedPosesInfo["PDBFileIndices"].append(PDBFileIndex)
 3118 
 3119         DockedPosesInfo["PDBFile"][PDBFileIndex] = PDBFile
 3120         DockedPosesInfo["ChainID"][PDBFileIndex] = ChainID
 3121 
 3122         DockedPosesInfo["LigandID"][PDBFileIndex] = LigandID
 3123         DockedPosesInfo["UseInputFileAsLigandID"][PDBFileIndex] = UseInputFileAsLigandID
 3124 
 3125         DockedPosesInfo["InputFiles"][PDBFileIndex] = InputFiles
 3126         DockedPosesInfo["InputFilesRoots"][PDBFileIndex] = InputFilesRoots
 3127         DockedPosesInfo["InputFilesIDs"][PDBFileIndex] = InputFilesIDs
 3128 
 3129     return DockedPosesInfo
 3130 
 3131 
 3132 def ProcessDockedPosesDistanceContactsOptionsInfo():
 3133     """Process dockes poses distance contacts info."""
 3134 
 3135     DistanceContactsCutoffs = OptionsInfo["DockedPosesDistanceContactsCutoffs"]
 3136     if re.match("^none$", DistanceContactsCutoffs):
 3137         return None
 3138 
 3139     DistanceContactsInfo = {}
 3140     DistanceContactsInfo["ContactIDs"] = []
 3141     DistanceContactsInfo["ContactCutoff"] = {}
 3142 
 3143     DistanceContactsCutoffs = re.sub(" ", "", DistanceContactsCutoffs)
 3144     if not DistanceContactsCutoffs:
 3145         MiscUtil.PrintError('No value specified using "--dockedPosesDistanceContactsCutoffs" option.')
 3146 
 3147     ContactCutoffValues = DistanceContactsCutoffs.split(",")
 3148     for Index, ContactCutoff in enumerate(ContactCutoffValues):
 3149         MiscUtil.ValidateOptionFloatValue(
 3150             "--dockedPosesDistanceContactsCutoffs", ContactCutoff, {">": 0.0, "<=": OptionsInfo["PocketDistanceCutoff"]}
 3151         )
 3152         ContactCutoff = float(ContactCutoff.strip())
 3153 
 3154         ContactID = "Contact%s_At_%s" % ((Index + 1), ContactCutoff)
 3155         ContactID = re.sub(r"\.", "pt", ContactID)
 3156 
 3157         DistanceContactsInfo["ContactIDs"].append(ContactID)
 3158         DistanceContactsInfo["ContactCutoff"][ContactID] = ContactCutoff
 3159 
 3160     return DistanceContactsInfo
 3161 
 3162 
 3163 def ProcessTrajectories():
 3164     """Process trajectories."""
 3165 
 3166     TrajectoriesInfo = ProcessTrajectoriesOptionsInfo("--Trajectories", OptionsInfo["Trajectories"])
 3167     OptionsInfo["TrajectoriesInfo"] = TrajectoriesInfo
 3168 
 3169 
 3170 def ProcessTrajectoriesOptionsInfo(TrajectoriesOptionName, TrajectoriesOptionValue):
 3171     """Process trajectories options info."""
 3172 
 3173     Trajectories = TrajectoriesOptionValue
 3174     if re.match("^none$", Trajectories, re.I):
 3175         return None
 3176 
 3177     MiscUtil.PrintInfo("\nProcessing trajectories...")
 3178 
 3179     # Initialize trajectories info...
 3180     TrajectoriesInfo = {}
 3181     TrajectoriesInfo["PDBFileIndices"] = []
 3182 
 3183     TrajectoriesInfo["PDBFile"] = {}
 3184     TrajectoriesInfo["TrajFiles"] = {}
 3185     TrajectoriesInfo["TrajFilesRoots"] = {}
 3186     TrajectoriesInfo["TrajFilesIDs"] = {}
 3187 
 3188     # Parse trajectories values...
 3189     TrajectoriesWords = Trajectories.split(",")
 3190     if len(TrajectoriesWords) % 2:
 3191         MiscUtil.PrintError(
 3192             'The number of comma delimited trajectories values, %d, specified using "%s" option must be a multple of 2.'
 3193             % (len(TrajectoriesWords), TrajectoriesOptionName)
 3194         )
 3195 
 3196     # Validate and process specified values...
 3197     for Index in range(0, len(TrajectoriesWords), 2):
 3198         PDBFile = TrajectoriesWords[Index].strip()
 3199         TrajFiles = TrajectoriesWords[Index + 1].strip()
 3200 
 3201         TrajFiles = re.sub("[ ]+", " ", TrajFiles)
 3202         TrajFiles = TrajFiles.split(" ")
 3203 
 3204         # Process PDB file...
 3205         MiscUtil.ValidateOptionFilePath(TrajectoriesOptionName, PDBFile)
 3206 
 3207         PDBFileIndex = None
 3208         for FileIndex in range(0, len(OptionsInfo["InfilesInfo"]["InfilesNames"])):
 3209             PDBInfile = OptionsInfo["InfilesInfo"]["InfilesNames"][FileIndex]
 3210             if PDBFile == PDBInfile:
 3211                 PDBFileIndex = FileIndex
 3212                 break
 3213         if PDBFileIndex is None:
 3214             MiscUtil.PrintError(
 3215                 'The topology PDB file specified, %s, using option "%s" is not valid. It must be specified as an input file.'
 3216                 % (PDBFile, TrajectoriesOptionName)
 3217             )
 3218 
 3219         if PDBFileIndex in TrajectoriesInfo["PDBFileIndices"]:
 3220             MiscUtil.PrintError(
 3221                 'The topology PDB file specified, %s, using option "%s" is not valid. It is a duplicate and has already been specified.'
 3222                 % (PDBFile, TrajectoriesOptionName)
 3223             )
 3224 
 3225         # Process trajectory files...
 3226         TrajFilesRoots = []
 3227         TrajFilesIDs = []
 3228         for TrajFile in TrajFiles:
 3229             MiscUtil.ValidateOptionFilePath(TrajectoriesOptionName, TrajFile)
 3230 
 3231             FileDir, FileName, FileExt = MiscUtil.ParseFileName(TrajFile)
 3232             TrajFileRoot = FileName
 3233 
 3234             # Clean up trajectory file names for generating PyMOL object names...
 3235             TrajFileID = re.sub("[^a-zA-Z0-9]", "_", FileName)
 3236 
 3237             if TrajFileRoot in TrajFilesRoots:
 3238                 MiscUtil.PrintError(
 3239                     'The trajectory file specified, %s, using option "%s" is not valid. It is a duplicate and has already been specified for a PDB file.'
 3240                     % (TrajFile, TrajectoriesOptionName)
 3241                 )
 3242 
 3243             TrajFilesRoots.append(TrajFileRoot)
 3244             TrajFilesIDs.append(TrajFileID)
 3245 
 3246         # Track values...
 3247         TrajectoriesInfo["PDBFileIndices"].append(PDBFileIndex)
 3248 
 3249         TrajectoriesInfo["PDBFile"][PDBFileIndex] = PDBFile
 3250 
 3251         TrajectoriesInfo["TrajFiles"][PDBFileIndex] = TrajFiles
 3252         TrajectoriesInfo["TrajFilesRoots"][PDBFileIndex] = TrajFilesRoots
 3253         TrajectoriesInfo["TrajFilesIDs"][PDBFileIndex] = TrajFilesIDs
 3254 
 3255     return TrajectoriesInfo
 3256 
 3257 
 3258 def ProcessResidueTypes():
 3259     """Process residue types."""
 3260 
 3261     ResidueTypesNamesInfo, ResidueTypesParamsInfo = PyMOLUtil.ProcessResidueTypesOptionsInfo(
 3262         "-r, --residueTypes", OptionsInfo["ResidueTypes"]
 3263     )
 3264     OptionsInfo["ResidueTypesNames"] = ResidueTypesNamesInfo
 3265     OptionsInfo["ResidueTypesParams"] = ResidueTypesParamsInfo
 3266 
 3267 
 3268 def ProcessSaltBridgesChainResidues():
 3269     """Process salt bridges chain residues."""
 3270 
 3271     SaltBridgesChainResiduesInfo = PyMOLUtil.ProcessSaltBridgesChainResiduesOptionsInfo(
 3272         "--saltBridgesChainResidues", OptionsInfo["SaltBridgesChainResidues"]
 3273     )
 3274     OptionsInfo["SaltBridgesChainResiduesInfo"] = SaltBridgesChainResiduesInfo
 3275 
 3276 
 3277 def ProcessSurfaceAtomTypesColors():
 3278     """Process surface atom types colors."""
 3279 
 3280     AtomTypesColorNamesInfo = PyMOLUtil.ProcessSurfaceAtomTypesColorsOptionsInfo(
 3281         "--surfaceAtomTypesColors", OptionsInfo["SurfaceAtomTypesColors"]
 3282     )
 3283     OptionsInfo["AtomTypesColorNames"] = AtomTypesColorNamesInfo
 3284 
 3285 
 3286 def ProcessPockectChainSelections():
 3287     """Process custom selections for pocket chains."""
 3288 
 3289     PocketChainSelectionsInfo = PyMOLUtil.ProcessChainSelectionsOptionsInfo(
 3290         "--selectionsPocket", OptionsInfo["SelectionsPocket"]
 3291     )
 3292     OptionsInfo["PocketChainSelectionsInfo"] = PocketChainSelectionsInfo
 3293 
 3294 
 3295 def ProcessChainSelections():
 3296     """Process custom selections for chains."""
 3297 
 3298     ChainSelectionsInfo = PyMOLUtil.ProcessChainSelectionsOptionsInfo(
 3299         "--selectionsChain", OptionsInfo["SelectionsChain"]
 3300     )
 3301     OptionsInfo["ChainSelectionsInfo"] = ChainSelectionsInfo
 3302 
 3303 
 3304 def ProcessOptions():
 3305     """Process and validate command line arguments and options."""
 3306 
 3307     MiscUtil.PrintInfo("Processing options...")
 3308 
 3309     # Validate options...
 3310     ValidateOptions()
 3311 
 3312     OptionsInfo["Align"] = True if re.match("^Yes$", Options["--align"], re.I) else False
 3313     OptionsInfo["AlignMethod"] = Options["--alignMethod"].lower()
 3314     OptionsInfo["AlignMode"] = Options["--alignMode"]
 3315 
 3316     OptionsInfo["AllowEmptyObjects"] = True if re.match("^Yes$", Options["--allowEmptyObjects"], re.I) else False
 3317 
 3318     OptionsInfo["BFactorChain"] = Options["--BFactorChain"]
 3319     OptionsInfo["BFactorColorPalette"] = Options["--BFactorColorPalette"]
 3320 
 3321     OptionsInfo["Infiles"] = Options["--infiles"]
 3322     OptionsInfo["InfilesNames"] = Options["--infileNames"]
 3323 
 3324     OptionsInfo["AlignRefFile"] = Options["--alignRefFile"]
 3325     if re.match("^FirstInputFile$", Options["--alignRefFile"], re.I):
 3326         OptionsInfo["RefFileName"] = OptionsInfo["InfilesNames"][0]
 3327     else:
 3328         OptionsInfo["RefFileName"] = Options["--alignRefFile"]
 3329 
 3330     OptionsInfo["IgnoreHydrogens"] = True if re.match("^Yes$", Options["--ignoreHydrogens"], re.I) else False
 3331 
 3332     OptionsInfo["Overwrite"] = Options["--overwrite"]
 3333     OptionsInfo["PMLOut"] = True if re.match("^Yes$", Options["--PMLOut"], re.I) else False
 3334 
 3335     OptionsInfo["Outfile"] = Options["--outfile"]
 3336     FileDir, FileName, FileExt = MiscUtil.ParseFileName(OptionsInfo["Outfile"])
 3337     OptionsInfo["PSEOut"] = False
 3338     if re.match("^pml$", FileExt, re.I):
 3339         OptionsInfo["PMLOutfile"] = OptionsInfo["Outfile"]
 3340         OptionsInfo["PMEOutfile"] = re.sub(".pml$", ".pme", OptionsInfo["Outfile"])
 3341     elif re.match("^pse$", FileExt, re.I):
 3342         OptionsInfo["PSEOut"] = True
 3343         OptionsInfo["PSEOutfile"] = OptionsInfo["Outfile"]
 3344         OptionsInfo["PMLOutfile"] = re.sub(".pse$", ".pml", OptionsInfo["Outfile"])
 3345         if os.path.exists(OptionsInfo["PMLOutfile"]) and (not OptionsInfo["Overwrite"]):
 3346             MiscUtil.PrintError(
 3347                 'The intermediate output file to be generated, %s, already exist. Use option "--ov" or "--overwrite" and try again.'
 3348                 % OptionsInfo["PMLOutfile"]
 3349             )
 3350 
 3351     OptionsInfo["DisulfideBondsChain"] = Options["--disulfideBondsChain"]
 3352 
 3353     OptionsInfo["LabelFontID"] = int(Options["--labelFontID"])
 3354 
 3355     OptionsInfo["PocketContactsLigandColor"] = Options["--pocketContactsLigandColor"]
 3356     OptionsInfo["PocketContactsLigandHydrophobicColor"] = Options["--pocketContactsLigandHydrophobicColor"]
 3357     OptionsInfo["PocketContactsLigandPiPiColor"] = Options["--pocketContactsLigandPiPiColor"]
 3358     OptionsInfo["PocketContactsLigandPiCationColor"] = Options["--pocketContactsLigandPiCationColor"]
 3359     OptionsInfo["PocketContactsLigandHalogenColor"] = Options["--pocketContactsLigandHalogenColor"]
 3360 
 3361     OptionsInfo["PocketContactsSolventColor"] = Options["--pocketContactsSolventColor"]
 3362 
 3363     OptionsInfo["PocketContactsInorganicColor"] = Options["--pocketContactsInorganicColor"]
 3364     OptionsInfo["PocketContactsInorganicPiCationColor"] = Options["--pocketContactsInorganicPiCationColor"]
 3365 
 3366     OptionsInfo["PocketContactsCutoff"] = float(Options["--pocketContactsCutoff"])
 3367     OptionsInfo["PocketDistanceCutoff"] = float(Options["--pocketDistanceCutoff"])
 3368 
 3369     OptionsInfo["PocketLabelColor"] = Options["--pocketLabelColor"]
 3370 
 3371     OptionsInfo["PocketResidueTypes"] = Options["--pocketResidueTypes"]
 3372     OptionsInfo["PocketSurface"] = Options["--pocketSurface"]
 3373     OptionsInfo["PocketSurfaceElectrostatics"] = Options["--pocketSurfaceElectrostatics"]
 3374 
 3375     OptionsInfo["ResidueTypesChain"] = Options["--residueTypesChain"]
 3376     OptionsInfo["ResidueTypes"] = Options["--residueTypes"]
 3377     ProcessResidueTypes()
 3378 
 3379     OptionsInfo["SaltBridgesChain"] = Options["--saltBridgesChain"]
 3380     OptionsInfo["SaltBridgesChainContactsColor"] = Options["--saltBridgesChainContactsColor"]
 3381     OptionsInfo["SaltBridgesChainCutoff"] = float(Options["--saltBridgesChainCutoff"])
 3382     OptionsInfo["SaltBridgesChainResidues"] = Options["--saltBridgesChainResidues"]
 3383     ProcessSaltBridgesChainResidues()
 3384 
 3385     OptionsInfo["SelectionsChain"] = Options["--selectionsChain"]
 3386     OptionsInfo["SelectionsChainSurface"] = Options["--selectionsChainSurface"]
 3387     OptionsInfo["SelectionsChainStyle"] = Options["--selectionsChainStyle"]
 3388     ProcessChainSelections()
 3389 
 3390     OptionsInfo["SelectionsPocket"] = Options["--selectionsPocket"]
 3391     OptionsInfo["SelectionsPocketSurface"] = Options["--selectionsPocketSurface"]
 3392     OptionsInfo["SelectionsPocketStyle"] = Options["--selectionsPocketStyle"]
 3393     ProcessPockectChainSelections()
 3394 
 3395     OptionsInfo["SurfaceChain"] = Options["--surfaceChain"]
 3396     OptionsInfo["SurfaceChainElectrostatics"] = Options["--surfaceChainElectrostatics"]
 3397 
 3398     OptionsInfo["SurfaceChainComplex"] = True if re.match("^Yes$", Options["--surfaceChainComplex"], re.I) else False
 3399     OptionsInfo["SurfaceComplex"] = True if re.match("^Yes$", Options["--surfaceComplex"], re.I) else False
 3400 
 3401     OptionsInfo["SurfaceColor"] = Options["--surfaceColor"]
 3402     OptionsInfo["SurfaceColorPalette"] = Options["--surfaceColorPalette"]
 3403     OptionsInfo["SurfaceAtomTypesColors"] = Options["--surfaceAtomTypesColors"]
 3404     ProcessSurfaceAtomTypesColors()
 3405 
 3406     OptionsInfo["SurfaceTransparency"] = float(Options["--surfaceTransparency"])
 3407 
 3408     RetrieveInfilesInfo()
 3409     RetrieveRefFileInfo()
 3410 
 3411     OptionsInfo["ChainIDs"] = Options["--chainIDs"]
 3412     OptionsInfo["LigandIDs"] = Options["--ligandIDs"]
 3413 
 3414     ProcessChainAndLigandIDs()
 3415 
 3416     OptionsInfo["DockedPoses"] = Options["--dockedPoses"]
 3417     ProcessDockedPoses()
 3418 
 3419     OptionsInfo["Trajectories"] = Options["--trajectories"]
 3420     ProcessTrajectories()
 3421 
 3422 
 3423 def RetrieveOptions():
 3424     """Retrieve command line arguments and options."""
 3425 
 3426     # Get options...
 3427     global Options
 3428     Options = docopt(_docoptUsage_)
 3429 
 3430     # Set current working directory to the specified directory...
 3431     WorkingDir = Options["--workingdir"]
 3432     if WorkingDir:
 3433         os.chdir(WorkingDir)
 3434 
 3435     # Handle examples option...
 3436     if "--examples" in Options and Options["--examples"]:
 3437         MiscUtil.PrintInfo(MiscUtil.GetExamplesTextFromDocOptText(_docoptUsage_))
 3438         sys.exit(0)
 3439 
 3440 
 3441 def ValidateOptions():
 3442     """Validate option values."""
 3443 
 3444     MiscUtil.ValidateOptionTextValue("--align", Options["--align"], "yes no")
 3445     MiscUtil.ValidateOptionTextValue("--alignMethod", Options["--alignMethod"], "align cealign super")
 3446     MiscUtil.ValidateOptionTextValue("--alignMode", Options["--alignMode"], "FirstChain Complex")
 3447 
 3448     MiscUtil.ValidateOptionTextValue("--allowEmptyObjects", Options["--allowEmptyObjects"], "yes no")
 3449 
 3450     MiscUtil.ValidateOptionTextValue("--BFactorChain", Options["--BFactorChain"], "yes no")
 3451 
 3452     # Expand infiles to handle presence of multiple input files...
 3453     InfileNames = MiscUtil.ExpandFileNames(Options["--infiles"], ",")
 3454     if not len(InfileNames):
 3455         MiscUtil.PrintError('No input files specified for "-i, --infiles" option')
 3456 
 3457     # Validate file extensions...
 3458     for Infile in InfileNames:
 3459         MiscUtil.ValidateOptionFilePath("-i, --infiles", Infile)
 3460         MiscUtil.ValidateOptionFileExt("-i, --infiles", Infile, "pdb cif")
 3461         MiscUtil.ValidateOptionsDistinctFileNames("-i, --infiles", Infile, "-o, --outfile", Options["--outfile"])
 3462     Options["--infileNames"] = InfileNames
 3463 
 3464     MiscUtil.ValidateOptionFileExt("-o, --outfile", Options["--outfile"], "pml pse")
 3465     MiscUtil.ValidateOptionsOutputFileOverwrite(
 3466         "-o, --outfile", Options["--outfile"], "--overwrite", Options["--overwrite"]
 3467     )
 3468 
 3469     if re.match("^yes$", Options["--align"], re.I):
 3470         if not re.match("^FirstInputFile$", Options["--alignRefFile"], re.I):
 3471             AlignRefFile = Options["--alignRefFile"]
 3472             MiscUtil.ValidateOptionFilePath("--alignRefFile", AlignRefFile)
 3473             MiscUtil.ValidateOptionFileExt("--alignRefFile", AlignRefFile, "pdb cif")
 3474             MiscUtil.ValidateOptionsDistinctFileNames(
 3475                 "--AlignRefFile", AlignRefFile, "-o, --outfile", Options["--outfile"]
 3476             )
 3477 
 3478     MiscUtil.ValidateOptionTextValue("--disulfideBondsChain", Options["--disulfideBondsChain"], "yes no auto")
 3479 
 3480     MiscUtil.ValidateOptionTextValue("--ignoreHydrogens", Options["--ignoreHydrogens"], "yes no")
 3481 
 3482     MiscUtil.ValidateOptionTextValue("--PMLOut", Options["--PMLOut"], "yes no")
 3483     MiscUtil.ValidateOptionIntegerValue("--labelFontID", Options["--labelFontID"], {})
 3484 
 3485     MiscUtil.ValidateOptionFloatValue("--pocketContactsCutoff", Options["--pocketContactsCutoff"], {">": 0.0})
 3486     MiscUtil.ValidateOptionFloatValue("--pocketDistanceCutoff", Options["--pocketDistanceCutoff"], {">": 0.0})
 3487     if float(Options["--pocketContactsCutoff"]) > float(Options["--pocketDistanceCutoff"]):
 3488         MiscUtil.PrintError(
 3489             'The value, %s, specified using option "--pocketContactsCutoff" must be less than value, %s, specified using "-pocketDistanceCutoff" option.'
 3490             % (Options["--pocketContactsCutoff"], Options["--pocketDistanceCutoff"])
 3491         )
 3492 
 3493     MiscUtil.ValidateOptionTextValue("--pocketResidueTypes", Options["--pocketResidueTypes"], "yes no auto")
 3494     MiscUtil.ValidateOptionTextValue("--pocketSurface", Options["--pocketSurface"], "yes no auto")
 3495     MiscUtil.ValidateOptionTextValue(
 3496         "--pocketSurfaceElectrostatics", Options["--pocketSurfaceElectrostatics"], "yes no auto"
 3497     )
 3498 
 3499     MiscUtil.ValidateOptionTextValue("--residueTypesChain", Options["--residueTypesChain"], "yes no auto")
 3500 
 3501     MiscUtil.ValidateOptionTextValue("--saltBridgesChain", Options["--saltBridgesChain"], "yes no auto")
 3502     MiscUtil.ValidateOptionFloatValue("--saltBridgesChainCutoff", Options["--saltBridgesChainCutoff"], {">": 0.0})
 3503 
 3504     MiscUtil.ValidateOptionTextValue("--selectionsChainSurface", Options["--selectionsChainSurface"], "yes no auto")
 3505     MiscUtil.ValidateOptionTextValue("--selectionsPocketSurface", Options["--selectionsPocketSurface"], "yes no auto")
 3506 
 3507     MiscUtil.ValidateOptionTextValue("--surfaceComplex", Options["--surfaceComplex"], "yes no")
 3508     MiscUtil.ValidateOptionTextValue("--surfaceChainComplex", Options["--surfaceChainComplex"], "yes no")
 3509     MiscUtil.ValidateOptionTextValue("--surfaceChain", Options["--surfaceChain"], "yes no auto")
 3510     MiscUtil.ValidateOptionTextValue(
 3511         "--surfaceChainElectrostatics", Options["--surfaceChainElectrostatics"], "yes no auto"
 3512     )
 3513 
 3514     MiscUtil.ValidateOptionTextValue(
 3515         "--surfaceColorPalette", Options["--surfaceColorPalette"], "RedToWhite WhiteToGreen"
 3516     )
 3517     MiscUtil.ValidateOptionFloatValue("--surfaceTransparency", Options["--surfaceTransparency"], {">=": 0.0, "<=": 1.0})
 3518 
 3519 
 3520 # Setup a usage string for docopt...
 3521 _docoptUsage_ = """
 3522 PyMOLVisualizeMacromolecules.py - Visualize macromolecules
 3523 
 3524 Usage:
 3525     PyMOLVisualizeMacromolecules.py [--align <yes or no>] [--alignMethod <align, cealign, super>]
 3526                                     [--alignMode <FirstChain or Complex>] [--alignRefFile <filename>]
 3527                                     [--allowEmptyObjects <yes or no>] [--BFactorChain <yes or no>] [--BFactorColorPalette <text>]
 3528                                     [--chainIDs <First, All or ID1,ID2...>] [--disulfideBondsChain <yes or no>]
 3529                                     [--dockedPoses <PDBFile,ChainID,LigandID,InputFiles,...>] [--dockedPosesDistanceContactsCutoffs <number1,number2...>]
 3530                                     [--dockedPosesDistanceContactsColor <text>] [--dockedPosesGroupName <text>]
 3531                                     [--dockedPosesName <text>] [--ignoreHydrogens <yes or no>] [--ligandIDs <Largest, All or ID1,ID2...>]
 3532                                     [--labelFontID <number>] [--PMLOut <yes or no>] [--pocketContactsInorganicColor <text>]
 3533                                     [--pocketContactsInorganicPiCationColor <text>] [--pocketContactsLigandColor <text>]
 3534                                     [--pocketContactsLigandHydrophobicColor <text>] [--pocketContactsLigandHalogenColor <text>]
 3535                                     [--pocketContactsLigandPiCationColor <text>] [--pocketContactsLigandPiPiColor <text>]
 3536                                     [--pocketContactsSolventColor <text>] [--pocketContactsCutoff <number>]
 3537                                     [--pocketDistanceCutoff <number>] [--pocketLabelColor <text>] [--pocketResidueTypes <yes or no>]
 3538                                     [--pocketSurface <yes or no>] [--pocketSurfaceElectrostatics <yes or no>]
 3539                                     [--residueTypes <Type,Color,ResNames,...>] [--residueTypesChain <yes or no>]
 3540                                     [--saltBridgesChain <yes or no>] [--saltBridgesChainContactsColor <text>]
 3541                                     [--saltBridgesChainCutoff <number>] [--saltBridgesChainResidues <Type, ResNames,...>]
 3542                                     [--selectionsChain <ObjectName,SelectionSpec,...>] [--selectionsChainSurface <yes or no>]
 3543                                     [--selectionsChainStyle <DisplayStyle>] [--selectionsPocket <ObjectName,SelectionSpec,...>]
 3544                                     [--selectionsPocketSurface <yes or no>] [--selectionsPocketStyle <DisplayStyle>]
 3545                                     [--surfaceChain <yes or no>] [--surfaceChainElectrostatics <yes or no>]
 3546                                     [--surfaceChainComplex <yes or no>] [--surfaceComplex <yes or no>]
 3547                                     [--surfaceColor <ColorName>] [--surfaceColorPalette <RedToWhite or WhiteToGreen>]
 3548                                     [--surfaceAtomTypesColors <ColorType,ColorSpec,...>]
 3549                                     [--surfaceTransparency <number>] [--trajectories <PDBToplogyFile,TrajFiles,...> ]
 3550                                     [--overwrite] [-w <dir>] -i <infile1,infile2,infile3...> -o <outfile>
 3551     PyMOLVisualizeMacromolecules.py -h | --help | -e | --examples
 3552 
 3553 Description:
 3554     Generate PyMOL visualization files for viewing surfaces, chains, ligands, ligand
 3555     binding pockets, and interactions between ligands and binding pockets in
 3556     macromolecules including proteins and nucleic acids.
 3557 
 3558     The supported input file format are: PDB (.pdb), CIF (.cif)
 3559 
 3560     The supported output file formats are: PyMOL script file (.pml), PyMOL session
 3561     file (.pse)
 3562 
 3563     A variety of PyMOL groups and objects may be  created for visualization of
 3564     macromolecules. These groups and objects correspond to complexes, surfaces,
 3565     chains, ligands, inorganics, ligand binding pockets, pocket, polar interactions,
 3566     and pocket hydrophobic surfaces. A complete hierarchy of all possible PyMOL
 3567     groups and objects is shown below:
 3568     
 3569         <PDBFileRoot>
 3570             .Complex
 3571                 .Complex
 3572                 .Surface
 3573             .Trajectories
 3574                 .Topology
 3575                 .<TrajFileID>
 3576                     .Trajectory
 3577                 .<TrajFileID>
 3578                     ... ... ...
 3579                 .<TrajFileID>
 3580                     ... ... ...
 3581             .Chain<ID>
 3582                 .Complex
 3583                     .Complex
 3584                     .Surface
 3585                 .Chain
 3586                     .Chain
 3587                     .BFactor
 3588                         .Putty
 3589                         .Cartoon
 3590                     .Selections
 3591                         .<Name>
 3592                             .Selection
 3593                             .Surface
 3594                                 .Surface
 3595                                 .Hydrophobicity
 3596                                 .Hydrophobicity_Charge
 3597                         .<Name>
 3598                             ... ... ..
 3599                     .Residues
 3600                         .Aromatic
 3601                             .Residues
 3602                             .Surface
 3603                         .Hydrophobic
 3604                             .Residues
 3605                             .Surface
 3606                         .Polar
 3607                             .Residues
 3608                             .Surface
 3609                         .Positively_Charged
 3610                             .Residues
 3611                             .Surface
 3612                         .Negatively_Charged
 3613                             .Residues
 3614                             .Surface
 3615                         .Other
 3616                             .Residues
 3617                             .Surface
 3618                     .Surface
 3619                         .Surface
 3620                         .Hydrophobicity
 3621                         .Hydrophobicity_Charge
 3622                         .Vacuum_Electrostatics
 3623                             .Contact_Potentials
 3624                             .Map
 3625                             .Legend
 3626                             .Volume
 3627                     .Disulfide_Bonds
 3628                         .Residues
 3629                     .Salt_Bridges
 3630                         .Residues
 3631                             .Positively_Charged
 3632                             .Negatively_Charged
 3633                         .Contacts
 3634                 .Solvent
 3635                 .Inorganic
 3636                 .Ligand<ID>
 3637                     .Ligand
 3638                         .Ligand
 3639                         .BallAndStick
 3640                     .Pocket
 3641                         .Pocket
 3642                         .Polar_Contacts
 3643                         .Hydrophobic_Contacts
 3644                         .Pi_Pi_Contacts
 3645                         .Pi_Cation_Contacts
 3646                         .Halogen_Contacts
 3647                         .Selections
 3648                             .<Name>
 3649                                 .Selection
 3650                                 .Surface
 3651                                     .Surface
 3652                                     .Hydrophobicity
 3653                                     .Hydrophobicity_Charge
 3654                             .<Name>
 3655                                 ... ... ..
 3656                         .Residues
 3657                             .Aromatic
 3658                                 .Residues
 3659                                 .Surface
 3660                             .Hydrophobic
 3661                                 .Residues
 3662                                 .Surface
 3663                             .Polar
 3664                                 .Residues
 3665                                 .Surface
 3666                             .Positively_Charged
 3667                                 .Residues
 3668                                 .Surface
 3669                             .Negatively_Charged
 3670                                 .Residues
 3671                                 .Surface
 3672                             .Other
 3673                                 .Residues
 3674                                 .Surface
 3675                         .Surfaces
 3676                             .Surface
 3677                                 .Surface
 3678                                 .Hydrophobicity
 3679                                 .Hydrophobicity_Charge
 3680                                 .Vacuum_Electrostatics
 3681                                     .Contact_Potentials
 3682                                     .Map
 3683                                     .Legend
 3684                             .Cavity
 3685                                 .Surface
 3686                                 .Hydrophobicity
 3687                                 .Hydrophobicity_Charge
 3688                                 .Vacuum_Electrostatics
 3689                                     .Contact_Potentials
 3690                                     .Map
 3691                                     .Legend
 3692                     .Pocket_Solvent
 3693                         .Pocket_Solvent
 3694                         .Polar_Contacts
 3695                     .Pocket_Inorganic
 3696                         .Pocket_Inorganic
 3697                         .Polar_Contacts
 3698                         .Pi_Cation_Contacts
 3699                 .Ligand<ID>
 3700                     .Ligand
 3701                         ... ... ...
 3702                     .Pocket
 3703                         ... ... ...
 3704                     .Pocket_Solvent
 3705                         ... ... ...
 3706                     .Pocket_Inorganic
 3707                         ... ... ...
 3708                 .Docked_Poses or <CustomLabel>
 3709                     .<InputFileID>
 3710                         .Poses or <CustomLabel>
 3711                         .Pocket
 3712                             .Pocket
 3713                             .Distance_Contacts
 3714                                 .Contact1_At_<Distance>
 3715                                 .Contact1_At_<Distance>
 3716                                 ... ... ...
 3717                             .Polar_Contacts
 3718                             .Hydrophobic_Contacts
 3719                             .Pi_Pi_Contacts
 3720                             .Pi_Cation_Contacts
 3721                             .Halogen_Contacts
 3722                         .Pocket_Solvent
 3723                             .Pocket_Solvent
 3724                             .Polar_Contacts
 3725                         .Pocket_Inorganic
 3726                             .Polar_Contacts
 3727                             .Pi_Cation_Contacts
 3728                     .<InputFileID>
 3729                         ... ... ...
 3730                     .<InputFileID>
 3731                         ... ... ...
 3732             .Chain<ID>
 3733                 ... ... ...
 3734                 .Ligand<ID>
 3735                     ... ... ...
 3736                 .Ligand<ID>
 3737                     ... ... ...
 3738             .Chain<ID>
 3739                 ... ... ...
 3740         <PDBFileRoot>
 3741             .Complex
 3742                 ... ... ...
 3743             .Chain<ID>
 3744                 ... ... ...
 3745                 .Ligand<ID>
 3746                     ... ... ...
 3747                 .Ligand<ID>
 3748                     ... ... ...
 3749             .Chain<ID>
 3750                 ... ... ...
 3751     
 3752     The hydrophobic and electrostatic surfaces are not created for complete complex
 3753     and chain complex in input file(s) by default. A word to the wise: The creation of
 3754     surface objects may slow down loading of PML file and generation of PSE file, based
 3755     on the size of input complexes. The generation of PSE file may also fail.
 3756 
 3757 Options:
 3758     -a, --align <yes or no>  [default: no]
 3759         Align input files to a reference file before visualization. The docked poses
 3760         and trajectories are not aligned.
 3761     --alignMethod <align, cealign, super>  [default: super]
 3762         Alignment methodology to use for aligning input files to a
 3763         reference file.
 3764     --alignMode <FirstChain or Complex>  [default: FirstChain]
 3765         Portion of input and reference files to use for spatial alignment of
 3766         input files against reference file.  Possible values: FirstChain or
 3767         Complex.
 3768         
 3769         The FirstChain mode allows alignment of the first chain in each input
 3770         file to the first chain in the reference file along with moving the rest
 3771         of the complex to coordinate space of the reference file. The complete
 3772         complex in each input file is aligned to the complete complex in reference
 3773         file for the Complex mode.
 3774     --alignRefFile <filename>  [default: FirstInputFile]
 3775         Reference input file name. The default is to use the first input file
 3776         name specified using '-i, --infiles' option.
 3777     --allowEmptyObjects <yes or no>  [default: no]
 3778         Allow creation of empty PyMOL objects corresponding to solvent and
 3779         inorganic atom selections across chains and ligands in input file(s). By
 3780         default, the empty objects are marked for deletion.
 3781     -b, --BFactorChain <yes or no>  [default: yes]
 3782         A cartoon and putty around individual chains colored by an arbitrary set
 3783         of B factor values. The minimum and maximum values for B factors are
 3784         automatically detected. These values may indicate spread of electron
 3785         density around atoms or correspond to any other property mapped to
 3786         B factors in input file.
 3787     --BFactorColorPalette <text>  [default: blue_white_red]
 3788         Color palette for coloring cartoon and putty around chains generated using B
 3789         factor values. Any valid PyMOL color palette name is allowed. No validation is
 3790         performed. The complete list of valid color palette names is a available
 3791         at: pymolwiki.org/index.php/Spectrum. Examples: blue_white_red,
 3792         blue_white_magenta, blue_red, green_white_red, green_red.
 3793     -c, --chainIDs <First, All or ID1,ID2...>  [default: First]
 3794         List of chain IDs to use for visualizing macromolecules. Possible values:
 3795         First, All, or a comma delimited list of chain IDs. The default is to use the
 3796         chain ID for the first chain in each input file.
 3797     -d --disulfideBondsChain <yes or no>  [default: auto]
 3798         Disulfide bonds for chains. By default, the disulfide bonds group is
 3799         automatically created for chains containing amino acids and skipped for
 3800         chains only containing nucleic acids.
 3801     --dockedPoses <PDBFile,ChainID,LigandID,InputFiles,...>  [default: none]
 3802         PDB file name, pocket chain ID, ligand specification, and input files to use
 3803         for creating pockets to visualize docked poses or any arbitrary set of
 3804         molecules. Any valid PyMOL input file format is allowed.
 3805         
 3806         It's a quartet of comma limited values corresponding to PDF file name,
 3807         pocket chain ID, ligand ID, and input files. Multiple input file names are
 3808         delimited by spaces.
 3809         
 3810         The supported values for docked poses are shown below:
 3811              
 3812             PDBFile: A valid PDB file name
 3813             ChainID: A valid Chain ID
 3814             LigandID: A valid Ligand ID or UseInputFile
 3815             InputFiles: A space delimited list of input file names
 3816              
 3817         All docked pose values must be specified. No default values are assigned.
 3818         
 3819         The 'ChainID' and 'LigandID' are used for creating pocket to visualize docked
 3820         poses.
 3821         
 3822         The 'LigandID' must be a valid ligand ID in 'ChainID'. Alternatively, you may use
 3823         input files by specifying 'UseInputFile' to select residues in 'ChainID' for creating
 3824         pockets to visualize docked poses.
 3825     --dockedPosesDistanceContactsCutoffs <number1,number2...>  [default: none]
 3826         A comma delimited list of distances in Angstroms for identifying and displaying
 3827         distance contacts between heavy atoms in pocket residues and docked poses. A
 3828         PyMOL distance contact object is created for each specified distance. You may
 3829         find it helpful for identifying steric clashes between docked poses and pocket
 3830         residues. The maximum distance cutoff value must be less than the specified
 3831         value for '--pocketDistanceCutoff' option.
 3832     --dockedPosesDistanceContactsColor <text>  [default: red]
 3833         Color for drawing distance contacts between docked poses and pocket residues.
 3834         The specified value must be valid color. No validation is performed.
 3835     --dockedPosesGroupName <text>  [default: Docked_Poses]
 3836         PyMOL object name for docked poses group. You may use an artbitray name
 3837         to reflect data in input file(s) specified in '--dockedPoses' option. It must be a valid
 3838         PyMOL object name. No validation is performed.
 3839     --dockedPosesName <text>  [default: Poses]
 3840         PyMOL object name for docked poses object. You may use an artbitray name
 3841         to reflect data in input file(s) specified in '--dockedPoses' option. It must be a
 3842         valid PyMOL object name. No validation is performed.
 3843     -e, --examples
 3844         Print examples.
 3845     -h, --help
 3846         Print this help message.
 3847     -i, --infiles <infile1,infile2,infile3...>
 3848         Input file names.
 3849     --ignoreHydrogens <yes or no>  [default: yes]
 3850         Ignore hydrogens for ligand, pocket, selection, and residue type views.
 3851     -l, --ligandIDs <Largest, All or ID1,ID2...>  [default: Largest]
 3852         List of ligand IDs present in chains for visualizing macromolecules to
 3853         highlight ligand interactions. Possible values: Largest, All, or a comma
 3854         delimited list of ligand IDs. The default is to use the largest ligand present
 3855         in all or specified chains in each input file.
 3856         
 3857         Ligands are identified using organic selection operator available in PyMOL.
 3858         It'll also  identify buffer molecules as ligands. The largest ligand contains
 3859         the highest number of heavy atoms.
 3860     --labelFontID <number>  [default: 7]
 3861         Font ID for drawing labels. Default: 7 (Sans Bold). Valid values: 5 to 16.
 3862         The specified value must be a valid PyMOL font ID. No validation is
 3863         performed. The complete lists of valid font IDs is available at:
 3864         pymolwiki.org/index.php/Label_font_id. Examples: 5 - Sans;
 3865         7 - Sans Bold; 9 - Serif; 10 - Serif Bold.
 3866     -o, --outfile <outfile>
 3867         Output file name.
 3868     -p, --PMLOut <yes or no>  [default: yes]
 3869         Save PML file during generation of PSE file.
 3870     --pocketContactsInorganicColor <text>  [default: deepsalmon]
 3871         Color for drawing polar contacts between inorganic and pocket residues.
 3872         The specified value must be valid color. No validation is performed.
 3873     --pocketContactsInorganicPiCationColor <text>  [default: limon]
 3874         Color for drawing pi cation contacts between inorganic and pocket residues.
 3875         The specified value must be valid color. No validation is performed. The pi
 3876         cation contacts are drawn using PyMOL distance command with support for
 3877         mode 7 and may require incentive version of PyMOL.
 3878     --pocketContactsLigandColor <text>  [default: orange]
 3879         Color for drawing polar contacts between ligand and pocket residues.
 3880         The specified value must be valid color. No validation is performed.
 3881     --pocketContactsLigandHalogenColor <text>  [default: magenta]
 3882         Color for drawing halogen contacts between ligand and pocket residues.
 3883         The specified value must be valid color. No validation is performed.
 3884     --pocketContactsLigandHydrophobicColor <text>  [default: purpleblue]
 3885         Color for drawing hydrophobic contacts between ligand and pocket residues.
 3886         The specified value must be valid color. No validation is performed. The
 3887         hydrophobic contacts are shown between pairs of carbon atoms not
 3888         connected to hydrogen bond donor or acceptors atoms as identified
 3889         by PyMOL.
 3890     --pocketContactsLigandPiCationColor <text>  [default: yelloworange]
 3891         Color for drawing pi cation contacts between ligand and pocket residues.
 3892         The specified value must be valid color. No validation is performed. The pi
 3893         cation contacts are drawn using PyMOL distance command with support for
 3894         mode 7 and may require incentive version of PyMOL.
 3895     --pocketContactsLigandPiPiColor <text>  [default: cyan]
 3896         Color for drawing pi pi contacts between ligand and pocket residues.
 3897         The specified value must be valid color. No validation is performed. The pi
 3898         pi contacts are drawn using PyMOL distance command with support for
 3899         mode 6 and may require incentive version of PyMOL.
 3900     --pocketContactsSolventColor <text>  [default: marine]
 3901         Color for drawing polar contacts between solvent and pocket residues..
 3902         The specified value must be valid color. No validation is performed.
 3903     --pocketContactsCutoff <number>  [default: 4.0]
 3904         Distance in Angstroms for identifying polar, hyrdophobic contacts, pi pi,
 3905         pi cation, and halogen contacts  between atoms in pocket residues and
 3906         ligands.
 3907     --pocketDistanceCutoff <number>  [default: 5.0]
 3908         Distance in Angstroms for identifying pocket residues around ligands.
 3909     --pocketLabelColor <text>  [default: magenta]
 3910         Color for drawing residue or atom level labels for a pocket. The specified
 3911         value must be valid color. No validation is performed.
 3912     --pocketResidueTypes <yes or no>  [default: auto]
 3913         Pocket residue types. The residue groups are generated using residue types,
 3914         colors, and names specified by '--residueTypes' option. It is only valid for
 3915         amino acids.  By default, the residue type groups are automatically created
 3916         for pockets containing amino acids and skipped for chains only containing
 3917         nucleic acids.
 3918     --pocketSurface <yes or no>  [default: auto]
 3919         Surfaces around pocket residues colored by hydrophobicity alone and
 3920         both hydrophobicity and charge. The hydrophobicity surface is colored
 3921         at residue level using Eisenberg hydrophobicity scale for residues and color
 3922         gradient specified by '--surfaceColorPalette' option. The  hydrophobicity and
 3923         charge surface is colored [ Ref 140 ] at atom level using colors specified for
 3924         groups of atoms by '--surfaceAtomTypesColors' option. This scheme allows
 3925         simultaneous mapping of hyrophobicity and charge values on the surfaces.
 3926         
 3927         The cavity surfaces around ligands are also generated. These surfaces are
 3928         colored by hydrophobicity along and both hydrophobicity and charge.
 3929         
 3930         This option is only valid for amino acids. By default, both surfaces are
 3931         automatically created for pockets containing amino acids and skipped for
 3932         pockets containing only nucleic acids.
 3933     --pocketSurfaceElectrostatics <yes or no>  [default: no]
 3934         Vacuum electrostatics contact potential surface around pocket residues.
 3935         A word to the wise from PyMOL documentation: The computed protein
 3936         contact potentials are only qualitatively useful, due to short cutoffs,
 3937         truncation, and lack of solvent "screening".
 3938         
 3939         The cavity surface around ligands is also generated. This surface is
 3940         colored by vacuum electrostatics contact potential.
 3941         
 3942         This option is only valid for amino acids. By default, the electrostatics surface
 3943         is automatically created for chains containing amino acids and skipped for chains
 3944         containing only nucleic acids.
 3945     -r, --residueTypes <Type,Color,ResNames,...>  [default: auto]
 3946         Residue types, colors, and names to generate for residue groups during
 3947         '--pocketResidueTypes' and '--residueTypesChain' option. It is only
 3948         valid for amino acids.
 3949         
 3950         It is a triplet of comma delimited list of amino acid residues type, residues
 3951         color, and a space delimited list three letter residue names. 
 3952         
 3953         The default values for residue type, color, and name triplets  are shown
 3954         below:
 3955             
 3956             Aromatic,brightorange,HIS PHE TRP TYR,
 3957             Hydrophobic,orange,ALA GLY VAL LEU ILE PRO MET,
 3958             Polar,palegreen,ASN GLN SER THR CYS,
 3959             Positively_Charged,marine,ARG LYS,
 3960             Negatively_Charged,red,ASP GLU
 3961             
 3962         The color name must be a valid PyMOL name. No validation is performed.
 3963         An amino acid name may appear across multiple residue types. All other
 3964         residues are grouped under 'Other'.
 3965     --residueTypesChain <yes or no>  [default: auto]
 3966         Chain residue types. The residue groups are generated using residue types,
 3967         colors, and names specified by '--residueTypes' option. It is only valid for
 3968         amino acids.  By default, the residue type groups are automatically created
 3969         for chains containing amino acids and skipped for chains only containing
 3970         nucleic acids.
 3971      --saltBridgesChain <yes or no>  [default: auto]
 3972         Salt bridges for chains. By default, the salt bridges group is automatically
 3973         created for chains containing amino acids and skipped for chains only
 3974         containing nucleic acids. The salt bridges correspond to polar contacts
 3975         between positively and negatively charges residues in a chain.
 3976     --saltBridgesChainContactsColor <text>  [default: brightorange]
 3977         Color for drawing polar contacts between positively and negatively
 3978         charged residues involved in salt bridges. The specified value must
 3979         be valid color. No validation is performed.
 3980     --saltBridgesChainCutoff <number>  [default: 4.0]
 3981         Distance in Angstroms for identifying polar contacts between positively
 3982         and negatively charged residues involved in salt bridges in a chain.
 3983      --saltBridgesChainResidues <Type, ResNames,...>  [default: auto]
 3984         Residue types and names to use for identifying positively and negatively
 3985         charged residues involved in salt bridges.
 3986         
 3987         It is a pair of comma delimited list of amino acid residue types and a space
 3988         delimited list three letter residue names.
 3989         
 3990         The default values for residue type and name pairs  are shown below:
 3991             
 3992             Positively_Charged,ARG LYS HIS HSP
 3993             Negatively_Charged,ASP GLU
 3994             
 3995         The residue names must be valid names. No validation is performed.
 3996     --selectionsChain <ObjectName,SelectionSpec,...>  [default: none]
 3997         Custom selections for chains. It is a pairwise list of comma delimited values
 3998         corresponding to PyMOL object names and selection specifications.  The
 3999         selection specification must be a valid PyMOL specification. No validation is
 4000         performed.
 4001         
 4002         The PyMOL objects are created for each chain corresponding to the
 4003         specified selections. The display style for PyMOL objects is set using
 4004         value of '--selectionsChainStyle' option.
 4005         
 4006         The specified selection specification is automatically appended to appropriate
 4007         chain specification before creating PyMOL objects.
 4008         
 4009         For example, the following specification for '--selectionsChain' option will
 4010         generate PyMOL objects for chains containing Cysteines and Serines:
 4011             
 4012             Cysteines,resn CYS,Serines,resn SER
 4013             
 4014     --selectionsChainSurface <yes or no>  [default: auto]
 4015         Surfaces around individual chain selections colored by hydrophobicity alone
 4016         and both hydrophobicity and charge. This option is similar to '--surfaceChain'
 4017         options for creating surfaces for chain. Additional details are available in the
 4018         documentation section for '--surfaceChain' options.
 4019     --selectionsChainStyle <DisplayStyle>  [default: sticks]
 4020         Display style for PyMOL objects created for '--selectionsChain' option. It
 4021         must be a valid PyMOL display style. No validation is performed.
 4022     --selectionsPocket <ObjectName,SelectionSpec,...>  [default: none]
 4023         Custom selections for pocket residues. It is a pairwise list of comma delimited
 4024         values corresponding to PyMOL object names and selection specifications.  The
 4025         selection specification must be a valid PyMOL specification. No validation is
 4026         performed.
 4027         
 4028         The PyMOL objects are created for each pocket corresponding to the
 4029         specified selections. The display style for PyMOL objects is set using
 4030         value of '--selectionsChainStyle' option.
 4031         
 4032         The specified selection specification is automatically appended to appropriate
 4033         pocket specification before creating PyMOL objects.
 4034         
 4035         For example, the following specification for '--selectionsPocket' option will
 4036         generate PyMOL objects for pockets containing Tyrosines and Serines:
 4037             
 4038             Tyrosines,resn TYR,Serines,resn SER
 4039             
 4040     --selectionsPocketSurface <yes or no>  [default: auto]
 4041         Surfaces around individual pocket chain selections colored by hydrophobicity
 4042         alone and both hydrophobicity and charge. This option is similar to '--surfaceChain'
 4043         options for creating surfaces for chain. Additional details are available in the
 4044         documentation section for '--surfaceChain' options.
 4045     --selectionsPocketStyle <DisplayStyle>  [default: sticks]
 4046         Display style for PyMOL objects created for '--selectionsPocket' option. It
 4047         must be a valid PyMOL display style. No validation is performed.
 4048     --surfaceChain <yes or no>  [default: auto]
 4049         Surfaces around individual chain colored by hydrophobicity alone and
 4050         both hydrophobicity and charge. The hydrophobicity surface is colored
 4051         at residue level using Eisenberg hydrophobicity scale for residues and color
 4052         gradient specified by '--surfaceColorPalette' option. The  hydrophobicity and
 4053         charge surface is colored [ Ref 140 ] at atom level using colors specified for
 4054         groups of atoms by '--surfaceAtomTypesColors' option. This scheme allows
 4055         simultaneous mapping of hyrophobicity and charge values on the surfaces.
 4056         
 4057         This option is only valid for amino acids. By default, both surfaces are
 4058         automatically created for chains containing amino acids and skipped for
 4059         chains containing only nucleic acids.
 4060     --surfaceChainElectrostatics <yes or no>  [default: no]
 4061         Vacuum electrostatics contact potential surface and volume around individual
 4062         chain. A word to the wise from PyMOL documentation: The computed protein
 4063         contact potentials are only qualitatively useful, due to short cutoffs,
 4064         truncation, and lack of solvent "screening".
 4065         
 4066         This option is only valid for amino acids. By default, the electrostatics surface
 4067         and volume are automatically created for chains containing amino acids and
 4068         skipped for chains containing only nucleic acids.
 4069     --surfaceChainComplex <yes or no>  [default: no]
 4070         Hydrophobic surface around chain complex. The  surface is colored by
 4071         hydrophobicity. It is only valid for amino acids.
 4072     --surfaceComplex <yes or no>  [default: no]
 4073         Hydrophobic surface around complete complex. The  surface is colored by
 4074         hydrophobicity. It is only valid for amino acids.
 4075     --surfaceAtomTypesColors <ColorType,ColorSpec,...>  [default: auto]
 4076         Atom colors for generating surfaces colored by hyrophobicity and charge
 4077         around chains and pockets in proteins. It's a pairwise comma delimited list
 4078         of atom color type and color specification for goups of atoms.
 4079         
 4080         The default values for color types [ Ref 140 ] along wth color specifications
 4081         are shown below: 
 4082             
 4083             HydrophobicAtomsColor, yellow,
 4084             NegativelyChargedAtomsColor, red,
 4085             PositivelyChargedAtomsColor, blue,
 4086             OtherAtomsColor, gray90
 4087             
 4088         The color names must be valid PyMOL names.
 4089         
 4090         The color values may also be specified as space delimited RGB triplets:
 4091              
 4092             HydrophobicAtomsColor, 0.95 0.78 0.0,
 4093             NegativelyChargedAtomsColor, 1.0 0.4 0.4,
 4094             PositivelyChargedAtomsColor, 0.2 0.5 0.8,
 4095             OtherAtomsColor, 0.95 0.95 0.95
 4096             
 4097     --surfaceColor <ColorName>  [default: lightblue]
 4098         Color name for surfaces around chains and pockets. This color is not used
 4099         for surfaces colored by hydrophobicity and charge. The color name must be
 4100         a valid PyMOL name.
 4101     --surfaceColorPalette <RedToWhite or WhiteToGreen>  [default: RedToWhite]
 4102         Color palette for hydrophobic surfaces around chains and pockets in proteins.
 4103         Possible values: RedToWhite or WhiteToGreen from most hydrophobic amino
 4104         acid to least hydrophobic. The colors values for amino acids are taken from
 4105         color_h script available as part of the Script Library at PyMOL Wiki.
 4106     --surfaceTransparency <number>  [default: 0.25]
 4107         Surface transparency for molecular surfaces.
 4108     -t, --trajectories <PDBToplogyFile,TrajFiles,...>  [default: none]
 4109         PDB topology file name and MD trajectories files for visualizing trajectories
 4110         for PDB files.
 4111         
 4112         It's a pair of comma limited values corresponding to a PDB file name and
 4113         MD trajectory files. Multiple trajectory file names are delimited by spaces.
 4114         
 4115         The supported values for trajectories are shown below:
 4116              
 4117             PDBTopologyFile: A valid PDB file name
 4118             TrajFiles: A space delimited list of MD trajectory file names
 4119              
 4120         The trajectory files must correspond to the specified PDB topology file. In
 4121         addition, the format of trajectory files must be a valid PyMOL format. PyMOL
 4122         uses Molfile Plugin, which supports a variety of trajectory file formats. For
 4123         example: HARMM, NAMD, X-PLOR (.dcd), Gromacs TRR/XTC (.trr, .xtc),
 4124         XYZ (.xyz) etc.
 4125     --overwrite
 4126         Overwrite existing files.
 4127     -w, --workingdir <dir>
 4128         Location of working directory which defaults to the current directory.
 4129 
 4130 Examples:
 4131     To visualize the first chain, the largest ligand in the first chain, and ligand
 4132     binding pockets to highlight ligand interaction with pocket resiudes, solvents
 4133     and inorganics, in a PDB file, and generate a PML file, type:
 4134 
 4135         % PyMOLVisualizeMacromolecules.py -i Sample4.pdb -o Sample4.pml
 4136 
 4137     To visualize the first chain along with all cysteines and serines, the largest
 4138     ligand in the first chain, and ligand binding pockets to highlight ligand
 4139     interaction with pocket resiudes, solvents and inorganics, in a PDB file,
 4140     and generate a PML file, type:
 4141 
 4142         % PyMOLVisualizeMacromolecules.py -i Sample4.pdb -o Sample4.pml
 4143           --selectionsChain "Cysteines,resn cys,Serines,resn ser"
 4144 
 4145     To visualize the first chain along with all serines and tyrosines in binding
 4146     pockets, the largest ligand in the first chain, and ligand binding pockets
 4147     to highlight ligand interaction with pocket resiudes, solvents and inorganics,
 4148     in a PDB file, and generate a PML file, type:
 4149 
 4150         % PyMOLVisualizeMacromolecules.py -i Sample4.pdb -o Sample4.pml
 4151           --selectionsPocket "Serines,resn ser,Tyrosines,resn tyr"
 4152 
 4153     To visualize docking poses from a SD file in a pocket corresponding to a SD file
 4154     for a chain, along with visualization of other information, in a PDB file,
 4155     and generate a PML file, type:
 4156 
 4157         % PyMOLVisualizeMacromolecules.py -c All -l "N3" -i  SampleMpro6LU7.pdb
 4158           -o  SampleMpro6LU7.pml --dockedPoses "SampleMpro6LU7.pdb,A,UseInputFile,
 4159           SampleMproDockedPosesTop100.sdf"
 4160     
 4161     To visualize docking poses from a SD file in a pocket corresponding to SD file
 4162     for a chain, along with visualization of distance contacts at 3.0 and 3.5 Angstroms,
 4163     in a PDB file, and generate a PML file, type:
 4164 
 4165         % PyMOLVisualizeMacromolecules.py -c All -l "N3" -i  SampleMpro6LU7.pdb
 4166           -o  SampleMpro6LU7.pml --dockedPoses "SampleMpro6LU7.pdb,A,UseInputFile,
 4167           SampleMproDockedPosesTop100.sdf"
 4168           --dockedPosesDistanceContactsCutoffs "3.0, 3.5"
 4169     
 4170     To visualize docking poses from a SD file in a pocket corresponding to a specific
 4171     ligand a chain, along with visualization of other information, in a PDB file,
 4172     and generate a PML file, type:
 4173 
 4174         % PyMOLVisualizeMacromolecules.py -c All -l "N3" -i  SampleMpro6LU7.pdb
 4175           -o  SampleMpro6LU7.pml --dockedPoses "SampleMpro6LU7.pdb,A,N3,
 4176           SampleMproDockedPosesTop100.sdf" 
 4177     
 4178     To visualize docking poses from multiple SDs file in a pocket corresponding SD file
 4179     a for a chain, along with visualization of other information, in a PDB file, and
 4180     generate a PML file, type: 
 4181 
 4182         % PyMOLVisualizeMacromolecules.py -c All -l "N3" -i  SampleMpro6LU7.pdb
 4183           -o  SampleMpro6LU7.pml --dockedPoses "SampleMpro6LU7.pdb,A,UseInputFile,
 4184           SampleMproDockedPosesTop100.sdf SampleMproDockedPosesDiverse100.sdf"
 4185 
 4186     To visualize trajectory from a DCD file,  along with visualization of other
 4187     information, corresponding to a PDB topology file and generate a PML file,
 4188     type:
 4189 
 4190         % PyMOLVisualizeMacromolecules.py -t "Sample10.pdb, Sample10.dcd"
 4191           -i Sample10.pdb -o Sample10.pml
 4192 
 4193     To visualize all chains, all ligands in all chains, and all ligand binding pockets to
 4194     highlight ligand interaction with pocket resiudes, solvents and inorganics, in a
 4195     PDB file, and generate a PML file, type:
 4196 
 4197         % PyMOLVisualizeMacromolecules.py -c All -l All -i Sample4.pdb -o
 4198           Sample4.pml
 4199 
 4200     To visualize all chains, ligands, and ligand binding pockets along with displaying
 4201     all hydrophibic surfaces and chain electrostatic surface, in a PDB file, and
 4202     generate a PML file, type:
 4203 
 4204         % PyMOLVisualizeMacromolecules.py -c All -l All
 4205           --surfaceChainElectrostatics yes --surfaceChainComplex yes
 4206           --surfaceComplex yes -i Sample4.pdb -o Sample4.pml
 4207 
 4208     To visualize chain E, ligand ADP in chain E, and ligand binding pockets to
 4209     highlight ligand interaction with pocket resiudes, solvents and inorganics,
 4210     in a PDB file, and generate a PML file, type:
 4211 
 4212         % PyMOLVisualizeMacromolecules.py -c E -l ADP -i Sample3.pdb
 4213           -o Sample3.pml
 4214 
 4215     To visualize chain E, ligand ADP in chain E, and ligand binding pockets to
 4216     highlight ligand interaction with pocket resiudes, solvents and inorganics,
 4217     in a PDB file, and generate a PSE file, type:
 4218 
 4219         % PyMOLVisualizeMacromolecules.py -c E -l ADP -i Sample3.pdb
 4220           -o Sample3.pse
 4221 
 4222     To visualize the first chain, the largest ligand in the first chain, and ligand
 4223     binding pockets to highlight ligand interaction with pocket resiudes, solvents
 4224     and inorganics, in PDB files, along with aligning first chain in each input file to
 4225     the first chain in first input file, and generate a PML file, type:
 4226 
 4227         % PyMOLVisualizeMacromolecules.py --align yes -i
 4228           "Sample5.pdb,Sample6.pdb,Sample7.pdb" -o SampleOut.pml
 4229 
 4230     To visualize all chains, all ligands in all chains, and all ligand binding pockets to
 4231     highlight ligand interaction with pocket resiudes, solvents and inorganics, in
 4232     PDB files, along with aligning first chain in each input file to the first chain in
 4233     first input file, and generate a PML file, type:
 4234 
 4235         % PyMOLVisualizeMacromolecules.py --align yes  -c All -l All -i
 4236           "Sample5.pdb,Sample6.pdb,Sample7.pdb" -o SampleOut.pml
 4237 
 4238     To visualize all chains, all ligands in all chains, and all ligand binding pockets to
 4239     highlight ligand interaction with pocket resiudes, solvents and inorganics, in
 4240     PDB files, along with aligning first chain in each input file to the first chain in a
 4241     specified PDB file using a specified alignment method, and generate a PML
 4242     file, type:
 4243 
 4244         % PyMOLVisualizeMacromolecules.py --align yes  --alignMode FirstChain
 4245           --alignRefFile Sample5.pdb --alignMethod super   -c All  -l All -i
 4246           "Sample5.pdb,Sample6.pdb,Sample7.pdb" -o SampleOut.pml
 4247 
 4248 Author:
 4249     Manish Sud(msud@san.rr.com)
 4250 
 4251 See also:
 4252     DownloadPDBFiles.pl, PyMOLVisualizeCavities.py,
 4253     PyMOLVisualizeCryoEMDensity.py, PyMOLVisualizeElectronDensity.py,
 4254     PyMOLVisualizeInterfaces.py, PyMOLVisualizeSurfaceAndBuriedResidues.py
 4255 
 4256 Copyright:
 4257     Copyright (C) 2026 Manish Sud. All rights reserved.
 4258 
 4259     The functionality available in this script is implemented using PyMOL, a
 4260     molecular visualization system on an open source foundation originally
 4261     developed by Warren DeLano.
 4262 
 4263     This file is part of MayaChemTools.
 4264 
 4265     MayaChemTools is free software; you can redistribute it and/or modify it under
 4266     the terms of the GNU Lesser General Public License as published by the Free
 4267     Software Foundation; either version 3 of the License, or (at your option) any
 4268     later version.
 4269 
 4270 """
 4271 
 4272 if __name__ == "__main__":
 4273     main()