MayaChemTools

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