        1 #!/bin/env python
        2 # File: PyMOLUtil.py
        3 # Author: Manish Sud <msud@san.rr.com>
        4 #
        5 # Copyright (C) 2018 Manish Sud. All rights reserved.
        6 #
        7 # The functionality available in this file is implemented using PyMOL, a
        8 # molecular visualization system on an open source foundation originally
        9 # developed by Warren DeLano.
       10 #
       11 # This file is part of MayaChemTools.
       12 #
       13 # MayaChemTools is free software; you can redistribute it and/or modify it under
       14 # the terms of the GNU Lesser General Public License as published by the Free
       15 # Software Foundation; either version 3 of the License, or (at your option) any
       16 # later version.
       17 #
       18 # MayaChemTools is distributed in the hope that it will be useful, but without
       19 # any warranty; without even the implied warranty of merchantability of fitness
       20 # for a particular purpose.  See the GNU Lesser General Public License for more
       21 # details.
       22 #
       23 # You should have received a copy of the GNU Lesser General Public License
       24 # along with MayaChemTools; if not, see <http://www.gnu.org/licenses/> or
       25 # write to the Free Software Foundation Inc., 59 Temple Place, Suite 330,
       26 # Boston, MA, 02111-1307, USA.
       27 #
       28
       29 from __future__ import print_function
       30
       31 import os
       32 import sys
       33 import re
       34
       35 from pymol import cmd, stored, CmdException
       36
       37 import MiscUtil
       38
       39 __all__ = ["AreAminoAcidResiduesPresent", "AreNucleicAcidResiduesPresent", "CalculateCenterOfMass", "ConvertFileFormat", "ConvertPMLFileToPSEFile", "GetChains", "GetChainsAndLigandsInfo", "GetAminoAcidResiduesInfo", "GetInorganicResiduesInfo", "GetLargestLigand", "GetLigandResiduesInfo", "GetLigands", "GetMolecules", "GetNucleicAcidResiduesInfo", "GetPocketInorganicResiduesInfo", "GetPocketPolymerResiduesInfo", "GetPocketSolventResiduesInfo",  "GetPolymerResiduesInfo", "GetSolventResiduesInfo", "ProcessChainsAndLigandsOptionsInfo", "SetupPMLForAlignment", "SetupPMLForBFactorPuttyView", "SetupPMLForBallAndStickView", "SetupPMLForEnableDisable", "SetupPMLForGroup", "SetupPMLForHydrophobicSurfaceView", "SetupPMLForHydrophobicAndChargeSurfaceView", "SetupPMLForInorganicView", "SetupPMLForLigandPocketInorganicView", "SetupPMLForLigandPocketSolventView", "SetupPMLForLigandPocketView", "SetupPMLForLigandView", "SetupPMLForPolarContactsView", "SetupPMLForPolymerChainComplexView", "SetupPMLForPolymerChainView", "SetupPMLForPolymerComplexView", "SetupPMLForSolventView", "SetupPMLForSurfaceView", "SetupPMLForSelectionDisplayView", "SetupPMLHeaderInfo"]
       40
       41 def GetMolecules(Selection = "all"):
       42     """Get names of molecule objects in a selection or all molecule objects.
       43
       44     Arguments:
       45         Selection: (str): A PyMOL selection.
       46
       47     Returns:
       48         list: Names of molecule objects.
       49
       50     """
       51     Names = cmd.get_object_list('(' + Selection + ')')
       52
       53     return Names
       54
       55 def GetChains(MoleculeName, RemoveEmpty = True):
       56     """Get chain identifiers present in a molecule.
       57
       58     Arguments:
       59         MoleculeName (str): Name of a PyMOL molecule object.
       60         RemoveEmpty (bool): Remove empty chain ID from the list of chain IDs
       61             returned by PyMOL.
       62
       63     Returns:
       64         list: Names of chains present in a molecule, sorted alphabetically in a
       65             ascending order.
       66
       67     """
       68     if not len(MoleculeName):
       69         return None
       70
       71     ChainIDs = []
       72     try:
       73         ChainIDs = cmd.get_chains('model %s' % MoleculeName)
       74     except CmdException as ErrMsg:
       75         MiscUtil.PrintWarning("PyMOLUtil.GetChains: Invalid molecule name: %s" % MoleculeName)
       76
       77     if not len(ChainIDs):
       78         return None
       79
       80     # Remove empty Chain IDs from the list...
       81     if RemoveEmpty:
       82         NonEmptyChainIDs = []
       83         for ChainID in ChainIDs:
       84             if len(ChainID):
       85                 NonEmptyChainIDs.append(ChainID)
       86         if len(NonEmptyChainIDs) != len(ChainIDs):
       87             MiscUtil.PrintInfo("PyMOLUtil.GetChains: Removing non-empty chain IDs from the list of chain IDs...")
       88
       89         ChainIDs = NonEmptyChainIDs
       90
       91     return ChainIDs
       92
       93 def GetChainsAndLigandsInfo(Infile, MolName, Quite = False, LigandSortBy = "Size", LigandSortOrder = "Auto", LigandIgnoreHydrogens = "Yes"):
       94     """Get chain identifiers present in a molecule along with names of the
       95     ligands present in chains. Ligands are identified using PyMOL 'organic'
       96     selection.
       97
       98     Arguments:
       99         Infile (str) : Name of a file.
      100         MolName (str) : Name to use for PyMOL molecule object.
      101         Quite (bool) : Flag
      102         LigandSortBy (str): Sort ligand names alphabetically or by size. Possible
      103             values: Alphabetical or Size
      104         LigandSortOrder (str): Sort order for sorting ligands. Possible values:
      105             Ascending, Descending, Auto. The 'Auto' value implies automatic
      106             determination of sort order based on the value of 'SortBy'.
      107             Automatic defaults: Descending for SortBy value of Size; Ascending
      108             for SortBy value of Alphabetical.
      109         LigandIgnoreHydrogens (str): Ignore hydrogens during determination of ligand
      110             size.
      111
      112     Returns:
      113         dict: A dictionary containing list of chain identifiers and dictionaries
      114             of chains containing lists of ligand names for each chain. Names of
      115             ligands present in chain for a molecule sorted by size or
      116             alphabetically.
      117
      118     Examples:
      119
      120         ChainsAndLigandsInfo = GetChainsAndLigandsInfo(Infile, MolName)
      121         for ChainID in ChainsAndLigandsInfo["ChainIDs"]:
      122             for LigandID in ChainsAndLigandsInfo["LigandIDs"][ChainID]:
      123                 MiscUtil.PrintInfo("ChainID: %s; LigandID: %s" % (ChainID,
      124                     LigandID))
      125
      126     """
      127     if not Quite:
      128         MiscUtil.PrintInfo("\nRetrieving chain and ligand information from input file %s..." % Infile)
      129
      130     # Collect chains and ligands information with ligands sorted by size to be used for
      131     # identification of largest ligand at the top...
      132     cmd.load(Infile, MolName)
      133     ChainsAndLigandsInfo = _GetChainsAndLigands(MolName, LigandSortBy = "size", LigandSortOrder = "descending")
      134     cmd.delete(MolName)
      135
      136     # Print out chain and ligand IDs...
      137     if not Quite:
      138         ChainIDs = ", ".join(ChainsAndLigandsInfo["ChainIDs"]) if len(ChainsAndLigandsInfo["ChainIDs"]) else "None"
      139         MiscUtil.PrintInfo("Chain IDs: %s" % ChainIDs)
      140
      141         for ChainID in ChainsAndLigandsInfo["ChainIDs"]:
      142             LigandIDs = ", ".join(ChainsAndLigandsInfo["LigandIDs"][ChainID]) if len(ChainsAndLigandsInfo["LigandIDs"][ChainID]) else "None"
      143             MiscUtil.PrintInfo("Chain ID: %s; LigandIDs: %s" % (ChainID, LigandIDs))
      144
      145     return ChainsAndLigandsInfo
      146
      147 def GetLigands(MoleculeName, ChainName, SortBy = "Size", SortOrder = "Auto", IgnoreHydrogens = "Yes"):
      148     """Get names of ligands present in a chain of a  molecule. Ligands are
      149     identified using PyMOL 'organic' selection.
      150
      151     Arguments:
      152         MoleculeName (str): Name of a PyMOL molecule object.
      153         ChainName (str): Name of a chain in a molecule.
      154         SortBy (str): Sort ligand names alphabetically or by size. Possible
      155             values: Alphabetical or Size
      156         SortOrder (str): Sort order for sorting ligands. Possible values:
      157             Ascending, Descending, Auto. The 'Auto' value implies automatic
      158             determination of sort order based on the value of 'SortBy'.
      159             Automatic defaults: Descending for SortBy value of Size; Ascending
      160             for SortBy value of Alphabetical.
      161         IgnoreHydrogens (str): Ignore hydrogens during determination of ligand
      162             size.
      163
      164     Returns:
      165         list: Names of ligands present in chain for a molecule sorted by size
      166             or alphabetically.
      167
      168     """
      169     if not (len(MoleculeName) and len(ChainName)):
      170         return None
      171
      172     LigandsInfoMap = _GetLigandsInfo(MoleculeName, ChainName, SortBy, SortOrder, IgnoreHydrogens)
      173
      174     LigandIDs = LigandsInfoMap["LigandResNames"]
      175     if not len(LigandIDs):
      176         LigandIDs = None
      177
      178     return LigandIDs
      179
      180 def GetLargestLigand(MoleculeName, ChainName, IgnoreHydrogens = 'Yes'):
      181     """Get name of the largest ligand for a chain present in a molecule. Ligands
      182     are identified using PyMOL 'organic' selection.
      183
      184     Arguments:
      185         IgnoreHydrogens (str): Ignore hydrogens during determination of ligand
      186             size.
      187
      188     Returns:
      189         str: Name of the largest ligand present in a chain.
      190
      191     """
      192     if not (len(MoleculeName) and len(ChainName)):
      193         return None
      194
      195     SortBy = "Size"
      196     SortOrder = "Descending"
      197     LigandsInfoMap = _GetLigandsInfo(MoleculeName, ChainName, SortBy, SortOrder, IgnoreHydrogens)
      198     LigandIDs = LigandsInfoMap["LigandResNames"]
      199
      200     if len(LigandIDs):
      201         LigandID = LigandIDs[0]
      202     else:
      203         LigandID = None
      204
      205     return LigandID
      206
      207 def _GetChainsAndLigands(MoleculeName, LigandSortBy = "Size", LigandSortOrder = "Auto", LigandIgnoreHydrogens = "Yes"):
      208     """Get chain identifiers in a molecule along with names of the ligands
      209     present in chains. Ligands are identified using PyMOL 'organic' selection.
      210     """
      211     if not len(MoleculeName):
      212         return None
      213
      214     ChainIDs = GetChains(MoleculeName)
      215     if ChainIDs is None:
      216         return None
      217
      218     ChainsAndLigandsMap = {}
      219     ChainsAndLigandsMap["ChainIDs"] = []
      220     ChainsAndLigandsMap["LigandIDs"] = {}
      221
      222     for ChainID in ChainIDs:
      223         ChainsAndLigandsMap["ChainIDs"].append(ChainID)
      224         ChainsAndLigandsMap["LigandIDs"][ChainID] = []
      225
      226         LigandIDs = GetLigands(MoleculeName, ChainID, SortBy = LigandSortBy, SortOrder = LigandSortOrder, IgnoreHydrogens = LigandIgnoreHydrogens)
      227         if LigandIDs is not None:
      228             ChainsAndLigandsMap["LigandIDs"][ChainID] = LigandIDs
      229
      230     return ChainsAndLigandsMap
      231
      232 def _GetLigandsInfo(MoleculeName, ChainName, SortBy = "Size", SortOrder = "Auto", IgnoreHydrogens = "Yes"):
      233     """Retrieve information about ligands present in a chain of a molecule."""
      234
      235     if not MiscUtil.CheckTextValue(SortBy, "Size Alphabetical"):
      236         MiscUtil.PrintError("PyMOLUtil._GetLigandsInfo: The value specified, %s, for parameter SortBy is not valid. SupportedValues: Size Alphabetical" % SortBy)
      237
      238     if not MiscUtil.CheckTextValue(SortOrder, "Ascending Descending Auto"):
      239         MiscUtil.PrintError("PyMOLUtil._GetLigandsInfo: The value specified, %s, for parameter SortOrder is not valid. SupportedValues: Ascending Descending Auto" % SortOrder)
      240
      241     if not MiscUtil.CheckTextValue(IgnoreHydrogens, "Yes No"):
      242         MiscUtil.PrintError("PyMOLUtil._GetLigandsInfo: The value specified, %s, for parameter IgnoreHydrogens is not valid. SupportedValues: Yes No" % IgnoreHydrogens)
      243
      244     SortBySize = True if re.match("^Size$", SortBy, re.I) else False
      245     if re.match("^Auto$", SortOrder, re.I):
      246         SortOrderDescending = True if re.match("^Size$", SortBy, re.I) else False
      247     else:
      248         SortOrderDescending = True if re.match("^Descending$", SortOrder, re.I) else False
      249     IgnoreHydrogenAtoms = True if re.match("^Yes$", IgnoreHydrogens, re.I) else False
      250
      251     # Set up a command to retrieve all appropriate ligand atoms in organic ligands...
      252     SelectionCmd = "%s and chain %s and organic" % (MoleculeName, ChainName)
      253     if IgnoreHydrogenAtoms:
      254         SelectionCmd = "%s and not hydro" % (SelectionCmd)
      255
      256     # Retrieve atoms...
      257     stored.LigandsInfo = []
      258     cmd.iterate(SelectionCmd, "stored.LigandsInfo.append([resi, resn])")
      259
      260     # Retrieve ligands...
      261     LigandsInfoMap = {}
      262     LigandsInfoMap["LigandResNames"] = []
      263     LigandsInfoMap["LigandAtomCount"] = {}
      264     LigandsInfoMap["LigandResNumber"] = {}
      265
      266     for LigandResNum, LigandResName in stored.LigandsInfo:
      267         if LigandResName in LigandsInfoMap["LigandResNames"]:
      268             LigandsInfoMap["LigandAtomCount"][LigandResName] += 1
      269         else:
      270             LigandsInfoMap["LigandResNames"].append(LigandResName)
      271             LigandsInfoMap["LigandAtomCount"][LigandResName] = 1
      272             LigandsInfoMap["LigandResNumber"][LigandResName] = LigandResNum
      273
      274     if not len(LigandsInfoMap["LigandResNames"]):
      275         return LigandsInfoMap
      276
      277     # Sort ligand names...
      278     ReverseOrder = True if SortOrderDescending else False
      279     if SortBySize:
      280         SortedLigandResNames = sorted(LigandsInfoMap["LigandResNames"], key = lambda LigandResName: LigandsInfoMap["LigandAtomCount"][LigandResName], reverse = ReverseOrder)
      281     else:
      282         # Sort alphabetically...
      283         SortedLigandResNames = sorted(LigandsInfoMap["LigandResNames"], reverse = ReverseOrder)
      284
      285     LigandsInfoMap["LigandResNames"] = SortedLigandResNames
      286
      287     return LigandsInfoMap
      288
      289 def AreAminoAcidResiduesPresent(MoleculeName, ChainName, Type = "Any"):
      290     """Check for the presence of amino acid residues in a chain of a
      291     molecule. Chains are identified using PyMOL 'polymer' selection.
      292     Nonstandard amino acid residues correspond to all residues other than
      293     the standard amino acids and nucleic acids. Any amino acid residues cover
      294     all residues other than the standard nucleic acids.
      295
      296     Arguments:
      297         MoleculeName (str): Name of a PyMOL molecule object.
      298         ChainName (str): Name of a chain in a molecule.
      299         Type (str): Types of amino acids: Standard, NonStandard, Any
      300
      301     Returns:
      302         boolean: True or False.
      303
      304     """
      305
      306     if not (len(MoleculeName) and len(ChainName)):
      307         return False
      308
      309     if not re.match("^(Standard|NonStandard|Any)$", Type, re.I):
      310         MiscUtil.PrintError("PyMOLUtil.AreAminoAcidResiduesPresent: Invalid amino acid type: %s" % Type)
      311
      312     SelectionCmd = _SetupAminoAcidResiduesSelectionCmd(MoleculeName, ChainName, Type)
      313
      314     Status = True if cmd.count_atoms(SelectionCmd) else False
      315
      316     return Status
      317
      318 def AreNucleicAcidResiduesPresent(MoleculeName, ChainName):
      319     """Check for the presence of nucleic acid residues in a chain of a
      320     molecule. Chains are identified using PyMOL 'polymer' selection.
      321
      322     Arguments:
      323         MoleculeName (str): Name of a PyMOL molecule object.
      324         ChainName (str): Name of a chain in a molecule.
      325
      326     Returns:
      327         boolean: True or False.
      328
      329     """
      330
      331     if not (len(MoleculeName) and len(ChainName)):
      332         return False
      333
      334     ResidueNames = _GetNucleicAcidResidueNames()
      335     if not len(ResidueNames):
      336         return False
      337
      338     ResidueNamesSelection = "+".join(ResidueNames)
      339     SelectionCmd = "(%s and chain %s and polymer and (resn %s))" % (MoleculeName, ChainName, ResidueNamesSelection)
      340
      341     Status = True if cmd.count_atoms(SelectionCmd) else False
      342
      343     return Status
      344
      345 def _SetupAminoAcidResiduesSelectionCmd(MoleculeName, ChainName, Type):
      346     """Set up amino acids selection command for PyMOL. """
      347
      348     AminoAcidsSelection = "+".join(_GetAminoAcidResidueNames())
      349     NucleicAcidsSelection = "+".join(_GetNucleicAcidResidueNames())
      350
      351     if re.match("^Standard$", Type, re.I):
      352         SelectionCmd = "(%s and chain %s and polymer and (resn %s))" % (MoleculeName, ChainName, AminoAcidsSelection)
      353     elif re.match("^NonStandard$", Type, re.I):
      354         SelectionCmd = "(%s and chain %s and polymer and (not ((resn %s) or (resn %s))))" % (MoleculeName, ChainName, AminoAcidsSelection, NucleicAcidsSelection)
      355     else:
      356         # Any amino acid resiudes...
      357         SelectionCmd = "(%s and chain %s and polymer and (not (resn %s)))" % (MoleculeName, ChainName, NucleicAcidsSelection)
      358
      359     return SelectionCmd
      360
      361 def _GetAminoAcidResidueNames():
      362     """Get list of amino acid residue names.
      363     """
      364
      365     ResidueNames = ["ALA", "ARG", "ASN", "ASP", "CYS", "GLN", "GLU", "GLY", "HIS", "ILE", "LEU", "LYS", "MET", "PHE", "PRO", "SER", "THR", "TRP", "TYR", "VAL"]
      366
      367     return ResidueNames
      368
      369 def _GetNucleicAcidResidueNames():
      370     """Get list of nucleic acid residue names.
      371     """
      372
      373     ResidueNames = ["A", "G", "T", "U", "C", "DA", "DG", "DT", "DU", "DC"]
      374
      375     return ResidueNames
      376
      377 def GetPolymerResiduesInfo(MoleculeName, ChainName):
      378     """Get information for residues present in a chain of a  molecule.
      379     Chains are identified using PyMOL 'polymer' selection.
      380
      381     Arguments:
      382         MoleculeName (str): Name of a PyMOL molecule object.
      383         ChainName (str): Name of a chain in a molecule.
      384
      385     Returns:
      386         dict: A dictionary containing list of residue names and dictionaries of
      387             residue numbers and residue count for each residue. Names of
      388             residues in the dictionary are not sorted.
      389
      390     Examples:
      391
      392         ResiduesInfo = GetPolymerResiduesInfo(MolName, ChainName)
      393         for ResName in ResiduesInfo["ResNames"]:
      394             ResCount = ResiduesInfo["ResCount"][ResName]
      395             ResNums = ResiduesInfo["ResNum"][ResName]
      396             MiscUtil.PrintInfo("ResName: %s; ResCount: %s; ResNums: %s" %
      397                 (ResName, ResCount, ResNums))
      398
      399     """
      400     if not (len(MoleculeName) and len(ChainName)):
      401         return None
      402
      403     SelectionCmd = "%s and chain %s and polymer" % (MoleculeName, ChainName)
      404     ResiduesInfoMap = _GetSelectionResiduesInfo(SelectionCmd)
      405
      406     return ResiduesInfoMap
      407
      408 def GetAminoAcidResiduesInfo(MoleculeName, ChainName, Type = "Standard"):
      409     """Get information for amino acid residues present in a chain of a
      410     molecule. Chains are identified using PyMOL 'polymer' selection.
      411     Nonstandard amino acid residues correspond to all residues other than
      412     the standard amino acids and nucleic acids. Any amino acid residues cover
      413     all residues other than the standard nucleic acids.
      414
      415     Arguments:
      416         MoleculeName (str): Name of a PyMOL molecule object.
      417         ChainName (str): Name of a chain in a molecule.
      418         Type (str): Types of amino acids: Standard, NonStandard, Any
      419
      420     Returns:
      421         dict: A dictionary containing list of residue names and dictionaries of
      422             residue numbers and residue count for each residue. Names of
      423             residues in the dictionary are not sorted.
      424
      425     Examples:
      426
      427         ResiduesInfo = GetPolymerResiduesInfo(MolName, ChainName)
      428         for ResName in ResiduesInfo["ResNames"]:
      429             ResCount = ResiduesInfo["ResCount"][ResName]
      430             ResNums = ResiduesInfo["ResNum"][ResName]
      431             MiscUtil.PrintInfo("ResName: %s; ResCount: %s; ResNums: %s" %
      432                 (ResName, ResCount, ResNums))
      433
      434     """
      435
      436     if not (len(MoleculeName) and len(ChainName)):
      437         return None
      438
      439     if not re.match("^(Standard|NonStandard|Any)$", Type, re.I):
      440         MiscUtil.PrintError("PyMOLUtil.GetAminoAcidResiduesInfo: Invalid amino acid type: %s" % Type)
      441
      442     SelectionCmd = _SetupAminoAcidResiduesSelectionCmd(MoleculeName, ChainName, Type)
      443     ResiduesInfoMap = _GetSelectionResiduesInfo(SelectionCmd)
      444
      445     return ResiduesInfoMap
      446
      447 def GetNucleicAcidResiduesInfo(MoleculeName, ChainName):
      448     """Get information for nucleic acid residues present in a chain of
      449     a  molecule. Chains are identified using PyMOL 'polymer' selection.
      450
      451     Arguments:
      452         MoleculeName (str): Name of a PyMOL molecule object.
      453         ChainName (str): Name of a chain in a molecule.
      454
      455     Returns:
      456         dict: A dictionary containing list of residue names and dictionaries of
      457             residue numbers and residue count for each residue. Names of
      458             residues in the dictionary are not sorted.
      459
      460     Examples:
      461
      462         ResiduesInfo = GetPolymerResiduesInfo(MolName, ChainName)
      463         for ResName in ResiduesInfo["ResNames"]:
      464             ResCount = ResiduesInfo["ResCount"][ResName]
      465             ResNums = ResiduesInfo["ResNum"][ResName]
      466             MiscUtil.PrintInfo("ResName: %s; ResCount: %s; ResNums: %s" %
      467                 (ResName, ResCount, ResNums))
      468
      469     """
      470
      471     if not (len(MoleculeName) and len(ChainName)):
      472         return None
      473
      474     ResidueNames = _GetNucleicAcidResidueNames()
      475
      476     ResidueNamesSelection = "+".join(ResidueNames)
      477     SelectionCmd = "(%s and chain %s and polymer and (resn %s))" % (MoleculeName, ChainName, ResidueNamesSelection)
      478
      479     ResiduesInfoMap = _GetSelectionResiduesInfo(SelectionCmd)
      480
      481     return ResiduesInfoMap
      482
      483 def GetSolventResiduesInfo(MoleculeName, ChainName):
      484     """Get information for solvent residues present in a chain of a  molecule.
      485     Solvents are identified using PyMOL 'solvent' selection.
      486
      487     Arguments:
      488         MoleculeName (str): Name of a PyMOL molecule object.
      489         ChainName (str): Name of a chain in a molecule.
      490
      491     Returns:
      492         dict: A dictionary containing list of residue names and dictionaries of
      493             residue numbers and residue count for each residue. Names of
      494             residues in the dictionary are not sorted.
      495
      496     Examples:
      497
      498         ResiduesInfo = GetSolventResiduesInfo(MolName, ChainName)
      499         for ResName in ResiduesInfo["ResNames"]:
      500             ResCount = ResiduesInfo["ResCount"][ResName]
      501             ResNums = ResiduesInfo["ResNum"][ResName]
      502             MiscUtil.PrintInfo("ResName: %s; ResCount: %s; ResNums: %s" %
      503                 (ResName, ResCount, ResNums))
      504
      505     """
      506     if not (len(MoleculeName) and len(ChainName)):
      507         return None
      508
      509     SelectionCmd = "%s and chain %s and solvent" % (MoleculeName, ChainName)
      510     ResiduesInfoMap = _GetSelectionResiduesInfo(SelectionCmd)
      511
      512     return ResiduesInfoMap
      513
      514 def GetInorganicResiduesInfo(MoleculeName, ChainName):
      515     """Get information for inorganic residues present in a chain of a  molecule.
      516     Inorganic residues are identified using PyMOL 'inorganic' selection.
      517
      518     Arguments:
      519         MoleculeName (str): Name of a PyMOL molecule object.
      520         ChainName (str): Name of a chain in a molecule.
      521
      522     Returns:
      523         dict: A dictionary containing list of residue names and dictionaries of
      524             residue numbers and residue count for each residue. Names of
      525             residues in the dictionary are not sorted.
      526
      527     Examples:
      528
      529         ResiduesInfo = GetInorganicResiduesInfo(MolName, ChainName)
      530         for ResName in ResiduesInfo["ResNames"]:
      531             ResCount = ResiduesInfo["ResCount"][ResName]
      532             ResNums = ResiduesInfo["ResNum"][ResName]
      533             MiscUtil.PrintInfo("ResName: %s; ResCount: %s; ResNums: %s" %
      534                 (ResName, ResCount, ResNums))
      535
      536     """
      537     if not (len(MoleculeName) and len(ChainName)):
      538         return None
      539
      540     SelectionCmd = "%s and chain %s and inorganic" % (MoleculeName, ChainName)
      541     ResiduesInfoMap = _GetSelectionResiduesInfo(SelectionCmd)
      542
      543     return ResiduesInfoMap
      544
      545 def GetLigandResiduesInfo(MoleculeName, ChainName):
      546     """Get information for ligand residues present in a chain of a  molecule.
      547     Ligands are identified using PyMOL 'organic' selection.
      548
      549     Arguments:
      550         MoleculeName (str): Name of a PyMOL molecule object.
      551         ChainName (str): Name of a chain in a molecule.
      552
      553     Returns:
      554         dict: A dictionary containing list of residue names and dictionaries of
      555             residue numbers and residue count for each residue. Names of
      556             residues in the dictionary are not sorted.
      557
      558     Examples:
      559
      560         ResiduesInfo = GetLigandResiduesInfo(MolName, ChainName)
      561         for ResName in ResiduesInfo["ResNames"]:
      562             ResCount = ResiduesInfo["ResCount"][ResName]
      563             ResNums = ResiduesInfo["ResNum"][ResName]
      564             MiscUtil.PrintInfo("ResName: %s; ResCount: %s; ResNums: %s" %
      565                 (ResName, ResCount, ResNums))
      566
      567     """
      568     if not (len(MoleculeName) and len(ChainName)):
      569         return None
      570
      571     SelectionCmd = "%s and chain %s and organic" % (MoleculeName, ChainName)
      572     ResiduesInfoMap = _GetSelectionResiduesInfo(SelectionCmd)
      573
      574     return ResiduesInfoMap
      575
      576 def GetPocketPolymerResiduesInfo(MoleculeName, ChainName, LigandResName, LigandResNum, PocketDistanceCutoff):
      577     """Get information for chain residues present in a pocket around a ligand
      578     in a molecule. Polymer residues are identified using negation of PyMOL
      579     selection operators 'organic', 'solvent', and 'inorganic'.
      580
      581     Arguments:
      582         MoleculeName (str): Name of a PyMOL molecule object.
      583         ChainName (str): Name of a chain in a molecule.
      584         LigandResName (str): Residue name of a ligand in a chain.
      585         LigandResNum (str): Residue number of a ligand in a chain.
      586         PocketDistanceCutoff (float): Distance around ligand to identify pocket
      587             residues.
      588
      589     Returns:
      590         dict: A dictionary containing list of residue names and dictionaries of
      591             residue numbers and residue count for each residue. Names of
      592             residues in the dictionary are not sorted.
      593
      594     Examples:
      595
      596         ResiduesInfo = GetPocketPolymerResiduesInfo(MolName, ChainName)
      597         for ResName in ResiduesInfo["ResNames"]:
      598             ResCount = ResiduesInfo["ResCount"][ResName]
      599             ResNums = ResiduesInfo["ResNum"][ResName]
      600             MiscUtil.PrintInfo("ResName: %s; ResCount: %s; ResNums: %s" %
      601                 (ResName, ResCount, ResNums))
      602
      603     """
      604     if not (len(MoleculeName) and len(ChainName) and len(LigandResName) and len(LigandResNum)):
      605         return None
      606
      607     LigandSelection = "%s and chain %s and organic and resn %s and resi %s" % (MoleculeName, ChainName, LigandResName, LigandResNum)
      608     MoleculeSelection = "%s and chain %s" % (MoleculeName, ChainName)
      609     SelectionCmd = "((byresidue (%s) within %.1f of (%s))  and (not solvent) and (not inorganic) and (not organic))" % (MoleculeSelection, PocketDistanceCutoff, LigandSelection)
      610
      611     ResiduesInfoMap = _GetSelectionResiduesInfo(SelectionCmd)
      612
      613     return ResiduesInfoMap
      614
      615 def GetPocketSolventResiduesInfo(MoleculeName, ChainName, LigandResName, LigandResNum, PocketDistanceCutoff):
      616     """Get information for solvent residues present in a pocket around a ligand
      617     in a molecule. Solvent residues are identified using PyMOL 'solvent'
      618     selection.
      619
      620     Arguments:
      621         MoleculeName (str): Name of a PyMOL molecule object.
      622         ChainName (str): Name of a chain in a molecule.
      623         LigandResName (str): Residue name of a ligand in a chain.
      624         LigandResNum (str): Residue number of a ligand in a chain.
      625         PocketDistanceCutoff (float): Distance around ligand to identify pocket
      626             residues.
      627
      628     Returns:
      629         dict: A dictionary containing list of residue names and dictionaries of
      630             residue numbers and residue count for each residue. Names of
      631             residues in the dictionary are not sorted.
      632
      633     Examples:
      634
      635         ResiduesInfo = GetPocketSolventResiduesInfo(MolName, ChainName)
      636         for ResName in ResiduesInfo["ResNames"]:
      637             ResCount = ResiduesInfo["ResCount"][ResName]
      638             ResNums = ResiduesInfo["ResNum"][ResName]
      639             MiscUtil.PrintInfo("ResName: %s; ResCount: %s; ResNums: %s" %
      640                 (ResName, ResCount, ResNums))
      641
      642     """
      643     if not (len(MoleculeName) and len(ChainName) and len(LigandResName) and len(LigandResNum)):
      644         return None
      645
      646     LigandSelection = "%s and chain %s and organic and resn %s and resi %s" % (MoleculeName, ChainName, LigandResName, LigandResNum)
      647     MoleculeSelection = "%s and chain %s" % (MoleculeName, ChainName)
      648     SelectionCmd = "((byresidue (%s) within %.1f of (%s))  and solvent)" % (MoleculeSelection, PocketDistanceCutoff, LigandSelection)
      649
      650     ResiduesInfoMap = _GetSelectionResiduesInfo(SelectionCmd)
      651
      652     return ResiduesInfoMap
      653
      654 def GetPocketInorganicResiduesInfo(MoleculeName, ChainName, LigandResName, LigandResNum, PocketDistanceCutoff):
      655     """Get information for inorganic residues present in a pocket around a
      656     ligand in a molecule. Inorganic residues are identified using PyMOL
      657     'inorganic' selection.
      658
      659     Arguments:
      660         MoleculeName (str): Name of a PyMOL molecule object.
      661         ChainName (str): Name of a chain in a molecule.
      662         LigandResName (str): Residue name of a ligand in a chain.
      663         LigandResNum (str): Residue number of a ligand in a chain.
      664         PocketDistanceCutoff (float): Distance around a ligand to identify
      665             pocket residues.
      666
      667     Returns:
      668         dict: A dictionary containing list of residue names and dictionaries of
      669             residue numbers and residue count for each residue. Names of
      670             residues in the dictionary are not sorted.
      671
      672     Examples:
      673
      674         ResiduesInfo = GetPocketInorganicResiduesInfo(MolName, ChainName)
      675         for ResName in ResiduesInfo["ResNames"]:
      676             ResCount = ResiduesInfo["ResCount"][ResName]
      677             ResNums = ResiduesInfo["ResNum"][ResName]
      678             MiscUtil.PrintInfo("ResName: %s; ResCount: %s; ResNums: %s" %
      679                 (ResName, ResCount, ResNums))
      680
      681     """
      682     if not (len(MoleculeName) and len(ChainName) and len(LigandResName) and len(LigandResNum)):
      683         return None
      684
      685     LigandSelection = "%s and chain %s and organic and resn %s and resi %s" % (MoleculeName, ChainName, LigandResName, LigandResNum)
      686     MoleculeSelection = "%s and chain %s" % (MoleculeName, ChainName)
      687     SelectionCmd = "((byresidue (%s) within %.1f of (%s))  and inorganic)" % (MoleculeSelection, PocketDistanceCutoff, LigandSelection)
      688
      689     ResiduesInfoMap = _GetSelectionResiduesInfo(SelectionCmd)
      690
      691     return ResiduesInfoMap
      692
      693 def _GetSelectionResiduesInfo(SelectionCmd):
      694     """Get residue names and count information for a selection. """
      695
      696     # Retrieve atoms...
      697     stored.SelectionInfo = []
      698     cmd.iterate(SelectionCmd, "stored.SelectionInfo.append([resi, resn])")
      699
      700     # Retrieve residues...
      701     SelectionInfoMap = {}
      702     SelectionInfoMap["ResNames"] = []
      703     SelectionInfoMap["ResNum"] = {}
      704     SelectionInfoMap["ResCount"] = {}
      705
      706     PreviousResNum = 0
      707     for ResNum, ResName in stored.SelectionInfo:
      708         if ResName in SelectionInfoMap["ResNames"]:
      709             if ResNum != PreviousResNum:
      710                 # Same residue name but different residue number
      711                 SelectionInfoMap["ResNum"][ResName].append(ResNum)
      712                 PreviousResNum = ResNum
      713
      714                 SelectionInfoMap["ResCount"][ResName] += 1
      715         else:
      716             SelectionInfoMap["ResNames"].append(ResName)
      717
      718             SelectionInfoMap["ResNum"][ResName] = []
      719             SelectionInfoMap["ResNum"][ResName].append(ResNum)
      720             PreviousResNum = ResNum
      721
      722             SelectionInfoMap["ResCount"][ResName] = 1
      723
      724     return SelectionInfoMap
      725
      726 def ProcessChainsAndLigandsOptionsInfo(ChainsAndLigandsInfo, ChainsOptionName, ChainsOptionValue, LigandsOptionName = None, LigandsOptionValue = None):
      727     """Process specified chain and ligand IDs using command line options.
      728
      729     Arguments:
      730         ChainsAndLigandsInfo (dict): A dictionary containing information
      731             existing chains and ligands.
      732         ChainsOptionName (str): Name of command line chains option.
      733         ChainsOptionValue (str): Value for command line chains option.
      734         LigandsOptionName (str): Name of command line ligands option.
      735         LigandsOptionValue (str): Value for command line ligands option.
      736
      737     Returns:
      738         dict: A dictionary containing list of chain identifiers and dictionaries
      739             of chains containing lists of ligand names for each chain.
      740
      741     Examples:
      742
      743         ChainsAndLigandsInfo = ProcessChainsAndLigandsOptionsInfo(Infile,
      744             MolName)
      745         for ChainID in ChainsAndLigandsInfo["ChainIDs"]:
      746             for LigandID in ChainsAndLigandsInfo["LigandIDs"][ChainID]:
      747                 MiscUtil.PrintInfo("ChainID: %s; LigandID: %s" % (ChainID,
      748                     LigandID))
      749
      750     """
      751     SpecifiedChainsAndLigandsInfo = {}
      752     SpecifiedChainsAndLigandsInfo["ChainIDs"] = []
      753     SpecifiedChainsAndLigandsInfo["LigandIDs"] = {}
      754
      755     if ChainsOptionValue is None:
      756         return SpecifiedChainsAndLigandsInfo
      757
      758     _ProcessChainIDs(ChainsAndLigandsInfo, SpecifiedChainsAndLigandsInfo, ChainsOptionName, ChainsOptionValue)
      759
      760     if LigandsOptionValue is None:
      761         return SpecifiedChainsAndLigandsInfo
      762
      763     _ProcessLigandIDs(ChainsAndLigandsInfo, SpecifiedChainsAndLigandsInfo, LigandsOptionName, LigandsOptionValue)
      764
      765     return SpecifiedChainsAndLigandsInfo
      766
      767 def _ProcessChainIDs(ChainsAndLigandsInfo, SpecifiedChainsAndLigandsInfo, ChainsOptionName, ChainsOptionValue):
      768     """Process chain IDs"""
      769
      770     MiscUtil.PrintInfo("Processing chain IDs...")
      771
      772     if re.match("^All$", ChainsOptionValue, re.I):
      773         SpecifiedChainsAndLigandsInfo["ChainIDs"] = ChainsAndLigandsInfo["ChainIDs"]
      774         return
      775     elif re.match("^(First|Auto)$", ChainsOptionValue, re.I):
      776         FirstChainID = ChainsAndLigandsInfo["ChainIDs"][0] if (len(ChainsAndLigandsInfo["ChainIDs"])) else None
      777         if FirstChainID is not None:
      778             SpecifiedChainsAndLigandsInfo["ChainIDs"].append(FirstChainID)
      779         return
      780
      781     ChainIDs = re.sub(" ", "", ChainsOptionValue)
      782     if not ChainIDs:
      783         MiscUtil.PrintError("No valid value specified using \"%s\" option." % ChainsOptionName)
      784
      785     ChainIDsList = ChainsAndLigandsInfo["ChainIDs"]
      786     SpecifiedChainIDsList = []
      787
      788     ChainIDsWords = ChainIDs.split(",")
      789     for ChainID in ChainIDsWords:
      790         if not ChainID in ChainIDsList:
      791             MiscUtil.PrintWarning("The chain ID, %s, specified using \"%s\" option is not valid. It'll be ignored. Valid chain IDs: %s" % (ChainID, ChainsOptionName, ", ".join(ChainIDsList)))
      792             continue
      793         if ChainID in SpecifiedChainIDsList:
      794             MiscUtil.PrintWarning("The chain ID, %s, has already been specified using \"%s\" option. It'll be ignored." % (ChainID, ChainsOptionName))
      795             continue
      796         SpecifiedChainIDsList.append(ChainID)
      797
      798     if not len(SpecifiedChainIDsList):
      799         MiscUtil.PrintError("No valid chain IDs \"%s\"  specified using \"%s\" option." % (ChainsOptionValue, ChainsOptionName))
      800
      801     SpecifiedChainsAndLigandsInfo["ChainIDs"] = SpecifiedChainIDsList
      802
      803 def _ProcessLigandIDs(ChainsAndLigandsInfo, SpecifiedChainsAndLigandsInfo, LigandsOptionName, LigandsOptionValue):
      804     """Process ligand IDs"""
      805
      806     MiscUtil.PrintInfo("Processing ligand IDs...")
      807
      808     # Intialize ligand IDs...
      809     for ChainID in SpecifiedChainsAndLigandsInfo["ChainIDs"] :
      810         SpecifiedChainsAndLigandsInfo["LigandIDs"][ChainID] = []
      811
      812     if re.match("^All$", LigandsOptionValue, re.I):
      813         for ChainID in SpecifiedChainsAndLigandsInfo["ChainIDs"] :
      814             SpecifiedChainsAndLigandsInfo["LigandIDs"][ChainID] = ChainsAndLigandsInfo["LigandIDs"][ChainID]
      815         return
      816     elif re.match("^(Largest|Auto)$", LigandsOptionValue, re.I):
      817         # Setup largest ligand ID for each chain...
      818         for ChainID in SpecifiedChainsAndLigandsInfo["ChainIDs"] :
      819             LargestLigandID = ChainsAndLigandsInfo["LigandIDs"][ChainID][0] if (len(ChainsAndLigandsInfo["LigandIDs"][ChainID])) else None
      820             if LargestLigandID is not None:
      821                 SpecifiedChainsAndLigandsInfo["LigandIDs"][ChainID].append(LargestLigandID)
      822         return
      823
      824     LigandIDs = re.sub(" ", "", LigandsOptionValue)
      825     if not LigandIDs:
      826         MiscUtil.PrintError("No valid value specified using \"%s\" option." % LigandsOptionName)
      827
      828     LigandIDsWords = LigandIDs.split(",")
      829
      830     for ChainID in SpecifiedChainsAndLigandsInfo["ChainIDs"]:
      831         LigandIDsList = ChainsAndLigandsInfo["LigandIDs"][ChainID]
      832         SpecifiedLigandIDsList = []
      833
      834         for LigandID in LigandIDsWords:
      835             if not LigandID in LigandIDsList:
      836                 LigandIDsListNames = ",".join(LigandIDsList) if len(LigandIDsList) else "None"
      837                 MiscUtil.PrintWarning("The ligand ID, %s, specified using \"%s\" option is not valid for chain, %s. It'll be ignored. Valid ligand IDs: %s" % (LigandID, LigandsOptionName, ChainID, LigandIDsListNames))
      838                 continue
      839             if LigandID in SpecifiedLigandIDsList:
      840                 MiscUtil.PrintWarning("The ligand ID, %s, has already been specified using \"%s\" option. It'll be ignored." % (LigandID, LigandsOptionName))
      841                 continue
      842             SpecifiedLigandIDsList.append(LigandID)
      843
      844         if not len(SpecifiedLigandIDsList):
      845             MiscUtil.PrintWarning("No valid ligand IDs \"%s\" specified using \"%s\" option for chain ID, %s." % (LigandsOptionValue, LigandsOptionName, ChainID))
      846
      847         SpecifiedChainsAndLigandsInfo["LigandIDs"][ChainID] = SpecifiedLigandIDsList
      848
      849 def CalculateCenterOfMass(Selection = "all", Quiet = 0):
      850     """Calculate center of mass for a selection.
      851
      852     Arguments:
      853         Selection (str): A PyMOL selection.
      854         Quiet (int): Print information.
      855
      856     Returns:
      857         list: X, Y, Z coordinates for center of mass.
      858
      859     """
      860     MassTotal = 0.0
      861     X, Y, Z = [0.0, 0.0, 0.0]
      862
      863     Atoms = cmd.get_model(Selection)
      864     for Atom in Atoms.atom:
      865         Mass = Atom.get_mass()
      866         MassTotal += Mass
      867
      868         X += Atom.coord[0] * Mass
      869         Y += Atom.coord[1] * Mass
      870         Z += Atom.coord[2] * Mass
      871
      872     XCOM = X/MassTotal
      873     YCOM = Y/MassTotal
      874     ZCOM = Z/MassTotal
      875
      876     if not Quiet:
      877         MiscUtil.PrintInfo("PyMOLUtil.CalculateCenterOfMass: %f, %f, %f" % (XCOM, YCOM, ZCOM))
      878
      879     return [XCOM, YCOM, ZCOM]
      880
      881 def ConvertFileFormat(Infile, Outfile, Reinitialize = True, OutputFeedback = True):
      882     """Convert infile to outfile by automatically detecting their formats
      883     from the file extensions.
      884
      885     The formats of both input and output files must be a valid format supported
      886     by PyMOL.
      887
      888     Arguments:
      889         Infile (str): Name of input file.
      890         Outfile (str): Name of outfile file.
      891         Reinitialize (bool): Reinitialize PyMOL before loading input file.
      892         OutputFeedback (bool): Control output feedback.
      893
      894     """
      895
      896     if not os.path.exists(Infile):
      897         MiscUtil.PrintWarning("The input file, %s, doesn't exists.%s..." % (Infile))
      898
      899     if Reinitialize:
      900         cmd.reinitialize()
      901
      902     if not OutputFeedback:
      903         # Turn off output feedback...
      904         MiscUtil.PrintInfo("Disabling output feedback for PyMOL...")
      905         cmd.feedback("disable", "all", "output")
      906
      907     FileDir, FileName, FileExt = MiscUtil.ParseFileName(Infile)
      908     MolName = FileName
      909
      910     cmd.load(Infile, MolName)
      911     cmd.save(Outfile, MolName)
      912     cmd.delete(MolName)
      913
      914     if not OutputFeedback:
      915         # Turn it back on...
      916         MiscUtil.PrintInfo("\nEnabling output feedback for PyMOL...")
      917         cmd.feedback("enable", "all", "output")
      918
      919 def ConvertPMLFileToPSEFile(PMLFile, PSEFile, Reinitialize = True, OutputFeedback = True):
      920     """Convert PML file to PME file.
      921
      922     Arguments:
      923         PMLFile (str): Name of PML file.
      924         PSEFile (str): Name of PSE file.
      925         Reinitialize (bool): Reinitialize PyMOL before loading PML file.
      926         OutputFeedback (bool): Control output feedback.
      927
      928     """
      929
      930     if not os.path.exists(PMLFile):
      931         MiscUtil.PrintWarning("The PML file, %s, doesn't exists.%s..." % (PMLFile))
      932
      933     if Reinitialize:
      934         cmd.reinitialize()
      935
      936     if not OutputFeedback:
      937         # Turn off output feedback...
      938         MiscUtil.PrintInfo("Disabling output feedback for PyMOL...")
      939         cmd.feedback("disable", "all", "output")
      940
      941     cmd.do("@%s" % PMLFile)
      942     cmd.save(PSEFile)
      943
      944     if not OutputFeedback:
      945         # Turn it back on...
      946         MiscUtil.PrintInfo("\nEnabling output feedback for PyMOL...")
      947         cmd.feedback("enable", "all", "output")
      948
      949 def SetupPMLHeaderInfo(ScriptName = None, IncludeLocalPython = True):
      950     """Setup header information for generating PML files. The local Python
      951     functions are optionally embedded in the header information for their
      952     use in PML files.
      953
      954     Arguments:
      955         ScriptName (str): Name of script calling the function.
      956         IncludeLocalPython (bool): Include local Python functions.
      957
      958     Returns:
      959         str: Text containing header information for generating PML files.
      960
      961     """
      962     if ScriptName is None:
      963         HeaderInfo = """\
      964 #
      965 # This file is automatically generated by a script available in MayaChemTools.
      966 #
      967 cmd.reinitialize()"""
      968     else:
      969         HeaderInfo = """\
      970 #
      971 # This file is automatically generated by the following PyMOL script available in
      972 # MayaChemTools: %s
      973 #
      974 cmd.reinitialize() """ % (ScriptName)
      975
      976     if IncludeLocalPython:
      977         PMLForLocalPython = _SetupPMLForLocalPython()
      978         HeaderInfo = "%s\n\n%s" % (HeaderInfo, PMLForLocalPython)
      979
      980     return HeaderInfo
      981
      982 def _SetupPMLForLocalPython():
      983     """Setup local Python functions for PML file.
      984     """
      985
      986     PMLForPython = """\
      987 ""
      988 "Setting up local Python functions  for PML script..."
      989 ""
      990 python
      991
      992 from __future__ import print_function
      993 import re
      994
      995 def ColorByHydrophobicity(Selection, ColorPalette = "RedToWhite"):
      996     \"""Color by hydrophobicity using hydrophobic values for amino acid
      997     residues corresponding to the Eisenberg hydrophobicity scale.
      998
      999     Possible values for ColorPalette: RedToWhite or WhiteToGreen from most
     1000     hydrophobic amino acid to least hydrophobic.
     1001
     1002     The colors values for amino acids are taken from color_h script avaiable
     1003     as part of the Script Library at PyMOL Wiki.
     1004
     1005     \"""
     1006
     1007     if not re.match("^(RedToWhite|WhiteToGreen)$", ColorPalette, re.I):
     1008         print("Invalid ColorPalette value: %s. Valid values: RedToWhite, WhiteToGreen" % ColorPalette)
     1009
     1010     ResColors = {}
     1011     ColorType = ""
     1012
     1013     if re.match("^WhiteToGreen$", ColorPalette, re.I):
     1014         ColorType = "H2"
     1015         ResColors = {"ile" : [0.938,1,0.938], "phe" : [0.891,1,0.891], "val" : [0.844,1,0.844], "leu" : [0.793,1,0.793], "trp" : [0.746,1,0.746], "met" : [0.699,1,0.699], "ala" : [0.652,1,0.652], "gly" : [0.606,1,0.606], "cys" : [0.555,1,0.555], "tyr" : [0.508,1,0.508], "pro" : [0.461,1,0.461], "thr" : [0.414,1,0.414], "ser" : [0.363,1,0.363], "his" : [0.316,1,0.316], "glu" : [0.27,1,0.27], "asn" : [0.223,1,0.223], "gln" : [0.176,1,0.176], "asp" : [0.125,1,0.125], "lys" : [0.078,1,0.078], "arg" : [0.031,1,0.031]}
     1016     else:
     1017         ColorType = "H1"
     1018         ResColors = {"ile" : [0.996,0.062,0.062], "phe" : [0.996,0.109,0.109], "val" : [0.992,0.156,0.156], "leu" : [0.992,0.207,0.207], "trp" : [0.992,0.254,0.254], "met" : [0.988,0.301,0.301], "ala" : [0.988,0.348,0.348], "gly" : [0.984,0.394,0.394], "cys" : [0.984,0.445,0.445], "tyr" : [0.984,0.492,0.492], "pro" : [0.980,0.539,0.539], "thr" : [0.980,0.586,0.586], "ser" : [0.980,0.637,0.637], "his" : [0.977,0.684,0.684], "glu" : [0.977,0.730,0.730], "asn" : [0.973,0.777,0.777], "gln" : [0.973,0.824,0.824], "asp" : [0.973,0.875,0.875], "lys" : [0.899,0.922,0.922], "arg" : [0.899,0.969,0.969]}
     1019
     1020     # Set up colors...
     1021     for ResName in ResColors:
     1022         ColorName = "color_%s_%s" % (ResName, ColorType)
     1023         cmd.set_color(ColorName, ResColors[ResName])
     1024
     1025         ResSelection = "(%s and resn %s*)" % (Selection, ResName)
     1026         cmd.color(ColorName, ResSelection)
     1027
     1028 cmd.extend("ColorByHydrophobicity", ColorByHydrophobicity)
     1029
     1030 def ColorAtomsByHydrophobicityAndCharge(Selection, HydrophobicAtomsColor = "yellow", NegativelyChargedAtomsColor = "red", PositivelyChargedAtomsColor = "blue", OtherAtomsColor = "gray90"):
     1031     \"""Color atoms in amino acids by their propensity to make hydrophobic and
     1032     charge interactions [REF 140].  The atom names in standard amino acid
     1033     residues are used to identify atom types as shown below:
     1034
     1035         Hydrophobic: C atoms not bound to N or O atoms
     1036         NegativelyCharged: Side chain O atoms in ASP and GLU
     1037         PositivelyCharged: Side chain N atoms in ARG and LYS
     1038         Others: Remaining atoms in polar and other residues
     1039
     1040     The following color scheme is used by default:
     1041
     1042         Hydrophobic: yellow
     1043         NegativelyCharged: red
     1044         PositivelyCharged: blue
     1045         Others: gray90
     1046
     1047     The  amino acid atom names to color specific atoms  are taken from YRB.py
     1048     script [ REF 140]. The color values may also be specified as comma delimited
     1049     RGB triplets. For example: HydrophobicAtomsColor = "0.950 0.78 0.0",
     1050     NegativelyChargedAtomsColor = "1.0 0.4 0.4", PositivelyChargedAtomsColor
     1051     = "0.2 0.5 0.8", OtherAtomsColor = "0.95 0.95 0.95"
     1052
     1053     \"""
     1054
     1055     # Process colors...
     1056     Colors = {"HydrophobicAtomsColor": HydrophobicAtomsColor, "NegativelyChargedAtomsColor": NegativelyChargedAtomsColor, "PositivelyChargedAtomsColor": PositivelyChargedAtomsColor, "OtherAtomsColor": OtherAtomsColor}
     1057     ColorsRGB = {}
     1058     for ColorKey, ColorValue in Colors.items():
     1059         if re.search(" ", ColorValue):
     1060             ColorRGB = ColorValue.split(" ")
     1061         else:
     1062             ColorRGB = cmd.get_color_tuple(cmd.get_color_index(ColorValue))
     1063         ColorsRGB[ColorKey] = ColorRGB
     1064
     1065     # Set up colors...
     1066     for ColorKey, ColorValue in ColorsRGB.items():
     1067         cmd.set_color(ColorKey, ColorValue)
     1068
     1069     #  Set up colors for atom names across all resiudes...
     1070     AtomColors = {"OtherAtomsColor": "N,C,CA,O", "HydrophobicAtomsColor": "CB"}
     1071
     1072     #  Set up colors for atom names across specific resiudes...
     1073     ResAtomColors = {"arg" : {"HydrophobicAtomsColor": "CG", "PositivelyChargedAtomsColor": "NE,NH2,NH1", "OtherAtomsColor": "CD,CZ"}, "asn" : {"OtherAtomsColor": "CG,OD1,ND2"}, "asp" : {"NegativelyChargedAtomsColor": "OD2,OD1", "OtherAtomsColor": "CG"}, "cys" : {"OtherAtomsColor": "SG"}, "gln" : {"HydrophobicAtomsColor": "CG", "OtherAtomsColor": "CD,OE1,NE2"}, "glu" : {"HydrophobicAtomsColor": "CG", "NegativelyChargedAtomsColor": "OE1,OE2", "OtherAtomsColor": "CD"}, "his" : {"OtherAtomsColor": "CG,CD2,ND1,NE2,CE1"}, "ile" : {"HydrophobicAtomsColor": "CG1,CG2,CD1"}, "leu" : {"HydrophobicAtomsColor": "CG,CD1,CD2"}, "lys" : {"HydrophobicAtomsColor": "CG,CD", "PositivelyChargedAtomsColor": "NZ", "OtherAtomsColor": "CE"}, "met" : {"HydrophobicAtomsColor": "CG,CE", "OtherAtomsColor": "SD"}, "phe" : {"HydrophobicAtomsColor": "CG,CD1,CE1,CZ,CE2,CD2"}, "pro" : {"HydrophobicAtomsColor": "CG", "OtherAtomsColor": "CD"}, "ser" : {"OtherAtomsColor": "CB,OG"}, "thr" : {"HydrophobicAtomsColor": "CG2", "OtherAtomsColor": "CB,OG1"}, "trp" : {"HydrophobicAtomsColor": "CG,CD2,CZ2,CH2,CZ3,CE3", "OtherAtomsColor": "CD1,NE1,CE2"}, "tyr" : {"HydrophobicAtomsColor": "CG,CE1,CD1,CE2,CD2", "OtherAtomsColor": "CZ,OH"}, "val" : {"HydrophobicAtomsColor": "CG1,CG2"}}
     1074
     1075     #  Color atom names across all resiudes...
     1076     for ColorName in AtomColors:
     1077         AtomNames = AtomColors[ColorName]
     1078         AtomsSelection = "(%s and name %s)" % (Selection, AtomNames)
     1079         cmd.color(ColorName, AtomsSelection)
     1080
     1081     #  Color atom names across specific resiudes...
     1082     for ResName in ResAtomColors:
     1083         for ColorName in ResAtomColors[ResName]:
     1084             AtomNames = ResAtomColors[ResName][ColorName]
     1085             AtomsSelection = "(%s and resn %s and name %s)" % (Selection, ResName, AtomNames)
     1086             cmd.color(ColorName, AtomsSelection)
     1087
     1088 cmd.extend("ColorAtomsByHydrophobicityAndCharge", ColorAtomsByHydrophobicityAndCharge)
     1089
     1090 def CheckAndDeleteEmptyObjects(ObjectNames, ParentObjectName = None):
     1091     \"""Delete an empty objects along with optionally deleting their parent.
     1092
     1093     \"""
     1094
     1095     ObjectNamesList = ObjectNames.split(",")
     1096
     1097     AllObjectsEmpty = True
     1098     for ObjectName in ObjectNamesList:
     1099         ObjectName = ObjectName.strip()
     1100         if  cmd.count_atoms("(%s)" % ObjectName):
     1101             AllObjectsEmpty = False
     1102         else:
     1103             cmd.delete("%s" % ObjectName)
     1104
     1105     if AllObjectsEmpty and ParentObjectName is not None:
     1106         cmd.delete("%s" % ParentObjectName)
     1107
     1108 cmd.extend("CheckAndDeleteEmptyObjects", CheckAndDeleteEmptyObjects)
     1109
     1110 python end"""
     1111
     1112     return PMLForPython
     1113
     1114 def SetupPMLForEnableDisable(Name, Enable = True):
     1115     """Setup PML command for enabling or disabling display of a PyMOL object.
     1116
     1117     Arguments:
     1118         Name (str): Name of a PyMOL object.
     1119         Enable (bool): Display status.
     1120
     1121     Returns:
     1122         str: PML command for enabling or disabling display of an object.
     1123
     1124     """
     1125
     1126     if Enable:
     1127         PML = """cmd.enable("%s")""" % Name
     1128     else:
     1129         PML = """cmd.disable("%s")""" % Name
     1130
     1131     return PML
     1132
     1133 def SetupPMLForGroup(GroupName, GroupMembersList, Enable = None, Action = None):
     1134     """Setup PML commands for creating a group from a list of group members. The
     1135     display and open status of the group may be optionally set. The 'None' values
     1136     for Enable and Action imply usage of PyMOL defaults for the creation of group.
     1137
     1138     Arguments:
     1139         GroupName (str): Name of a PyMOL group.
     1140         GroupMembersList (list): List of group member names.
     1141         Enable (bool): Display status of group.
     1142         Action (str): Open or close status of group object.
     1143
     1144     Returns:
     1145         str: PML commands for creating a group object.
     1146
     1147     """
     1148
     1149     PMLCmds = []
     1150
     1151     GroupMembers = " ".join(GroupMembersList)
     1152     PMLCmds.append("""cmd.group("%s", "%s")""" % (GroupName, GroupMembers))
     1153
     1154     if Enable is not None:
     1155         if Enable:
     1156             PMLCmds.append("""cmd.enable("%s")""" % GroupName)
     1157         else:
     1158             PMLCmds.append("""cmd.disable("%s")""" % GroupName)
     1159
     1160     if Action is not None:
     1161         PMLCmds.append("""cmd.group("%s", action="%s")""" % (GroupName, Action))
     1162
     1163     PML = "\n".join(PMLCmds)
     1164
     1165     return PML
     1166
     1167 def SetupPMLForLigandView(Name, Selection, LigandResName, Enable = True):
     1168     """Setup PML commands for creating a ligand view corresponding to a ligand
     1169     present in a selection. The ligand is identified using organic selection
     1170     operator available in PyMOL in conjunction with the specified ligand ID.
     1171     The ligand is colored by atom types and displayed as 'sticks'.
     1172
     1173     Arguments:
     1174         Name (str): Name of a new PyMOL ligand object.
     1175         Selection (str): PyMOL selection containing ligand.
     1176         LigandResName (str): Ligand ID.
     1177         Enable (bool): Display status of ligand object.
     1178
     1179     Returns:
     1180         str: PML commands for a ligand view.
     1181
     1182     """
     1183
     1184     PMLCmds = []
     1185     PMLCmds.append("""cmd.create("%s", "((%s) and organic and (resn %s))")""" % (Name, Selection, LigandResName))
     1186     PMLCmds.append("""cmd.hide("everything", "%s")""" % (Name))
     1187     PMLCmds.append("""util.cbag("%s", _self = cmd)""" % (Name))
     1188     PMLCmds.append("""cmd.show("sticks", "%s")""" % (Name))
     1189     PMLCmds.append(SetupPMLForEnableDisable(Name, Enable))
     1190
     1191     PML = "\n".join(PMLCmds)
     1192
     1193     return PML
     1194
     1195 def SetupPMLForLigandPocketView(Name, Selection, LigandSelection, DistanceCutoff, Enable = True):
     1196     """Setup PML commands for creating a ligand binding pocket view
     1197     corresponding all residues present in a selection within a specified
     1198     distance from a ligand selection. The solvent and inorganic portions of
     1199     the selection are not included in the binding pocket. The pocket residues
     1200     are shown as 'lines'. The hydrogen atoms are not displayed.
     1201
     1202     Arguments:
     1203         Name (str): Name of a new PyMOL binding pocket object.
     1204         Selection (str): PyMOL selection containing binding pocket residues.
     1205         LigandSelection (str): PyMOL selection containing ligand.
     1206         DistanceCutoff (float): Distance cutoff from ligand for selecting
     1207             binding pockect residues.
     1208         Enable (bool): Display status of binding pocket object.
     1209
     1210     Returns:
     1211         str: PML commands for a ligand binding pocket view.
     1212
     1213     """
     1214
     1215     PMLCmds = []
     1216     PMLCmds.append("""cmd.create("%s", "((byresidue (%s) within %.1f of (%s)) and (not solvent) and (not inorganic) and (not organic))")""" % (Name, Selection, DistanceCutoff, LigandSelection))
     1217     PMLCmds.append("""cmd.hide("everything", "%s")""" % (Name))
     1218     PMLCmds.append("""cmd.show("lines", "(%s)")""" % (Name))
     1219     PMLCmds.append("""cmd.hide("(%s and hydro)")""" % (Name))
     1220     PMLCmds.append(SetupPMLForEnableDisable(Name, Enable))
     1221
     1222     PML = "\n".join(PMLCmds)
     1223
     1224     return PML
     1225
     1226 def SetupPMLForLigandPocketSolventView(Name, Selection, LigandSelection, DistanceCutoff, Enable = True):
     1227     """Setup PML commands for creating a ligand binding pocket view
     1228     corresponding to only solvent residues present in a selection within a
     1229     specified distance from a ligand selection. The solvent pocket residues
     1230     are shown as 'lines' and 'nonbonded'.
     1231
     1232     Arguments:
     1233         Name (str): Name of a new PyMOL solvent binding pocket object.
     1234         Selection (str): PyMOL selection containing binding pocket residues.
     1235         LigandSelection (str): PyMOL selection containing ligand.
     1236         DistanceCutoff (float): Distance cutoff from ligand for selecting
     1237             binding pocket solvent residues.
     1238         Enable (bool): Display status of binding pocket object.
     1239
     1240     Returns:
     1241         str: PML commands for a ligand binding pocket view only showing solvent
     1242             residues.
     1243
     1244     """
     1245
     1246     PMLCmds = []
     1247     PMLCmds.append("""cmd.create("%s", "((byresidue (%s) within %.1f of (%s)) and solvent)")""" % (Name, Selection, DistanceCutoff, LigandSelection))
     1248     PMLCmds.append("""cmd.hide("everything", "%s")""" % (Name))
     1249     PMLCmds.append("""cmd.show("nonbonded", "%s")""" % (Name))
     1250     PMLCmds.append("""cmd.show("lines", "%s")""" % (Name))
     1251     PMLCmds.append(SetupPMLForEnableDisable(Name, Enable))
     1252
     1253     PML = "\n".join(PMLCmds)
     1254
     1255     return PML
     1256
     1257 def SetupPMLForLigandPocketInorganicView(Name, Selection, LigandSelection, DistanceCutoff, Enable = True):
     1258     """Setup PML commands for creating a ligand binding pocket view
     1259     corresponding to only inorganic residues present in a selection within a
     1260     specified distance from a ligand selection. The inorganic pocket residues
     1261     are shown as 'lines' and 'nonbonded'.
     1262
     1263     Arguments:
     1264         Name (str): Name of a new PyMOL solvent binding pocket object.
     1265         Selection (str): PyMOL selection containing binding pocket residues.
     1266         LigandSelection (str): PyMOL selection containing ligand.
     1267         DistanceCutoff (float): Distance cutoff from ligand for selecting
     1268             binding pocket inorganic residues.
     1269         Enable (bool): Display status of binding pocket object.
     1270
     1271     Returns:
     1272         str: PML commands for a ligand binding pocket view only showing inorganic
     1273             residues.
     1274
     1275     """
     1276
     1277     PMLCmds = []
     1278     PMLCmds.append("""cmd.create("%s", "((byresidue (%s) within %.1f of (%s)) and inorganic)")""" % (Name, Selection, DistanceCutoff, LigandSelection))
     1279     PMLCmds.append("""cmd.hide("everything", "%s")""" % (Name))
     1280     PMLCmds.append("""cmd.show("nonbonded", "%s")""" % (Name))
     1281     PMLCmds.append("""cmd.show("lines", "%s")""" % (Name))
     1282     PMLCmds.append(SetupPMLForEnableDisable(Name, Enable))
     1283
     1284     PML = "\n".join(PMLCmds)
     1285
     1286     return PML
     1287
     1288 def SetupPMLForPolarContactsView(Name, Selection1, Selection2, Enable = True, Color = "yellow"):
     1289     """Setup PML commands for creating polar contacts view between a pair of
     1290     selections. The polar contact view is generated using 'util.dist' command. The
     1291     distance labels are shown by default.
     1292
     1293     Arguments:
     1294         Name (str): Name of a new PyMOL polar contacts object.
     1295         Selection1 (str): First PyMOL selection.
     1296         Selection2 (str): Second PyMOL selection.
     1297         Enable (bool): Display status of polar contacts object.
     1298         Colot (str): Color for polar contact lines and labels.
     1299
     1300     Returns:
     1301         str: PML commands for polar contacts view between a pair of selections.
     1302
     1303     """
     1304
     1305     PMLCmds = []
     1306     PMLCmds.append("""cmd.dist("%s","(%s)","(%s)",quiet = 1, mode = 2, label = 1, reset = 1)""" % (Name, Selection1, Selection2))
     1307     PMLCmds.append("""util.color_deep("%s", "%s")""" % (Color, Name))
     1308     PMLCmds.append(SetupPMLForEnableDisable(Name, Enable))
     1309
     1310     PML = "\n".join(PMLCmds)
     1311
     1312     return PML
     1313
     1314 def SetupPMLForAlignment(Method, RefSelection, FitSelection):
     1315     """Setup PML commands for aligning a pair of selection using  a specified
     1316     alignment method.
     1317
     1318     Arguments:
     1319         Method (str): Alignment method. Possible values: align, cealign, super.
     1320         RefSelection (str): Name of reference selection which stays stationary.
     1321         FitSelection (str): Name of selection to align to reference selection.
     1322
     1323     Returns:
     1324         str: PML commands for aligning  a pair of selections.
     1325
     1326     """
     1327
     1328     PMLCmds = []
     1329     if re.match("^align$", Method, re.I):
     1330         PMLCmds.append("""cmd.align("(%s)", "(%s)")""" % (FitSelection, RefSelection))
     1331     elif re.match("^cealign$", Method, re.I):
     1332         PMLCmds.append("""cmd.cealign("(%s)", "(%s)")""" % (RefSelection, FitSelection))
     1333     elif re.match("^super$", Method, re.I):
     1334         PMLCmds.append("""cmd.super("(%s)", "(%s)")""" % (FitSelection, RefSelection))
     1335     else:
     1336         MiscUtil.PrintWarning("PyMOLUtil.SetupPMLForAlignment: Invalid method name: %s" % Method)
     1337
     1338     PML = "\n".join(PMLCmds)
     1339
     1340     return PML
     1341
     1342 def SetupPMLForBFactorPuttyView(Name, Selection, ColorPalette = "blue_white_red", Enable = True):
     1343     """Setup PML commands for creating a B factor putty view for a specified
     1344     selection. The B factor values must be available for the atoms. The atoms
     1345     are colored using a color spectrum corresponding to a specified color
     1346     palette. Any valid PyMOL color palette name may be used.
     1347
     1348     Arguments:
     1349         Name (str): Name of a new PyMOL B factor putty object.
     1350         Selection (str): Name of PyMOL selection.
     1351         ColorPalette (str): Name of color palette to use for color spectrum.
     1352         Enable (bool): Display status of B factor putty object.
     1353
     1354     Returns:
     1355         str: PML commands for B factor putty view.
     1356
     1357     """
     1358
     1359     PMLCmds = []
     1360     PMLCmds.append("""cmd.create("%s", "(%s)")""" % (Name, Selection))
     1361     PMLCmds.append("""cmd.hide("everything", "%s")""" % (Name))
     1362     PMLCmds.append("""cmd.spectrum("b", "%s", "(%s)")""" % (ColorPalette, Name))
     1363     PMLCmds.append("""cmd.show("cartoon", "%s")""" % (Name))
     1364     PMLCmds.append("""cmd.cartoon("putty", "%s")""" % (Name))
     1365     PMLCmds.append(SetupPMLForEnableDisable(Name, Enable))
     1366
     1367     PML = "\n".join(PMLCmds)
     1368
     1369     return PML
     1370
     1371 def SetupPMLForHydrophobicSurfaceView(Name, Selection, ColorPalette = "RedToWhite", Enable = True, DisplayAs = "cartoon"):
     1372     """Setup PML commands for creating a hydrophobic surface view for a specified
     1373     selection. The surfaces are colored using a specified color palette. This is only valid
     1374     for amino acids.
     1375
     1376     Arguments:
     1377         Name (str): Name of a new PyMOL hydrophobic surface object.
     1378         Selection (str): Name of PyMOL selection.
     1379         ColorPalette (str): Name of color palette to use for coloring surfaces.
     1380             Possible values: RedToWhite or WhiteToGreen for most hydrophobic
     1381             to least hydrophobic amino acids.
     1382         Enable (bool): Display status of surface object.
     1383         DisplayAs (str): Any additional valid display type such as lines,
     1384             sticks, ribbon, cartoon, or None.
     1385
     1386     Returns:
     1387         str: PML commands for hydrophobic surface view.
     1388
     1389     """
     1390
     1391     PMLCmds = _GetPMLCmdsForSurfaceView(Name, Selection, DisplayAs)
     1392     PMLCmds.append("""ColorByHydrophobicity("%s", "%s")""" % (Name, ColorPalette))
     1393     PMLCmds.append(SetupPMLForEnableDisable(Name, Enable))
     1394
     1395     PML = "\n".join(PMLCmds)
     1396
     1397     return PML
     1398
     1399 def SetupPMLForHydrophobicAndChargeSurfaceView(Name, Selection, HydrophobicAtomsColor = "yellow", NegativelyChargedAtomsColor = "red", PositivelyChargedAtomsColor = "blue", OtherAtomsColor = "gray90", Enable = True, DisplayAs = "cartoon"):
     1400     """Setup PML commands for creating a surface colored by hydrophobic and
     1401     charge [ REF 140] properties of atoms in amino acids. The atom names in
     1402     standard amino acid residues are used to identify atom types as shown below:
     1403
     1404     Hydrophobic: C atoms not bound to N or O atoms; NegativelyCharged: Side
     1405     chain O atoms in ASP and GLU; PositivelyCharged: Side chain N atoms in
     1406     ARG and LYS; Others: Remaining atoms in polar and other residues
     1407
     1408     The  amino acid atom names to color specific atoms  are taken from YRB.py
     1409     script [ REF 140]. The color values may also be specified as comma delimited
     1410     RGB triplets. For example: HydrophobicAtomsColor = "0.950 0.78 0.0",
     1411     NegativelyChargedAtomsColor = "1.0 0.4 0.4", PositivelyChargedAtomsColor
     1412     = "0.2 0.5 0.8", OtherAtomsColor = "0.95 0.95 0.95"
     1413
     1414     Arguments:
     1415         Name (str): Name of a new PyMOL hydrophobic surface object.
     1416         Selection (str): Name of PyMOL selection.
     1417         HydrophobicAtomsColor (str): Color name or space delimited RGB values
     1418         NegativelyChargedAtomsColor (str): Color name or space delimited RGB values
     1419         PositivelyChargedAtomsColor (str): Color name or space delimited RGB values
     1420         OtherAtomsColor (str): Color name or space delimited RGB values
     1421         Enable (bool): Display status of surface object.
     1422         DisplayAs (str): Any additional valid display type such as lines,
     1423             sticks, ribbon, cartoon, or None.
     1424
     1425     Returns:
     1426         str: PML commands for hydrophobic and charge surface view.
     1427
     1428     """
     1429
     1430     PMLCmds = _GetPMLCmdsForSurfaceView(Name, Selection, DisplayAs)
     1431     PMLCmds.append("""ColorAtomsByHydrophobicityAndCharge("%s", "%s", "%s", "%s", "%s")""" % (Name, HydrophobicAtomsColor, NegativelyChargedAtomsColor, PositivelyChargedAtomsColor, OtherAtomsColor))
     1432     PMLCmds.append(SetupPMLForEnableDisable(Name, Enable))
     1433
     1434     PML = "\n".join(PMLCmds)
     1435
     1436     return PML
     1437
     1438 def SetupPMLForSurfaceView(Name, Selection, Enable = True, DisplayAs = "cartoon"):
     1439     """Setup PML commands for creating a molecular surface view for a specified
     1440     selection.
     1441
     1442     Arguments:
     1443         Name (str): Name of a new PyMOL molecular surface object.
     1444         Selection (str): Name of PyMOL selection.
     1445         Enable (bool): Display status of surface object.
     1446         DisplayAs (str): Any additional valid display type such as lines,
     1447             sticks, ribbon, cartoon, or None.
     1448
     1449     Returns:
     1450         str: PML commands for molecular surface view.
     1451
     1452     """
     1453
     1454     PMLCmds = _GetPMLCmdsForSurfaceView(Name, Selection, DisplayAs)
     1455     PMLCmds.append(SetupPMLForEnableDisable(Name, Enable))
     1456
     1457     PML = "\n".join(PMLCmds)
     1458
     1459     return PML
     1460
     1461 def _GetPMLCmdsForSurfaceView(Name, Selection, DisplayAs = "cartoon"):
     1462     """Setup PML command for surface view."""
     1463
     1464     PMLCmds = []
     1465     PMLCmds.append("""cmd.create("%s", "(%s)")""" % (Name, Selection))
     1466     PMLCmds.append("""cmd.hide("everything", "%s")""" % (Name))
     1467     if DisplayAs is not None:
     1468         PMLCmds.append("""cmd.show("%s", "%s")""" % (DisplayAs, Name))
     1469     PMLCmds.append("""cmd.show("surface", "%s")""" % (Name))
     1470
     1471     return PMLCmds
     1472
     1473 def SetupPMLForSelectionDisplayView(Name, Selection, DisplayAs, Color = None, Enable = True):
     1474     """Setup PML commands for creating a specific molecular display view for a
     1475      selection.
     1476
     1477     Arguments:
     1478         Name (str): Name of a new PyMOL object.
     1479         Selection (str): Name of PyMOL selection.
     1480         DisplayAs (str): Any valid display type such as lines, sticks, ribbon,
     1481             cartoon, or surface
     1482         Color (str): Color name or use default color.
     1483         Enable (bool): Display status of object.
     1484
     1485     Returns:
     1486         str: PML commands for molecular selection view.
     1487
     1488     """
     1489
     1490     PMLCmds = []
     1491     PMLCmds.append("""cmd.create("%s", "(%s)")""" % (Name, Selection))
     1492     PMLCmds.append("""cmd.hide("everything", "%s")""" % (Name))
     1493     PMLCmds.append("""cmd.show("%s", "%s")""" % (DisplayAs, Name))
     1494     if Color is not None:
     1495         PMLCmds.append("""util.color_deep("%s", "%s")""" % (Color, Name))
     1496     PMLCmds.append(SetupPMLForEnableDisable(Name, Enable))
     1497
     1498     PML = "\n".join(PMLCmds)
     1499
     1500     return PML
     1501
     1502 def SetupPMLForBallAndStickView(Name, Selection, Enable = True, SphereScale = 0.3, StickRadius = 0.2):
     1503     """Setup PML commands for creating a ball and stick view for a specified
     1504     selection.
     1505
     1506     Arguments:
     1507         Name (str): Name of a new PyMOL ball and stick object.
     1508         Selection (str): Name of PyMOL selection.
     1509         Enable (bool): Display status of ball and stick object.
     1510         SphereScale (float): Scaling factor for sphere radii.
     1511         StickScale (float): Scaling factor for stick radii.
     1512
     1513     Returns:
     1514         str: PML commands for ball and stick view.
     1515
     1516     """
     1517
     1518     PMLCmds = []
     1519     PMLCmds.append("""cmd.create("%s", "(%s)")""" % (Name, Selection))
     1520     PMLCmds.append("""cmd.hide("everything", "%s")""" % (Name))
     1521     PMLCmds.append("""cmd.show("sphere", "%s")""" % (Name))
     1522     PMLCmds.append("""cmd.show("sticks", "%s")""" % (Name))
     1523     PMLCmds.append("""cmd.set("sphere_scale", %.1f, "%s")""" % (SphereScale, Name))
     1524     PMLCmds.append("""cmd.set("stick_radius", %.1f, "%s")""" % (StickRadius, Name))
     1525
     1526     PMLCmds.append(SetupPMLForEnableDisable(Name, Enable))
     1527
     1528     PML = "\n".join(PMLCmds)
     1529
     1530     return PML
     1531
     1532 def SetupPMLForInorganicView(Name, Selection, Enable = True):
     1533     """Setup PML commands for creating a inorganic view corresponding to
     1534     inorganic residues present in a selection. The inorganic residues are
     1535     identified using inorganic selection operator available in PyMOL. The
     1536     inorganic residues are displayed as 'lines' and 'nonbonded'.
     1537
     1538     Arguments:
     1539         Name (str): Name of a new PyMOL inorganic object.
     1540         Selection (str): Name of PyMOL selection.
     1541         Enable (bool): Display status of inorganic object.
     1542
     1543     Returns:
     1544         str: PML commands for inorganic view.
     1545
     1546     """
     1547
     1548     PMLCmds = []
     1549     PMLCmds.append("""cmd.create("%s", "((%s) and inorganic)")""" % (Name, Selection))
     1550     PMLCmds.append("""cmd.show("nonbonded", "%s")""" % (Name))
     1551     PMLCmds.append("""cmd.show("lines", "%s")""" % (Name))
     1552     PMLCmds.append(SetupPMLForEnableDisable(Name, Enable))
     1553
     1554     PML = "\n".join(PMLCmds)
     1555
     1556     return PML
     1557
     1558 def SetupPMLForSolventView(Name, Selection, Enable = True):
     1559     """Setup PML commands for creating a solvent view corresponding to
     1560     solvent residues present in a selection. The solvent residues are
     1561     identified using solvent selection operator available in PyMOL. The
     1562     solvent residues are displayed as 'nonbonded'.
     1563
     1564     Arguments:
     1565         Name (str): Name of a new PyMOL solvent object.
     1566         Selection (str): Name of PyMOL selection.
     1567         Enable (bool): Display status of inorganic object.
     1568
     1569     Returns:
     1570         str: PML commands for solvent view.
     1571
     1572     """
     1573
     1574     PMLCmds = []
     1575     PMLCmds.append("""cmd.create("%s", "((%s) and solvent)")""" % (Name, Selection))
     1576     PMLCmds.append("""cmd.show("nonbonded", "%s")""" % (Name))
     1577     PMLCmds.append(SetupPMLForEnableDisable(Name, Enable))
     1578
     1579     PML = "\n".join(PMLCmds)
     1580
     1581     return PML
     1582
     1583 def SetupPMLForPolymerChainView(Name, Selection, Enable = True):
     1584     """Setup PML commands for creating a polymer chain view corresponding
     1585     to backbone and sidechain residues in a selection. The polymer chain is
     1586     displayed as 'cartoon'.
     1587
     1588     Arguments:
     1589         Name (str): Name of a new PyMOL polymer chain object.
     1590         Selection (str): Name of PyMOL selection.
     1591         Enable (bool): Display status of chain object.
     1592
     1593     Returns:
     1594         str: PML commands for polymer chain view.
     1595
     1596     """
     1597
     1598     PMLCmds = []
     1599     PMLCmds.append("""cmd.create("%s", "((%s) and (backbone or sidechain))")""" % (Name, Selection))
     1600     PMLCmds.append("""cmd.hide("everything", "%s")""" % (Name))
     1601     PMLCmds.append("""util.cbag("%s", _self = cmd)""" % (Name))
     1602     PMLCmds.append("""cmd.show("cartoon", "%s")""" % (Name))
     1603     PMLCmds.append(SetupPMLForEnableDisable(Name, Enable))
     1604
     1605
     1606     PML = "\n".join(PMLCmds)
     1607
     1608     return PML
     1609
     1610
     1611 def SetupPMLForPolymerComplexView(MoleculeName, PDBFile, Enable = True, ShowSolvent = True, ShowInorganic = True, ShowLines = True):
     1612     """Setup PML commands for creating a polymer complex view for all chains
     1613     in a PDB file. The solvent and inorganic residues are also shown by default.
     1614      The polymer chains are displayed as 'cartoon'. The 'line' display for the
     1615     polymer chains is also shown and may be turned off. The organic residues are
     1616     displayed as 'sticks'. The solvent and inorganic residues are displayed as
     1617     'nonbonded' and 'lines'.
     1618
     1619     Arguments:
     1620         MoleculeName (str): Name of a new PyMOL molecule object.
     1621         PDBFile (str): Name of PDB file.
     1622         Enable (bool): Display status of chain object.
     1623         ShowSolvent (bool): Display solvent residues.
     1624         ShowInorganic (bool): Display inorganic residues.
     1625         ShowLines (bool): Display lines for polymer chains.
     1626
     1627     Returns:
     1628         str: PML commands for polymer complex view.
     1629
     1630     """
     1631
     1632     PMLCmds = []
     1633
     1634     PMLCmds.append("""cmd.load("%s", "%s")""" % (PDBFile, MoleculeName))
     1635     PML = _SetupPMLForPolymerComplexView(MoleculeName, Enable, ShowSolvent, ShowInorganic, ShowLines)
     1636     PMLCmds.append(PML)
     1637
     1638     PML = "\n".join(PMLCmds)
     1639
     1640     return PML
     1641
     1642 def SetupPMLForPolymerChainComplexView(ChainComplexName, Selection, ChainName, Enable = True, ShowSolvent = True, ShowInorganic = True, ShowLines = True):
     1643     """Setup PML commands for creating a polymer chain complex view for a specified
     1644     chain in a selection. The solvent and inorganic residues are also shown by
     1645     default. The polymer chain is displayed as 'cartoon'. The 'line' display for the
     1646     polymer chain is also shown and may be turned off. The organic residues are
     1647     displayed as 'sticks'. The solvent and inorganic residues are displayed as
     1648     'nonbonded' and 'lines'.
     1649
     1650     Arguments:
     1651         ChainComplexName (str): Name of a new PyMOL polymer chain complex.
     1652         Selection (str): Name of PyMOL selection.
     1653         ChainName (str): Name of a chain.
     1654         Enable (bool): Display status of chain object.
     1655         ShowSolvent (bool): Display solvent residues.
     1656         ShowInorganic (bool): Display inorganic residues.
     1657         ShowLines (bool): Display lines for polymer chain.
     1658
     1659     Returns:
     1660         str: PML commands for polymer chain complex view.
     1661
     1662     """
     1663
     1664     PMLCmds = []
     1665
     1666     PMLCmds.append("""cmd.create("%s", "(%s and chain %s)")""" % (ChainComplexName, Selection, ChainName))
     1667     PML = _SetupPMLForPolymerComplexView(ChainComplexName, Enable, ShowSolvent, ShowInorganic, ShowLines)
     1668     PMLCmds.append(PML)
     1669
     1670     PML = "\n".join(PMLCmds)
     1671
     1672     return PML
     1673
     1674 def _SetupPMLForPolymerComplexView(Name, Enable = True, ShowSolvent = True, ShowInorganic = True,  ShowLines = False):
     1675     """Setup PML for creating a polymer complex view."""
     1676
     1677     PMLCmds = []
     1678
     1679     PMLCmds.append("""cmd.hide("everything", "%s")""" % (Name))
     1680     PMLCmds.append("""cmd.show("cartoon", "%s")""" % (Name))
     1681     PMLCmds.append("""util.cba(33, "%s", _self = cmd)""" % (Name))
     1682     PMLCmds.append("""cmd.show("sticks", "(organic and (%s))")""" % (Name))
     1683     if ShowSolvent:
     1684         PMLCmds.append("""cmd.show("nonbonded", "(solvent and (%s))")""" % (Name))
     1685     if ShowInorganic:
     1686         PMLCmds.append("""cmd.show("nonbonded", "(inorganic and (%s))")""" % (Name))
     1687
     1688     if ShowLines:
     1689         PMLCmds.append("""cmd.show("lines", "%s")""" % (Name))
     1690     else:
     1691         if ShowInorganic:
     1692             PMLCmds.append("""cmd.show("lines", "(inorganic and (%s))")""" % (Name))
     1693
     1694     PMLCmds.append("""cmd.set_bond("valence", "1", "%s", quiet = 1)""" % (Name))
     1695     PMLCmds.append(SetupPMLForEnableDisable(Name, Enable))
     1696
     1697     PML = "\n".join(PMLCmds)
     1698
     1699     return PML