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