1 #!/bin/env python 2 # File: PyMOLUtil.py 3 # Author: Manish Sud <msud@san.rr.com> 4 # 5 # Copyright (C) 2024 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", "GetCentroid", "GetChains", "GetChainsAndLigandsInfo", "GetAminoAcidResiduesInfo", "GetInorganicResiduesInfo", "GetInterfaceChainsResiduesByCAlphaAtomsDistance", "GetInterfaceChainsResiduesByHeavyAtomsDistance", "GetInterfaceChainsResiduesBySASAChange", "GetLargestLigand", "GetLigandResiduesInfo", "GetLigands", "GetMolecules", "GetNucleicAcidResiduesInfo", "GetPocketInorganicResiduesInfo", "GetPocketPolymerResiduesInfo", "GetPocketSolventResiduesInfo", "GetPolymerResiduesInfo", "GetPhiPsiResiduesInfo", "GetPhiPsiChainsAndResiduesInfo", "GetPhiPsiCategoriesResiduesInfo", "GetSelectionResiduesInfo", "GetSolventResiduesInfo", "GetSurfaceResiduesInfo", "ProcessChainsAndLigandsOptionsInfo", "ProcessChainSelectionsOptionsInfo", "ProcessResidueTypesOptionsInfo", "ProcessSaltBridgesChainResiduesOptionsInfo", "ProcessSurfaceAtomTypesColorsOptionsInfo", "SetupPMLForAlignment", "SetupPMLForBFactorCartoonView", "SetupPMLForBFactorPuttyView", "SetupPMLForBallAndStickView", "SetupPMLForDeepColoring", "SetupPMLForDisulfideBondsView", "SetupPMLForEnableDisable", "SetupPMLForGroup", "SetupPMLForHydrophobicSurfaceView", "SetupPMLForHydrophobicAndChargeSurfaceView", "SetupPMLForInorganicView", "SetupPMLForLigandPocketInorganicView", "SetupPMLForLigandPocketSolventView", "SetupPMLForLigandPocketView", "SetupPMLForLigandView", "SetupPMLForLigandsInputFileView", "SetupPMLForDistanceContactsView", "SetupPMLForPiCationContactsView", "SetupPMLForPiPiContactsView", "SetupPMLForPolarContactsView", "SetupPMLForHalogenContactsView", "SetupPMLForHydrophobicContactsView", "SetupPMLForPolymerChainComplexView", "SetupPMLForPolymerChainView", "SetupPMLForPolymerComplexView", "SetupPMLForSolventView", "SetupPMLForSaltBridgesResiduesView", "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 MoleculeName (str): Name of a PyMOL molecule object. 186 ChainName (str): Name of a chain in a molecule. 187 IgnoreHydrogens (str): Ignore hydrogens during determination of ligand 188 size. 189 190 Returns: 191 str: Name of the largest ligand present in a chain. 192 193 """ 194 if not (len(MoleculeName) and len(ChainName)): 195 return None 196 197 SortBy = "Size" 198 SortOrder = "Descending" 199 LigandsInfoMap = _GetLigandsInfo(MoleculeName, ChainName, SortBy, SortOrder, IgnoreHydrogens) 200 LigandIDs = LigandsInfoMap["LigandResNames"] 201 202 if len(LigandIDs): 203 LigandID = LigandIDs[0] 204 else: 205 LigandID = None 206 207 return LigandID 208 209 def _GetChainsAndLigands(MoleculeName, LigandSortBy = "Size", LigandSortOrder = "Auto", LigandIgnoreHydrogens = "Yes"): 210 """Get chain identifiers in a molecule along with names of the ligands 211 present in chains. Ligands are identified using PyMOL 'organic' selection. 212 """ 213 if not len(MoleculeName): 214 return None 215 216 ChainIDs = GetChains(MoleculeName) 217 if ChainIDs is None: 218 return None 219 220 ChainsAndLigandsMap = {} 221 ChainsAndLigandsMap["ChainIDs"] = [] 222 ChainsAndLigandsMap["LigandIDs"] = {} 223 224 for ChainID in ChainIDs: 225 ChainsAndLigandsMap["ChainIDs"].append(ChainID) 226 ChainsAndLigandsMap["LigandIDs"][ChainID] = [] 227 228 LigandIDs = GetLigands(MoleculeName, ChainID, SortBy = LigandSortBy, SortOrder = LigandSortOrder, IgnoreHydrogens = LigandIgnoreHydrogens) 229 if LigandIDs is not None: 230 ChainsAndLigandsMap["LigandIDs"][ChainID] = LigandIDs 231 232 return ChainsAndLigandsMap 233 234 def _GetLigandsInfo(MoleculeName, ChainName, SortBy = "Size", SortOrder = "Auto", IgnoreHydrogens = "Yes"): 235 """Retrieve information about ligands present in a chain of a molecule.""" 236 237 if not MiscUtil.CheckTextValue(SortBy, "Size Alphabetical"): 238 MiscUtil.PrintError("PyMOLUtil._GetLigandsInfo: The value specified, %s, for parameter SortBy is not valid. SupportedValues: Size Alphabetical" % SortBy) 239 240 if not MiscUtil.CheckTextValue(SortOrder, "Ascending Descending Auto"): 241 MiscUtil.PrintError("PyMOLUtil._GetLigandsInfo: The value specified, %s, for parameter SortOrder is not valid. SupportedValues: Ascending Descending Auto" % SortOrder) 242 243 if not MiscUtil.CheckTextValue(IgnoreHydrogens, "Yes No"): 244 MiscUtil.PrintError("PyMOLUtil._GetLigandsInfo: The value specified, %s, for parameter IgnoreHydrogens is not valid. SupportedValues: Yes No" % IgnoreHydrogens) 245 246 SortBySize = True if re.match("^Size$", SortBy, re.I) else False 247 if re.match("^Auto$", SortOrder, re.I): 248 SortOrderDescending = True if re.match("^Size$", SortBy, re.I) else False 249 else: 250 SortOrderDescending = True if re.match("^Descending$", SortOrder, re.I) else False 251 IgnoreHydrogenAtoms = True if re.match("^Yes$", IgnoreHydrogens, re.I) else False 252 253 # Set up a command to retrieve all appropriate ligand atoms in organic ligands... 254 SelectionCmd = "%s and chain %s and organic" % (MoleculeName, ChainName) 255 if IgnoreHydrogenAtoms: 256 SelectionCmd = "%s and not hydro" % (SelectionCmd) 257 258 # Retrieve atoms... 259 stored.LigandsInfo = [] 260 cmd.iterate(SelectionCmd, "stored.LigandsInfo.append([resi, resn])") 261 262 # Retrieve ligands... 263 LigandsInfoMap = {} 264 LigandsInfoMap["LigandResNames"] = [] 265 LigandsInfoMap["LigandAtomCount"] = {} 266 LigandsInfoMap["LigandResNumber"] = {} 267 268 for LigandResNum, LigandResName in stored.LigandsInfo: 269 if LigandResName in LigandsInfoMap["LigandResNames"]: 270 LigandsInfoMap["LigandAtomCount"][LigandResName] += 1 271 else: 272 LigandsInfoMap["LigandResNames"].append(LigandResName) 273 LigandsInfoMap["LigandAtomCount"][LigandResName] = 1 274 LigandsInfoMap["LigandResNumber"][LigandResName] = LigandResNum 275 276 if not len(LigandsInfoMap["LigandResNames"]): 277 return LigandsInfoMap 278 279 # Sort ligand names... 280 ReverseOrder = True if SortOrderDescending else False 281 if SortBySize: 282 SortedLigandResNames = sorted(LigandsInfoMap["LigandResNames"], key = lambda LigandResName: LigandsInfoMap["LigandAtomCount"][LigandResName], reverse = ReverseOrder) 283 else: 284 # Sort alphabetically... 285 SortedLigandResNames = sorted(LigandsInfoMap["LigandResNames"], reverse = ReverseOrder) 286 287 LigandsInfoMap["LigandResNames"] = SortedLigandResNames 288 289 return LigandsInfoMap 290 291 def GetCentroid(Selection): 292 """Get centroid of a PyMOL selection. 293 294 Arguments: 295 MoleculeName (str): Name of a PyMOL selection. 296 297 Returns: 298 list or None: List of centroid values. 299 300 """ 301 302 SelectionCmd = "(%s)" % Selection 303 304 stored.CoordinatesInfo = [] 305 cmd.iterate_state(1, SelectionCmd, "stored.CoordinatesInfo.append([x, y, z])") 306 307 XCoords = [Coords[0] for Coords in stored.CoordinatesInfo] 308 YCoords = [Coords[1] for Coords in stored.CoordinatesInfo] 309 ZCoords = [Coords[2] for Coords in stored.CoordinatesInfo] 310 311 NumOfCoords = len(stored.CoordinatesInfo) 312 313 CentroidX = sum(XCoords)/NumOfCoords 314 CentroidY = sum(YCoords)/NumOfCoords 315 CentroidZ = sum(ZCoords)/NumOfCoords 316 317 return [CentroidX, CentroidY, CentroidZ] 318 319 def AreAminoAcidResiduesPresent(MoleculeName, ChainName, Type = "Any"): 320 """Check for the presence of amino acid residues in a chain of a 321 molecule. Chains are identified using PyMOL 'polymer' selection. 322 Nonstandard amino acid residues correspond to all residues other than 323 the standard amino acids and nucleic acids. Any amino acid residues cover 324 all residues other than the standard nucleic acids. 325 326 Arguments: 327 MoleculeName (str): Name of a PyMOL molecule object. 328 ChainName (str): Name of a chain in a molecule. 329 Type (str): Types of amino acids: Standard, NonStandard, Any 330 331 Returns: 332 boolean: True or False. 333 334 """ 335 336 if not (len(MoleculeName) and len(ChainName)): 337 return False 338 339 if not re.match("^(Standard|NonStandard|Any)$", Type, re.I): 340 MiscUtil.PrintError("PyMOLUtil.AreAminoAcidResiduesPresent: Invalid amino acid type: %s" % Type) 341 342 SelectionCmd = _SetupAminoAcidResiduesSelectionCmd(MoleculeName, ChainName, Type) 343 344 Status = True if cmd.count_atoms(SelectionCmd) else False 345 346 return Status 347 348 def AreNucleicAcidResiduesPresent(MoleculeName, ChainName): 349 """Check for the presence of nucleic acid residues in a chain of a 350 molecule. Chains are identified using PyMOL 'polymer' selection. 351 352 Arguments: 353 MoleculeName (str): Name of a PyMOL molecule object. 354 ChainName (str): Name of a chain in a molecule. 355 356 Returns: 357 boolean: True or False. 358 359 """ 360 361 if not (len(MoleculeName) and len(ChainName)): 362 return False 363 364 ResidueNames = _GetNucleicAcidResidueNames() 365 if not len(ResidueNames): 366 return False 367 368 ResidueNamesSelection = "+".join(ResidueNames) 369 SelectionCmd = "(%s and chain %s and polymer and (resn %s))" % (MoleculeName, ChainName, ResidueNamesSelection) 370 371 Status = True if cmd.count_atoms(SelectionCmd) else False 372 373 return Status 374 375 def _SetupAminoAcidResiduesSelectionCmd(MoleculeName, ChainName, Type): 376 """Set up amino acids selection command for PyMOL. """ 377 378 AminoAcidsSelection = "+".join(_GetAminoAcidResidueNames()) 379 NucleicAcidsSelection = "+".join(_GetNucleicAcidResidueNames()) 380 381 if re.match("^Standard$", Type, re.I): 382 SelectionCmd = "(%s and chain %s and polymer and (resn %s))" % (MoleculeName, ChainName, AminoAcidsSelection) 383 elif re.match("^NonStandard$", Type, re.I): 384 SelectionCmd = "(%s and chain %s and polymer and (not ((resn %s) or (resn %s))))" % (MoleculeName, ChainName, AminoAcidsSelection, NucleicAcidsSelection) 385 else: 386 # Any amino acid resiudes... 387 SelectionCmd = "(%s and chain %s and polymer and (not (resn %s)))" % (MoleculeName, ChainName, NucleicAcidsSelection) 388 389 return SelectionCmd 390 391 def _GetAminoAcidResidueNames(): 392 """Get list of amino acid residue names. 393 """ 394 395 ResidueNames = ["ALA", "ARG", "ASN", "ASP", "CYS", "GLN", "GLU", "GLY", "HIS", "ILE", "LEU", "LYS", "MET", "PHE", "PRO", "SER", "THR", "TRP", "TYR", "VAL"] 396 397 return ResidueNames 398 399 def _GetNucleicAcidResidueNames(): 400 """Get list of nucleic acid residue names. 401 """ 402 403 ResidueNames = ["A", "G", "T", "U", "C", "DA", "DG", "DT", "DU", "DC"] 404 405 return ResidueNames 406 407 def GetPolymerResiduesInfo(MoleculeName, ChainName): 408 """Get information for residues present in a chain of a molecule. 409 Chains are identified using PyMOL 'polymer' selection. 410 411 Arguments: 412 MoleculeName (str): Name of a PyMOL molecule object. 413 ChainName (str): Name of a chain in a molecule. 414 415 Returns: 416 dict: A dictionary containing list of residue names and dictionaries of 417 residue numbers and residue count for each residue. Names of 418 residues in the dictionary are not sorted. 419 420 Examples: 421 422 ResiduesInfo = GetPolymerResiduesInfo(MolName, ChainName) 423 for ResName in ResiduesInfo["ResNames"]: 424 ResCount = ResiduesInfo["ResCount"][ResName] 425 ResNums = ResiduesInfo["ResNum"][ResName] 426 MiscUtil.PrintInfo("ResName: %s; ResCount: %s; ResNums: %s" % 427 (ResName, ResCount, ResNums)) 428 429 """ 430 if not (len(MoleculeName) and len(ChainName)): 431 return None 432 433 SelectionCmd = "%s and chain %s and polymer" % (MoleculeName, ChainName) 434 ResiduesInfoMap = _GetSelectionResiduesInfo(SelectionCmd) 435 436 return ResiduesInfoMap 437 438 def GetAminoAcidResiduesInfo(MoleculeName, ChainName, Type = "Standard"): 439 """Get information for amino acid residues present in a chain of a 440 molecule. Chains are identified using PyMOL 'polymer' selection. 441 Nonstandard amino acid residues correspond to all residues other than 442 the standard amino acids and nucleic acids. Any amino acid residues cover 443 all residues other than the standard nucleic acids. 444 445 Arguments: 446 MoleculeName (str): Name of a PyMOL molecule object. 447 ChainName (str): Name of a chain in a molecule. 448 Type (str): Types of amino acids: Standard, NonStandard, Any 449 450 Returns: 451 dict: A dictionary containing list of residue names and dictionaries of 452 residue numbers and residue count for each residue. Names of 453 residues in the dictionary are not sorted. 454 455 Examples: 456 457 ResiduesInfo = GetPolymerResiduesInfo(MolName, ChainName) 458 for ResName in ResiduesInfo["ResNames"]: 459 ResCount = ResiduesInfo["ResCount"][ResName] 460 ResNums = ResiduesInfo["ResNum"][ResName] 461 MiscUtil.PrintInfo("ResName: %s; ResCount: %s; ResNums: %s" % 462 (ResName, ResCount, ResNums)) 463 464 """ 465 466 if not (len(MoleculeName) and len(ChainName)): 467 return None 468 469 if not re.match("^(Standard|NonStandard|Any)$", Type, re.I): 470 MiscUtil.PrintError("PyMOLUtil.GetAminoAcidResiduesInfo: Invalid amino acid type: %s" % Type) 471 472 SelectionCmd = _SetupAminoAcidResiduesSelectionCmd(MoleculeName, ChainName, Type) 473 ResiduesInfoMap = _GetSelectionResiduesInfo(SelectionCmd) 474 475 return ResiduesInfoMap 476 477 def GetNucleicAcidResiduesInfo(MoleculeName, ChainName): 478 """Get information for nucleic acid residues present in a chain of 479 a molecule. Chains are identified using PyMOL 'polymer' selection. 480 481 Arguments: 482 MoleculeName (str): Name of a PyMOL molecule object. 483 ChainName (str): Name of a chain in a molecule. 484 485 Returns: 486 dict: A dictionary containing list of residue names and dictionaries of 487 residue numbers and residue count for each residue. Names of 488 residues in the dictionary are not sorted. 489 490 Examples: 491 492 ResiduesInfo = GetPolymerResiduesInfo(MolName, ChainName) 493 for ResName in ResiduesInfo["ResNames"]: 494 ResCount = ResiduesInfo["ResCount"][ResName] 495 ResNums = ResiduesInfo["ResNum"][ResName] 496 MiscUtil.PrintInfo("ResName: %s; ResCount: %s; ResNums: %s" % 497 (ResName, ResCount, ResNums)) 498 499 """ 500 501 if not (len(MoleculeName) and len(ChainName)): 502 return None 503 504 ResidueNames = _GetNucleicAcidResidueNames() 505 506 ResidueNamesSelection = "+".join(ResidueNames) 507 SelectionCmd = "(%s and chain %s and polymer and (resn %s))" % (MoleculeName, ChainName, ResidueNamesSelection) 508 509 ResiduesInfoMap = _GetSelectionResiduesInfo(SelectionCmd) 510 511 return ResiduesInfoMap 512 513 def GetSelectionResiduesInfo(SelectionCmd): 514 """Get information for residues in a chain specified by a selection command. 515 516 Arguments: 517 SelectionCmd (str): PyMOL selection command. 518 519 Returns: 520 dict: A dictionary containing list of residue names and dictionaries of 521 residue numbers and residue count for each residue. Names of 522 residues in the dictionary are not sorted. 523 524 Examples: 525 526 ResiduesInfo = GetSelectionResiduesInfo(SelectionCmd) 527 for ResName in ResiduesInfo["ResNames"]: 528 ResCount = ResiduesInfo["ResCount"][ResName] 529 ResNums = ResiduesInfo["ResNum"][ResName] 530 MiscUtil.PrintInfo("ResName: %s; ResCount: %s; ResNums: %s" % 531 (ResName, ResCount, ResNums)) 532 533 """ 534 if not len(SelectionCmd): 535 return None 536 537 ResiduesInfoMap = _GetSelectionResiduesInfo(SelectionCmd) 538 539 return ResiduesInfoMap 540 541 def GetSolventResiduesInfo(MoleculeName, ChainName): 542 """Get information for solvent residues present in a chain of a molecule. 543 Solvents are identified using PyMOL 'solvent' selection. 544 545 Arguments: 546 MoleculeName (str): Name of a PyMOL molecule object. 547 ChainName (str): Name of a chain in a molecule. 548 549 Returns: 550 dict: A dictionary containing list of residue names and dictionaries of 551 residue numbers and residue count for each residue. Names of 552 residues in the dictionary are not sorted. 553 554 Examples: 555 556 ResiduesInfo = GetSolventResiduesInfo(MolName, ChainName) 557 for ResName in ResiduesInfo["ResNames"]: 558 ResCount = ResiduesInfo["ResCount"][ResName] 559 ResNums = ResiduesInfo["ResNum"][ResName] 560 MiscUtil.PrintInfo("ResName: %s; ResCount: %s; ResNums: %s" % 561 (ResName, ResCount, ResNums)) 562 563 """ 564 if not (len(MoleculeName) and len(ChainName)): 565 return None 566 567 SelectionCmd = "%s and chain %s and solvent" % (MoleculeName, ChainName) 568 ResiduesInfoMap = _GetSelectionResiduesInfo(SelectionCmd) 569 570 return ResiduesInfoMap 571 572 def GetInorganicResiduesInfo(MoleculeName, ChainName): 573 """Get information for inorganic residues present in a chain of a molecule. 574 Inorganic residues are identified using PyMOL 'inorganic' selection. 575 576 Arguments: 577 MoleculeName (str): Name of a PyMOL molecule object. 578 ChainName (str): Name of a chain in a molecule. 579 580 Returns: 581 dict: A dictionary containing list of residue names and dictionaries of 582 residue numbers and residue count for each residue. Names of 583 residues in the dictionary are not sorted. 584 585 Examples: 586 587 ResiduesInfo = GetInorganicResiduesInfo(MolName, ChainName) 588 for ResName in ResiduesInfo["ResNames"]: 589 ResCount = ResiduesInfo["ResCount"][ResName] 590 ResNums = ResiduesInfo["ResNum"][ResName] 591 MiscUtil.PrintInfo("ResName: %s; ResCount: %s; ResNums: %s" % 592 (ResName, ResCount, ResNums)) 593 594 """ 595 if not (len(MoleculeName) and len(ChainName)): 596 return None 597 598 SelectionCmd = "%s and chain %s and inorganic" % (MoleculeName, ChainName) 599 ResiduesInfoMap = _GetSelectionResiduesInfo(SelectionCmd) 600 601 return ResiduesInfoMap 602 603 def GetLigandResiduesInfo(MoleculeName, ChainName): 604 """Get information for ligand residues present in a chain of a molecule. 605 Ligands are identified using PyMOL 'organic' selection. 606 607 Arguments: 608 MoleculeName (str): Name of a PyMOL molecule object. 609 ChainName (str): Name of a chain in a molecule. 610 611 Returns: 612 dict: A dictionary containing list of residue names and dictionaries of 613 residue numbers and residue count for each residue. Names of 614 residues in the dictionary are not sorted. 615 616 Examples: 617 618 ResiduesInfo = GetLigandResiduesInfo(MolName, ChainName) 619 for ResName in ResiduesInfo["ResNames"]: 620 ResCount = ResiduesInfo["ResCount"][ResName] 621 ResNums = ResiduesInfo["ResNum"][ResName] 622 MiscUtil.PrintInfo("ResName: %s; ResCount: %s; ResNums: %s" % 623 (ResName, ResCount, ResNums)) 624 625 """ 626 if not (len(MoleculeName) and len(ChainName)): 627 return None 628 629 SelectionCmd = "%s and chain %s and organic" % (MoleculeName, ChainName) 630 ResiduesInfoMap = _GetSelectionResiduesInfo(SelectionCmd) 631 632 return ResiduesInfoMap 633 634 def GetPocketPolymerResiduesInfo(MoleculeName, ChainName, LigandResName, LigandResNum, PocketDistanceCutoff): 635 """Get information for chain residues present in a pocket around a ligand 636 in a molecule. Polymer residues are identified using negation of PyMOL 637 selection operators 'organic', 'solvent', and 'inorganic'. 638 639 Arguments: 640 MoleculeName (str): Name of a PyMOL molecule object. 641 ChainName (str): Name of a chain in a molecule. 642 LigandResName (str): Residue name of a ligand in a chain. 643 LigandResNum (str): Residue number of a ligand in a chain. 644 PocketDistanceCutoff (float): Distance around ligand to identify pocket 645 residues. 646 647 Returns: 648 dict: A dictionary containing list of residue names and dictionaries of 649 residue numbers and residue count for each residue. Names of 650 residues in the dictionary are not sorted. 651 652 Examples: 653 654 ResiduesInfo = GetPocketPolymerResiduesInfo(MolName, ChainName) 655 for ResName in ResiduesInfo["ResNames"]: 656 ResCount = ResiduesInfo["ResCount"][ResName] 657 ResNums = ResiduesInfo["ResNum"][ResName] 658 MiscUtil.PrintInfo("ResName: %s; ResCount: %s; ResNums: %s" % 659 (ResName, ResCount, ResNums)) 660 661 """ 662 if not (len(MoleculeName) and len(ChainName) and len(LigandResName) and len(LigandResNum)): 663 return None 664 665 LigandSelection = "%s and chain %s and organic and resn %s and resi %s" % (MoleculeName, ChainName, LigandResName, LigandResNum) 666 MoleculeSelection = "%s and chain %s" % (MoleculeName, ChainName) 667 SelectionCmd = "((byresidue (%s) within %.1f of (%s)) and (not solvent) and (not inorganic) and (not organic))" % (MoleculeSelection, PocketDistanceCutoff, LigandSelection) 668 669 ResiduesInfoMap = _GetSelectionResiduesInfo(SelectionCmd) 670 671 return ResiduesInfoMap 672 673 def GetPocketSolventResiduesInfo(MoleculeName, ChainName, LigandResName, LigandResNum, PocketDistanceCutoff): 674 """Get information for solvent residues present in a pocket around a ligand 675 in a molecule. Solvent residues are identified using PyMOL 'solvent' 676 selection. 677 678 Arguments: 679 MoleculeName (str): Name of a PyMOL molecule object. 680 ChainName (str): Name of a chain in a molecule. 681 LigandResName (str): Residue name of a ligand in a chain. 682 LigandResNum (str): Residue number of a ligand in a chain. 683 PocketDistanceCutoff (float): Distance around ligand to identify pocket 684 residues. 685 686 Returns: 687 dict: A dictionary containing list of residue names and dictionaries of 688 residue numbers and residue count for each residue. Names of 689 residues in the dictionary are not sorted. 690 691 Examples: 692 693 ResiduesInfo = GetPocketSolventResiduesInfo(MolName, ChainName) 694 for ResName in ResiduesInfo["ResNames"]: 695 ResCount = ResiduesInfo["ResCount"][ResName] 696 ResNums = ResiduesInfo["ResNum"][ResName] 697 MiscUtil.PrintInfo("ResName: %s; ResCount: %s; ResNums: %s" % 698 (ResName, ResCount, ResNums)) 699 700 """ 701 if not (len(MoleculeName) and len(ChainName) and len(LigandResName) and len(LigandResNum)): 702 return None 703 704 LigandSelection = "%s and chain %s and organic and resn %s and resi %s" % (MoleculeName, ChainName, LigandResName, LigandResNum) 705 MoleculeSelection = "%s and chain %s" % (MoleculeName, ChainName) 706 SelectionCmd = "((byresidue (%s) within %.1f of (%s)) and solvent)" % (MoleculeSelection, PocketDistanceCutoff, LigandSelection) 707 708 ResiduesInfoMap = _GetSelectionResiduesInfo(SelectionCmd) 709 710 return ResiduesInfoMap 711 712 def GetPocketInorganicResiduesInfo(MoleculeName, ChainName, LigandResName, LigandResNum, PocketDistanceCutoff): 713 """Get information for inorganic residues present in a pocket around a 714 ligand in a molecule. Inorganic residues are identified using PyMOL 715 'inorganic' selection. 716 717 Arguments: 718 MoleculeName (str): Name of a PyMOL molecule object. 719 ChainName (str): Name of a chain in a molecule. 720 LigandResName (str): Residue name of a ligand in a chain. 721 LigandResNum (str): Residue number of a ligand in a chain. 722 PocketDistanceCutoff (float): Distance around a ligand to identify 723 pocket residues. 724 725 Returns: 726 dict: A dictionary containing list of residue names and dictionaries of 727 residue numbers and residue count for each residue. Names of 728 residues in the dictionary are not sorted. 729 730 Examples: 731 732 ResiduesInfo = GetPocketInorganicResiduesInfo(MolName, ChainName) 733 for ResName in ResiduesInfo["ResNames"]: 734 ResCount = ResiduesInfo["ResCount"][ResName] 735 ResNums = ResiduesInfo["ResNum"][ResName] 736 MiscUtil.PrintInfo("ResName: %s; ResCount: %s; ResNums: %s" % 737 (ResName, ResCount, ResNums)) 738 739 """ 740 if not (len(MoleculeName) and len(ChainName) and len(LigandResName) and len(LigandResNum)): 741 return None 742 743 LigandSelection = "%s and chain %s and organic and resn %s and resi %s" % (MoleculeName, ChainName, LigandResName, LigandResNum) 744 MoleculeSelection = "%s and chain %s" % (MoleculeName, ChainName) 745 SelectionCmd = "((byresidue (%s) within %.1f of (%s)) and inorganic)" % (MoleculeSelection, PocketDistanceCutoff, LigandSelection) 746 747 ResiduesInfoMap = _GetSelectionResiduesInfo(SelectionCmd) 748 749 return ResiduesInfoMap 750 751 def GetPhiPsiResiduesInfo(MoleculeName, ChainName, Categorize = True): 752 """Get phi and psi torsion angle information for residues in a chain of a 753 molecule containing amino acids. 754 755 The phi and psi angles are optionally categorized into the following groups 756 corresponding to four types of Ramachandran plots: 757 758 General: All residues except glycine, proline, or pre-proline 759 Glycine: Only glycine residues 760 Proline: Only proline residues 761 Pre-Proline: Only residues before proline not including glycine or proline 762 763 Arguments: 764 MoleculeName (str): Name of a PyMOL molecule object. 765 ChainName (str): Name of a chain in a molecule. 766 767 Returns: 768 dict: A dictionary containing sorted list of residue numbers and 769 dictionaries of residue names, phi and psi angles for each residue 770 number. 771 772 Examples: 773 774 PhiPsiInfoMap = GetPhiPsiResiduesInfo(MolName, ChainName, True) 775 for ResNum in PhiPsiInfoMap["ResNums"]: 776 ResName = PhiPsiInfoMap["ResName"][ResNum] 777 Phi = PhiPsiInfoMap["Phi"][ResNum] 778 Psi = PhiPsiInfoMap["Psi"][ResNum] 779 Category = PhiPsiInfoMap["Category"][ResNum] 780 MiscUtil.PrintInfo("ResNum: %s; ResName: %s; Phi: %8.2f; 781 Psi: %8.2f; Category: %s" % (ResNum, ResName, Phi, Psi, 782 Categorize)) 783 784 """ 785 if not (len(MoleculeName) and len(ChainName)): 786 return None 787 788 SelectionCmd = "%s and chain %s" % (MoleculeName, ChainName) 789 PhiPsiResiduesInfoMap = _GetSelectionPhiPsiResiduesInfo(SelectionCmd, Categorize) 790 791 return PhiPsiResiduesInfoMap 792 793 def GetPhiPsiChainsAndResiduesInfo(MoleculeName, Categorize = True): 794 """Get phi and psi torsion angle information for residues across chains in 795 a molecule containing amino acids. 796 797 The phi and psi angles are optionally categorized into the following groups 798 corresponding to four types of Ramachandran plots: 799 800 General: All residues except glycine, proline, or pre-proline 801 Glycine: Only glycine residues 802 Proline: Only proline residues 803 Pre-Proline: Only residues before proline not including glycine or proline 804 805 Arguments: 806 MoleculeName (str): Name of a PyMOL molecule object. 807 808 Returns: 809 dict: A dictionary containing sorted list of residue numbers for each 810 chain and dictionaries of residue names, phi and psi angles for each 811 residue number. 812 813 Examples: 814 815 PhiPsiInfoMap = GetPhiPsiChainsAndResiduesInfo(MolName) 816 for ChainID in PhiPsiInfoMap["ChainIDs"]: 817 for ResNum in PhiPsiInfoMap["ResNums"][ChainID]: 818 ResName = PhiPsiInfoMap["ResName"][ChainID][ResNum] 819 Phi = PhiPsiInfoMap["Phi"][ChainID][ResNum] 820 Psi = PhiPsiInfoMap["Psi"][ChainID][ResNum] 821 Category = PhiPsiInfoMap["Category"][ChainID][ResNum] 822 MiscUtil.PrintInfo("ChainID: %s; ResNum: %s; ResName: %s; Phi: %8.2f; 823 Psi: %8.2f; Category: %s" % (ChainID, ResNum, ResName, Phi, 824 Psi, Category)) 825 826 """ 827 if not len(MoleculeName): 828 return None 829 830 SelectionCmd = "%s" % (MoleculeName) 831 PhiPsiResiduesInfoMap = _GetSelectionPhiPsiChainsAndResiduesInfo(SelectionCmd, Categorize) 832 833 return PhiPsiResiduesInfoMap 834 835 def GetPhiPsiCategoriesResiduesInfo(MoleculeName, ChainName): 836 """Get phi and psi torsion angle information for residues in a chain of a 837 molecule containing amino acids. 838 839 The phi and psi angles are optionally categorized into the following groups 840 corresponding to four types of Ramachandran plots: 841 842 General: All residues except glycine, proline, or pre-proline 843 Glycine: Only glycine residues 844 Proline: Only proline residues 845 Pre-Proline: Only residues before proline not including glycine or proline 846 847 Arguments: 848 MoleculeName (str): Name of a PyMOL molecule object. 849 ChainName (str): Name of a chain in a molecule. 850 851 Returns: 852 dict1: Phi and psi angle information for residues in General category. 853 It's a dictionary containing sorted list of residue numbers and 854 dictionaries of residue names, phi and psi angles for each residue 855 number. 856 dict2: Phi and psi angle information for residues in Gly category. 857 dict3: Phi and psi angle information for residues in Pro category. 858 dict2: Phi and psi angle information for residues in Pre-Pro category. 859 860 Examples: 861 862 GeneralPhiPsiInfo, GlyPhiPsiInfo, ProPhiPsiInfo, PreProPhiPsiInfo = 863 GetPhiPsiCategoriesResiduesInfo(MolName, ChainID) 864 for ResNum in GeneralPhiPsiInfo["ResNums"]: 865 ResName = GeneralPhiPsiInfo["ResName"][ResNum] 866 Phi = GeneralPhiPsiInfo["Phi"][ResNum] 867 Psi = GeneralPhiPsiInfo["Psi"][ResNum] 868 MiscUtil.PrintInfo("ResNum: %s; ResName: %s; 869 Phi: %8.2f; Psi: %8.2f" % (ResNum, ResName, Phi, Psi)) 870 871 """ 872 if not (len(MoleculeName) and len(ChainName)): 873 return None 874 875 SelectionCmd = "%s and chain %s" % (MoleculeName, ChainName) 876 GeneralPhiPsiInfo, GlyPhiPsiInfo, ProPhiPsiInfo, PreProPhiPsiInfo = _GetSelectionPhiPsiCategoriesResiduesInfo(SelectionCmd) 877 878 return GeneralPhiPsiInfo, GlyPhiPsiInfo, ProPhiPsiInfo, PreProPhiPsiInfo 879 880 def GetSurfaceAndBuriedResiduesInfo(MoleculeName, ChainName, SASACutoff = 2.5): 881 """Get information for surafce and buried residues present in a chain of a 882 molecule. The surface residues correspond to residues with Solvent Accessible 883 Surface Area (SASA) greater than or equal to the cutoff value. Otherwise, these 884 residues are considered as buried residues. 885 886 Arguments: 887 MoleculeName (str): Name of a PyMOL molecule object. 888 ChainName (str): Name of a chain in a molecule. 889 SASACutoff (float): SASA cutoff for heavy atoms corresponding to 890 surface residues in chain. Units: Angstroms ** 2 891 892 Returns: 893 dict: A dictionary containing list of residue names and dictionaries of 894 residue numbers and residue count for each residue. Names of 895 residues in the dictionary are not sorted. 896 dict2: Buried residues in a chain. 897 898 Examples: 899 900 SurfaceResiduesInfo, BurriedResiduesInfo = 901 GetSurfaceResiduesInfo(MolName, ChainName, 2.5) 902 for ResName in SurfaceResiduesInfo["ResNames"]: 903 ResCount = ResiduesInfo["ResCount"][ResName] 904 ResNums = ResiduesInfo["ResNum"][ResName] 905 MiscUtil.PrintInfo("ResName: %s; ResCount: %s; ResNums: %s" % 906 (ResName, ResCount, ResNums)) 907 908 """ 909 if not (len(MoleculeName) and len(ChainName)): 910 return None 911 912 # Get ready to calculate solvent accessible surface area.. 913 CurrentDotSolvent = cmd.get("dot_solvent") 914 cmd.set("dot_solvent", 1) 915 916 # Setup tmp object name... 917 TmpChainName = "Tmp_%s" % (MoleculeName) 918 TmpChainSelection = "(%s and chain %s and polymer and not hydrogens)" % (MoleculeName, ChainName) 919 cmd.create(TmpChainName, "(%s)" % (TmpChainSelection)) 920 921 # Calculate SASA for chain and load it into b... 922 cmd.get_area(TmpChainName, load_b = 1) 923 924 # Retrieve SASA for residues as B values... 925 ResiduesBValuesInfoMap = _GetSelectionResiduesBValuesInfo(TmpChainName) 926 927 # Retrieve information for surface and buried residues... 928 SurfaceResiduesInfoMap = _GetResiduesInfoFromResiduesBValues(ResiduesBValuesInfoMap, ">=", SASACutoff) 929 BuriedResiduesInfoMap = _GetResiduesInfoFromResiduesBValues(ResiduesBValuesInfoMap, "<", SASACutoff) 930 931 # Delete tmp objects... 932 cmd.delete(TmpChainName) 933 934 # Restore current dot solvent... 935 cmd.set("dot_solvent", CurrentDotSolvent) 936 937 return SurfaceResiduesInfoMap, BuriedResiduesInfoMap 938 939 def GetInterfaceChainsResiduesByCAlphaAtomsDistance(MoleculeName1, ChainNames1, MoleculeName2, ChainNames2, DistanceCutoff = 8.0): 940 """Get information for interface residues between chains in two 941 molecules based on the distance between CAlpha atoms. The chain 942 specification for molecules may contain multiple chain names delimited 943 by commas. 944 945 The interface residues are identified using PyMOL 'bycalpha' selection 946 operator with in a specified distance. 947 948 Arguments: 949 MoleculeName1 (str): Name of a PyMOL molecule object. 950 ChainNames1 (str): A chain name or comma delimited list of chain 951 names in a molecule. 952 MoleculeName2 (str): Name of a PyMOL molecule object. 953 ChainNames2 (str): A chain name or comma delimited list of chain 954 names in a molecule. 955 DistanceCutoff (float): Distance cutoff for distance between 956 any two CAlpha atoms in interface residues in different chains. 957 958 Returns: 959 dict1: Interface residues in a chain for first molecule. It is a 960 dictionary containing list of residue names and dictionaries of 961 residue numbers and residue count for each residue. Names of 962 residues in the dictionary are not sorted. 963 dict2: Interface residues in the chain for second molecule. 964 965 Examples: 966 967 ResiduesInfo1, ResiduesInfo2 = 968 GetInterfaceResiduesByHeavyAtomsDistance(MolName1, 969 ChainName1, MolName2, ChainName2, DistanceCutoff) 970 for ChainID in ResiduesInfo1["ChainIDs"]: 971 for ResName in ResiduesInfo1["ResNames"][ChainID]: 972 ResCount = ResiduesInfo1["ResCount"][ChainID][ResName] 973 ResNums = ResiduesInfo1["ResNum"][ChainID][ResName] 974 MiscUtil.PrintInfo("ResName: %s; ResCount: %s; ResNums: 975 %s" % (ResName, ResCount, ResNums)) 976 977 """ 978 ChainNames1Selection, ChainNames2Selection = _ValidateAndSetupChainSelectionsForInterfaceResidues(MoleculeName1, ChainNames1, MoleculeName2, ChainNames2) 979 980 if ChainNames1Selection is None or ChainNames2Selection is None: 981 return None 982 983 MoleculeSelection1 = "%s and chain %s" % (MoleculeName1, ChainNames1Selection) 984 MoleculeSelection2 = "%s and chain %s" % (MoleculeName2, ChainNames2Selection) 985 986 SelectionCmd1 = "((bycalpha (%s) within %.1f of (%s)) and polymer)" % (MoleculeSelection1, DistanceCutoff, MoleculeSelection2) 987 ResiduesInfoMap1= _GetSelectionChainsAndResiduesInfo(SelectionCmd1) 988 989 SelectionCmd2 = "((bycalpha (%s) within %.1f of (%s)) and polymer)" % (MoleculeSelection2, DistanceCutoff, MoleculeSelection1) 990 ResiduesInfoMap2= _GetSelectionChainsAndResiduesInfo(SelectionCmd2) 991 992 return ResiduesInfoMap1, ResiduesInfoMap2 993 994 def GetInterfaceChainsResiduesByHeavyAtomsDistance(MoleculeName1, ChainNames1, MoleculeName2, ChainNames2, DistanceCutoff = 5.0): 995 """Get information for interface residues between chains in two 996 molecules based on the distance between heavy atoms. The chain 997 specification for molecules may contain multiple chain names delimited 998 by commas. 999 1000 The interface residues are identified using PyMOL 'byresidue' selection 1001 operator with in a specified distance. 1002 1003 Arguments: 1004 MoleculeName1 (str): Name of a PyMOL molecule object. 1005 ChainNames1 (str): A chain name or comma delimited list of chain 1006 names in a molecule. 1007 MoleculeName2 (str): Name of a PyMOL molecule object. 1008 ChainNames2 (str): A chain name or comma delimited list of chain 1009 names in a molecule. 1010 DistanceCutoff (float): Distance cutoff for distance between 1011 any two heavy atoms in interface residues in different chains. 1012 1013 Returns: 1014 dict1: Interface residues in a chain for first molecule. It is a 1015 dictionary containing list of residue names and dictionaries of 1016 residue numbers and residue count for each residue. Names of 1017 residues in the dictionary are not sorted. 1018 dict2: Interface residues in the chain for second molecule. 1019 1020 Examples: 1021 1022 ResiduesInfo1, ResiduesInfo2 = 1023 GetInterfaceResiduesByHeavyAtomsDistance(MolName1, 1024 ChainName1, MolName2, ChainName2, DistanceCutoff) 1025 for ChainID in ResiduesInfo1["ChainIDs"]: 1026 for ResName in ResiduesInfo1["ResNames"][ChainID]: 1027 ResCount = ResiduesInfo1["ResCount"][ChainID][ResName] 1028 ResNums = ResiduesInfo1["ResNum"][ChainID][ResName] 1029 MiscUtil.PrintInfo("ResName: %s; ResCount: %s; ResNums: 1030 %s" % (ResName, ResCount, ResNums)) 1031 1032 """ 1033 ChainNames1Selection, ChainNames2Selection = _ValidateAndSetupChainSelectionsForInterfaceResidues(MoleculeName1, ChainNames1, MoleculeName2, ChainNames2) 1034 1035 if ChainNames1Selection is None or ChainNames2Selection is None: 1036 return None 1037 1038 MoleculeSelection1 = "%s and chain %s and (not hydrogens)" % (MoleculeName1, ChainNames1Selection) 1039 MoleculeSelection2 = "%s and chain %s and (not hydrogens)" % (MoleculeName2, ChainNames2Selection) 1040 1041 SelectionCmd1 = "((byresidue (%s) within %.1f of (%s)) and polymer)" % (MoleculeSelection1, DistanceCutoff, MoleculeSelection2) 1042 ResiduesInfoMap1= _GetSelectionChainsAndResiduesInfo(SelectionCmd1) 1043 1044 SelectionCmd2 = "((byresidue (%s) within %.1f of (%s)) and polymer)" % (MoleculeSelection2, DistanceCutoff, MoleculeSelection1) 1045 ResiduesInfoMap2= _GetSelectionChainsAndResiduesInfo(SelectionCmd2) 1046 1047 return ResiduesInfoMap1, ResiduesInfoMap2 1048 1049 def GetInterfaceChainsResiduesBySASAChange(MoleculeName1, ChainNames1, MoleculeName2, ChainNames2, ChangeCutoff = 0.75): 1050 """Get information for interface residues between chains in two 1051 molecules based on the change in solvent accessible surface area 1052 (SASA) of a residue in chains in a molecule and chain complex 1053 containing specified chains across both molecules. The chain 1054 specification for molecules may contain multiple chain names 1055 delimited by commas. 1056 1057 Arguments: 1058 MoleculeName1 (str): Name of a PyMOL molecule object. 1059 ChainNames1 (str): A chain name or comma delimited list of chain 1060 names in a molecule. 1061 MoleculeName2 (str): Name of a PyMOL molecule object. 1062 ChainNames2 (str): A chain name or comma delimited list of chain 1063 names in a molecule. 1064 ChangeCutoff (float): SASA change cutoff for heavy atoms in 1065 a interface residue between an individual chain and a complex 1066 containing both chains. Units: Angstroms ** 2 1067 1068 Returns: 1069 dict1: Interface residues in the chain for first molecule. It is a 1070 dictionary containing list of residue names and dictionaries of 1071 residue numbers and residue count for each residue. Names of 1072 residues in the dictionary are not sorted. 1073 dict2: Interface residues in the chain for second molecule. 1074 1075 Examples: 1076 1077 ResiduesInfo1, ResiduesInfo2 = 1078 GetInterfaceResiduesBySASAChange(MolName1, 1079 ChainName1, MolName2, ChainName2, DistanceCutoff) 1080 for ResName in ResiduesInfo1["ResNames"]: 1081 ResCount = ResiduesInfo1["ResCount"][ResName] 1082 ResNums = ResiduesInfo1["ResNum"][ResName] 1083 MiscUtil.PrintInfo("ResName: %s; ResCount: %s; ResNums: %s" % 1084 (ResName, ResCount, ResNums)) 1085 1086 """ 1087 ChainNames1Selection, ChainNames2Selection = _ValidateAndSetupChainSelectionsForInterfaceResidues(MoleculeName1, ChainNames1, MoleculeName2, ChainNames2) 1088 1089 if ChainNames1Selection is None or ChainNames2Selection is None: 1090 return None 1091 1092 # Get ready to calculate solvent accessible surface area.. 1093 CurrentDotSolvent = cmd.get("dot_solvent") 1094 cmd.set("dot_solvent", 1) 1095 1096 # Setup tmp object names... 1097 TmpComplexName = "Tmp1_%s_%s" % (MoleculeName1, MoleculeName2) 1098 TmpChainName1 = "Tmp2_%s" % (MoleculeName1) 1099 TmpChainName2 = "Tmp3_%s" % (MoleculeName2) 1100 1101 # Setup complex... 1102 TmpComplexSelection = "(%s and chain %s and polymer and not hydrogens) or (%s and chain %s and polymer and not hydrogens)" % (MoleculeName1, ChainNames1Selection, MoleculeName2, ChainNames2Selection) 1103 cmd.create(TmpComplexName, "(%s)" % (TmpComplexSelection)) 1104 1105 # Calculate SASA for complex and load it into b... 1106 cmd.get_area(TmpComplexName, load_b = 1) 1107 cmd.alter(TmpComplexName, "q=b") 1108 1109 # Setup individual chains and calculate SASA... 1110 TmpChainNameSelection1 = "%s and (chain %s)" % (TmpComplexName, ChainNames1Selection) 1111 cmd.extract(TmpChainName1, "(%s)" % TmpChainNameSelection1) 1112 cmd.get_area(TmpChainName1, load_b = 1) 1113 1114 TmpChainNameSelection2 = "%s and (chain %s)" % (TmpComplexName, ChainNames2Selection) 1115 cmd.extract(TmpChainName2, "(%s)" % TmpChainNameSelection2) 1116 cmd.get_area(TmpChainName2, load_b = 1) 1117 1118 # Calculate SASA difference for individual chains... 1119 TmpChainNamesSelection = "(%s or %s)" % (TmpChainName1, TmpChainName2) 1120 cmd.alter(TmpChainNamesSelection, "b=b-q") 1121 1122 ResiduesInfoMap1 = _GetChainsResiduesInfoForSASAChange(TmpChainNamesSelection, TmpChainName1, ChangeCutoff) 1123 ResiduesInfoMap2 = _GetChainsResiduesInfoForSASAChange(TmpChainNamesSelection, TmpChainName2, ChangeCutoff) 1124 1125 # Delete tmp objects... 1126 cmd.delete(TmpComplexName) 1127 cmd.delete(TmpChainName1) 1128 cmd.delete(TmpChainName2) 1129 1130 # Restore current dot solvent... 1131 cmd.set("dot_solvent", CurrentDotSolvent) 1132 1133 return ResiduesInfoMap1, ResiduesInfoMap2 1134 1135 def _GetChainsResiduesInfoForSASAChange(SelectionCmd, MoleculeName, ChangeCutoff): 1136 """Get residue info for SASA change. """ 1137 1138 # Retrieve data... 1139 stored.ResiduesInfo = [] 1140 cmd.iterate(SelectionCmd, "stored.ResiduesInfo.append([model, chain, resi, resn, b])") 1141 1142 # Calculate SASA change for each residue... 1143 SASAChangeMap = {} 1144 SASAChangeMap["ChainIDs"] = [] 1145 SASAChangeMap["ResIDs"] = {} 1146 SASAChangeMap["ResSASAChange"] = {} 1147 1148 for Model, ChainID, ResNum, ResName, AtomSASAChange in stored.ResiduesInfo: 1149 if not re.match(Model, MoleculeName, re.I): 1150 continue 1151 ResID = "%s_%s" % (ResName, ResNum) 1152 1153 if not ChainID in SASAChangeMap["ChainIDs"]: 1154 # Track new chain ID and intialize SASA change information... 1155 SASAChangeMap["ChainIDs"].append(ChainID) 1156 SASAChangeMap["ResIDs"][ChainID] = [] 1157 SASAChangeMap["ResSASAChange"][ChainID]= {} 1158 1159 if ResID in SASAChangeMap["ResSASAChange"][ChainID]: 1160 SASAChangeMap["ResSASAChange"][ChainID][ResID] += AtomSASAChange 1161 else: 1162 # Track new residue ID... 1163 SASAChangeMap["ResIDs"][ChainID].append(ResID) 1164 SASAChangeMap["ResSASAChange"][ChainID][ResID] = AtomSASAChange 1165 1166 # Identify residues with SASA change greater than the specified cutoff value... 1167 SelectionInfoMap = {} 1168 SelectionInfoMap["ChainIDs"] = [] 1169 1170 SelectionInfoMap["ResNames"] = {} 1171 SelectionInfoMap["ResNum"] = {} 1172 SelectionInfoMap["ResCount"] = {} 1173 1174 for ChainID in SASAChangeMap["ChainIDs"]: 1175 for ResID in SASAChangeMap["ResIDs"][ChainID]: 1176 ResSASAChange = SASAChangeMap["ResSASAChange"][ChainID][ResID] 1177 if abs(ResSASAChange) < ChangeCutoff: 1178 continue 1179 ResName, ResNum = ResID.split("_") 1180 1181 if not ChainID in SelectionInfoMap["ChainIDs"]: 1182 # Track new chain ID and intialize residues information... 1183 SelectionInfoMap["ChainIDs"].append(ChainID) 1184 SelectionInfoMap["ResNames"][ChainID] = [] 1185 SelectionInfoMap["ResNum"][ChainID]= {} 1186 SelectionInfoMap["ResCount"][ChainID] = {} 1187 1188 if ResName in SelectionInfoMap["ResNames"][ChainID]: 1189 if not ResNum in SelectionInfoMap["ResNum"][ChainID][ResName]: 1190 # Same residue name but different residue number 1191 SelectionInfoMap["ResNum"][ChainID][ResName].append(ResNum) 1192 SelectionInfoMap["ResCount"][ChainID][ResName] += 1 1193 else: 1194 # Track new residue information... 1195 SelectionInfoMap["ResNames"][ChainID].append(ResName) 1196 1197 SelectionInfoMap["ResNum"][ChainID][ResName] = [] 1198 SelectionInfoMap["ResNum"][ChainID][ResName].append(ResNum) 1199 1200 SelectionInfoMap["ResCount"][ChainID][ResName] = 1 1201 1202 return SelectionInfoMap 1203 1204 def _ValidateAndSetupChainSelectionsForInterfaceResidues(MoleculeName1, ChainNames1, MoleculeName2, ChainNames2): 1205 """Validate and setup chains name selectons for idenfitying interface residues.""" 1206 1207 ChainNames1 = re.sub(" ", "", ChainNames1) 1208 ChainNames2 = re.sub(" ", "", ChainNames2) 1209 1210 if not (len(MoleculeName1) and len(ChainNames1) and len(MoleculeName2) and len(ChainNames2)): 1211 return None, None 1212 1213 # Setup chain names for PyMOL selections... 1214 ChainNames1Selection = "+".join(ChainNames1.split(",")) 1215 ChainNames2Selection = "+".join(ChainNames2.split(",")) 1216 1217 return ChainNames1Selection, ChainNames2Selection 1218 1219 def _GetSelectionChainsAndResiduesInfo(SelectionCmd): 1220 """Get chain names, residue names and count information for a selection. """ 1221 1222 # Retrieve atoms... 1223 stored.SelectionInfo = [] 1224 cmd.iterate(SelectionCmd, "stored.SelectionInfo.append([chain, resi, resn])") 1225 1226 # Retrieve chains and residues... 1227 SelectionInfoMap = {} 1228 SelectionInfoMap["ChainIDs"] = [] 1229 1230 SelectionInfoMap["ResNames"] = {} 1231 SelectionInfoMap["ResNum"] = {} 1232 SelectionInfoMap["ResCount"] = {} 1233 1234 for ChainID, ResNum, ResName in stored.SelectionInfo: 1235 if not ChainID in SelectionInfoMap["ChainIDs"]: 1236 # Track new chain ID and intialize residues information... 1237 SelectionInfoMap["ChainIDs"].append(ChainID) 1238 SelectionInfoMap["ResNames"][ChainID] = [] 1239 SelectionInfoMap["ResNum"][ChainID]= {} 1240 SelectionInfoMap["ResCount"][ChainID] = {} 1241 1242 if ResName in SelectionInfoMap["ResNames"][ChainID]: 1243 if not ResNum in SelectionInfoMap["ResNum"][ChainID][ResName]: 1244 # Same residue name but different residue number 1245 SelectionInfoMap["ResNum"][ChainID][ResName].append(ResNum) 1246 SelectionInfoMap["ResCount"][ChainID][ResName] += 1 1247 else: 1248 # Track new residue information... 1249 SelectionInfoMap["ResNames"][ChainID].append(ResName) 1250 1251 SelectionInfoMap["ResNum"][ChainID][ResName] = [] 1252 SelectionInfoMap["ResNum"][ChainID][ResName].append(ResNum) 1253 1254 SelectionInfoMap["ResCount"][ChainID][ResName] = 1 1255 1256 return SelectionInfoMap 1257 1258 def _GetSelectionResiduesInfo(SelectionCmd): 1259 """Get residue names and count information for a selection. """ 1260 1261 # Retrieve atoms... 1262 stored.SelectionInfo = [] 1263 cmd.iterate(SelectionCmd, "stored.SelectionInfo.append([resi, resn])") 1264 1265 # Retrieve residues... 1266 SelectionInfoMap = {} 1267 SelectionInfoMap["ResNames"] = [] 1268 SelectionInfoMap["ResNum"] = {} 1269 SelectionInfoMap["ResCount"] = {} 1270 1271 for ResNum, ResName in stored.SelectionInfo: 1272 if ResName in SelectionInfoMap["ResNames"]: 1273 if not ResNum in SelectionInfoMap["ResNum"][ResName]: 1274 # Same residue name but different residue number 1275 SelectionInfoMap["ResNum"][ResName].append(ResNum) 1276 SelectionInfoMap["ResCount"][ResName] += 1 1277 else: 1278 SelectionInfoMap["ResNames"].append(ResName) 1279 1280 SelectionInfoMap["ResNum"][ResName] = [] 1281 SelectionInfoMap["ResNum"][ResName].append(ResNum) 1282 1283 SelectionInfoMap["ResCount"][ResName] = 1 1284 1285 return SelectionInfoMap 1286 1287 def _GetSelectionPhiPsiResiduesInfo(SelectionCmd, Categorize): 1288 """Get phi and psi torsion angle information for residues in a selection 1289 with in a chain. 1290 1291 The phi and psi angles are optionally categorized into the following groups 1292 corresponding to four types of Ramachandran plots: 1293 1294 General: All residues except glycine, proline, or pre-proline 1295 Glycine: Only glycine residues 1296 Proline: Only proline residues 1297 Pre-Proline: Only residues before proline not including glycine or proline 1298 1299 """ 1300 1301 # Initialize... 1302 SelectionInfoMap = {} 1303 SelectionInfoMap["ResNums"] = [] 1304 SelectionInfoMap["ResName"] = {} 1305 SelectionInfoMap["Phi"] = {} 1306 SelectionInfoMap["Psi"] = {} 1307 SelectionInfoMap["Category"] = {} 1308 1309 # Retrieve phi and psi info... 1310 PhiPsiInfo = _GetSelectionPhiPsiInfo(SelectionCmd, Categorize) 1311 if PhiPsiInfo is None: 1312 return SelectionInfoMap 1313 1314 # Track... 1315 for Model, ChainID, ResNum, ResName, Phi, Psi, Category in PhiPsiInfo: 1316 if ResNum in SelectionInfoMap["ResName"]: 1317 continue 1318 1319 SelectionInfoMap["ResNums"].append(ResNum) 1320 SelectionInfoMap["ResName"][ResNum] = ResName 1321 SelectionInfoMap["Phi"][ResNum] = Phi 1322 SelectionInfoMap["Psi"][ResNum] = Psi 1323 SelectionInfoMap["Category"][ResNum] = Category 1324 1325 return SelectionInfoMap 1326 1327 def _GetSelectionPhiPsiChainsAndResiduesInfo(SelectionCmd, Categorize): 1328 """Get phi and psi torsion angle information for residues in a selection 1329 across chains in a molecule. 1330 1331 The phi and psi angles are optionally categorized into the following groups 1332 corresponding to four types of Ramachandran plots: 1333 1334 General: All residues except glycine, proline, or pre-proline 1335 Glycine: Only glycine residues 1336 Proline: Only proline residues 1337 Pre-Proline: Only residues before proline not including glycine or proline 1338 1339 """ 1340 1341 # Initialize... 1342 SelectionInfoMap = {} 1343 SelectionInfoMap["ChainIDs"] = [] 1344 SelectionInfoMap["ResNums"] = {} 1345 SelectionInfoMap["ResName"] = {} 1346 SelectionInfoMap["Phi"] = {} 1347 SelectionInfoMap["Psi"] = {} 1348 SelectionInfoMap["Category"] = {} 1349 1350 # Retrieve phi and psi info... 1351 PhiPsiInfo = _GetSelectionPhiPsiInfo(SelectionCmd, Categorize) 1352 if PhiPsiInfo is None: 1353 return SelectionInfoMap 1354 1355 # Track... 1356 for Model, ChainID, ResNum, ResName, Phi, Psi, Category in PhiPsiInfo: 1357 if not ChainID in SelectionInfoMap["ResNums"]: 1358 # Track new chain ID and initialize residues information... 1359 SelectionInfoMap["ChainIDs"].append(ChainID) 1360 1361 SelectionInfoMap["ResNums"][ChainID] = [] 1362 SelectionInfoMap["ResName"][ChainID] = {} 1363 SelectionInfoMap["Phi"][ChainID] = {} 1364 SelectionInfoMap["Psi"][ChainID] = {} 1365 SelectionInfoMap["Category"][ChainID] = {} 1366 1367 # Check for duplicates... 1368 if ResNum in SelectionInfoMap["ResName"][ChainID]: 1369 continue 1370 1371 # Track new residues information... 1372 SelectionInfoMap["ResNums"][ChainID].append(ResNum) 1373 SelectionInfoMap["ResName"][ChainID][ResNum] = ResName 1374 SelectionInfoMap["Phi"][ChainID][ResNum] = Phi 1375 SelectionInfoMap["Psi"][ChainID][ResNum] = Psi 1376 SelectionInfoMap["Category"][ChainID][ResNum] = Category 1377 1378 return SelectionInfoMap 1379 1380 def _GetSelectionPhiPsiCategoriesResiduesInfo(SelectionCmd): 1381 """Get phi and psi torsion angle information for residues in a selection 1382 with in a chain. 1383 1384 The phi and psi angles are optionally categorized into the following groups 1385 corresponding to four types of Ramachandran plots: 1386 1387 General: All residues except glycine, proline, or pre-proline 1388 Glycine: Only glycine residues 1389 Proline: Only proline residues 1390 Pre-Proline: Only residues before proline not including glycine or proline 1391 1392 """ 1393 1394 # Initialize... 1395 PhiPsiInfoMaps = {} 1396 PhiPsiInfoMaps["Maps"] = [] 1397 for Category in ["General", "Glycine", "Proline", "Pre-Proline"]: 1398 PhiPsiInfoMap = {} 1399 PhiPsiInfoMap["ResNums"] = [] 1400 PhiPsiInfoMap["ResName"] = {} 1401 PhiPsiInfoMap["Phi"] = {} 1402 PhiPsiInfoMap["Psi"] = {} 1403 PhiPsiInfoMap["Category"] = {} 1404 1405 PhiPsiInfoMaps[Category] = PhiPsiInfoMap 1406 PhiPsiInfoMaps["Maps"].append(PhiPsiInfoMap) 1407 1408 # Retrieve phi and psi info... 1409 PhiPsiInfo = _GetSelectionPhiPsiInfo(SelectionCmd, True) 1410 if PhiPsiInfo is None: 1411 return PhiPsiInfoMaps["Maps"] 1412 1413 Index = -1 1414 for Model, ChainID, ResNum, ResName, Phi, Psi, Category in PhiPsiInfo: 1415 Index += 1 1416 1417 if ResNum in PhiPsiInfoMaps[Category]["ResName"]: 1418 continue 1419 1420 # Track... 1421 PhiPsiInfoMaps[Category]["ResNums"].append(ResNum) 1422 PhiPsiInfoMaps[Category]["ResName"][ResNum] = ResName 1423 PhiPsiInfoMaps[Category]["Phi"][ResNum] = Phi 1424 PhiPsiInfoMaps[Category]["Psi"][ResNum] = Psi 1425 PhiPsiInfoMaps[Category]["Category"][ResNum] = Category 1426 1427 return PhiPsiInfoMaps["Maps"] 1428 1429 def _GetSelectionPhiPsiInfo(SelectionCmd, Categorize = False): 1430 """Get phi and psi angles for a selection along with information regarding 1431 model, chain, residue number, and residue name. 1432 1433 The phi and psi angles are optionally categorized into the following groups 1434 corresponding to four types of Ramachandran plots: 1435 1436 General: All residues except glycine, proline, or pre-proline 1437 Glycine: Only glycine residues 1438 Proline: Only proline residues 1439 Pre-Proline: Only residues before proline not including glycine or proline 1440 1441 """ 1442 1443 # Retrieve phi and psi values... 1444 PhiPsiInfoMap = cmd.get_phipsi("(%s)" % SelectionCmd) 1445 if PhiPsiInfoMap is None: 1446 return None 1447 1448 # Sort keys corresponding to model name and residue numbers... 1449 PhiPsiKeys = sorted(PhiPsiInfoMap.keys()) 1450 1451 # Retrieve related information... 1452 PhiPsiInfoList = [] 1453 1454 Category = None 1455 for Key in PhiPsiKeys: 1456 Model, Index = Key 1457 Phi, Psi = PhiPsiInfoMap[Key] 1458 1459 stored.PhiPsiInfoList = [] 1460 cmd.iterate("(%s`%d)" % (Model, Index), "stored.PhiPsiInfoList.append([model, chain, resi, resn])") 1461 for Model, Chain, ResNum, ResName in stored.PhiPsiInfoList: 1462 PhiPsiInfoList.append([Model, Chain, ResNum, ResName, Phi, Psi, Category]) 1463 1464 if Categorize: 1465 _CategorizePhiPsiAnglesInfo(PhiPsiInfoList) 1466 1467 return PhiPsiInfoList 1468 1469 def _CategorizePhiPsiAnglesInfo(PhiPsiInfo): 1470 """The phi and psi angles are optionally categorized into the following groups 1471 corresponding to four types of Ramachandran plots: 1472 1473 General: All residues except glycine, proline, or pre-proline 1474 Glycine: Only glycine residues 1475 Proline: Only proline residues 1476 Pre-Proline: Only residues before proline not including glycine or proline 1477 1478 """ 1479 1480 Index = -1 1481 LastIndex = len(PhiPsiInfo) - 1 1482 PhiPsiCategories = [] 1483 for Model, ChainID, ResNum, ResName, Phi, Psi, CategoryPlaceHolder in PhiPsiInfo: 1484 Index += 1 1485 if re.match("^Gly$", ResName, re.I): 1486 # Gly: Only glycine residues 1487 Category = "Glycine" 1488 elif re.match("^Pro$", ResName, re.I): 1489 # Pro: Only proline residues 1490 Category = "Proline" 1491 elif _IsPreProlinePhiPsiAngle(PhiPsiInfo, Index, LastIndex): 1492 # Pre-Proline: Only residues before proline not including glycine or proline 1493 Category = "Pre-Proline" 1494 else: 1495 # General: All residues except Gly, Pro, or pre-Pro 1496 Category = "General" 1497 # Track categories... 1498 PhiPsiCategories.append(Category) 1499 1500 # Update category in PhiPsiInfo... 1501 CategoryIndex = 6 1502 for Index, Category in enumerate(PhiPsiCategories): 1503 PhiPsiInfo[Index][CategoryIndex] = Category 1504 1505 def _IsPreProlinePhiPsiAngle(PhiPsiInfo, Index, LastIndex): 1506 """Check for Pre-Proline phi and psi angles.""" 1507 1508 # Pre-Proline: Only residues before proline not including glycine or proline 1509 1510 # Not a last residue... 1511 NextIndex = Index + 1 1512 if NextIndex >= LastIndex: 1513 return False 1514 1515 # Next residue is proline... 1516 if not re.match("^Pro$", PhiPsiInfo[NextIndex][3], re.I): 1517 return False 1518 1519 # Current residue is not Gly or Pro... 1520 NextResName = PhiPsiInfo[Index][3] 1521 if re.match("^(Gly|Pro)$", NextResName, re.I): 1522 return False 1523 1524 # Next chain ID is same as current chain ID... 1525 CurrentChainID = PhiPsiInfo[Index][1] 1526 NextChainID = PhiPsiInfo[NextIndex][1] 1527 if not re.match("^%s$" % CurrentChainID, NextChainID): 1528 return False 1529 1530 # Current and next residue numbers are sequential... 1531 CurrentResNum = int(PhiPsiInfo[Index][2]) 1532 NextResNum = int(PhiPsiInfo[NextIndex][2]) 1533 if not (NextResNum - CurrentResNum == 1): 1534 return False 1535 1536 return True 1537 1538 def _GetSelectionResiduesBValuesInfo(SelectionCmd): 1539 """Get B values info for residues in a chain. """ 1540 1541 # Retrieve data... 1542 stored.ResiduesInfo = [] 1543 cmd.iterate(SelectionCmd, "stored.ResiduesInfo.append([resi, resn, b])") 1544 1545 # Setup B-values for each residue... 1546 BValuesInfoMap = {} 1547 BValuesInfoMap["ResIDs"] = [] 1548 BValuesInfoMap["BValue"] = {} 1549 1550 for ResNum, ResName, AtomBValue in stored.ResiduesInfo: 1551 ResID = "%s_%s" % (ResName, ResNum) 1552 1553 if ResID in BValuesInfoMap["BValue"]: 1554 BValuesInfoMap["BValue"][ResID] += AtomBValue 1555 else: 1556 # Track new residue ID... 1557 BValuesInfoMap["ResIDs"].append(ResID) 1558 BValuesInfoMap["BValue"][ResID] = AtomBValue 1559 1560 return BValuesInfoMap 1561 1562 def _GetResiduesInfoFromResiduesBValues(ResiduesBValuesInfoMap, Mode, Cutoff): 1563 """Get residues info map using residues B values. """ 1564 1565 GreaterThanEquals, GreaterThan, LessThanEquals, LessThan, Equals = [False] * 5 1566 if re.match("^>=$", Mode, re.I): 1567 GreaterThanEquals = True 1568 elif re.match("^>$", Mode, re.I): 1569 GreaterThan = True 1570 elif re.match("^<=$", Mode, re.I): 1571 LessThanEquals = True 1572 elif re.match("^<$", Mode, re.I): 1573 LessThan = True 1574 elif re.match("^=$", Mode, re.I): 1575 Equals = True 1576 else: 1577 MiscUtil.PrintError("PyMOLUtil._GetResiduesInfoFromResiduesBValues: The value, %s, specified for Mode is not valid. Supported values: >=, >, <=, <, =") 1578 1579 # Setup residues info map... 1580 ResiduesInfoMap = {} 1581 ResiduesInfoMap["ResNames"] = [] 1582 ResiduesInfoMap["ResNum"] = {} 1583 ResiduesInfoMap["ResCount"] = {} 1584 1585 for ResID in ResiduesBValuesInfoMap["ResIDs"]: 1586 ResName, ResNum = ResID.split("_") 1587 ResBValue = ResiduesBValuesInfoMap["BValue"][ResID] 1588 1589 if GreaterThanEquals: 1590 if ResBValue < Cutoff: 1591 continue 1592 elif GreaterThan: 1593 if ResBValue <= Cutoff: 1594 continue 1595 elif LessThanEquals: 1596 if ResBValue > Cutoff: 1597 continue 1598 elif LessThan: 1599 if ResBValue >= Cutoff: 1600 continue 1601 elif Equals: 1602 if ResBValue != Cutoff: 1603 continue 1604 1605 if ResName in ResiduesInfoMap["ResNames"]: 1606 if not ResNum in ResiduesInfoMap["ResNum"][ResName]: 1607 # Same residue name but different residue number 1608 ResiduesInfoMap["ResNum"][ResName].append(ResNum) 1609 ResiduesInfoMap["ResCount"][ResName] += 1 1610 else: 1611 ResiduesInfoMap["ResNames"].append(ResName) 1612 1613 ResiduesInfoMap["ResNum"][ResName] = [] 1614 ResiduesInfoMap["ResNum"][ResName].append(ResNum) 1615 1616 ResiduesInfoMap["ResCount"][ResName] = 1 1617 1618 return ResiduesInfoMap 1619 1620 def ProcessChainsAndLigandsOptionsInfo(ChainsAndLigandsInfo, ChainsOptionName, ChainsOptionValue, LigandsOptionName = None, LigandsOptionValue = None): 1621 """Process specified chain and ligand IDs using command line options. 1622 1623 Arguments: 1624 ChainsAndLigandsInfo (dict): A dictionary containing information 1625 existing chains and ligands. 1626 ChainsOptionName (str): Name of command line chains option. 1627 ChainsOptionValue (str): Value for command line chains option. 1628 LigandsOptionName (str): Name of command line ligands option. 1629 LigandsOptionValue (str): Value for command line ligands option. 1630 1631 Returns: 1632 dict: A dictionary containing list of chain identifiers and dictionaries 1633 of chains containing lists of ligand names for each chain. 1634 1635 Examples: 1636 1637 ChainsAndLigandsInfo = ProcessChainsAndLigandsOptionsInfo( 1638 ChainsAndLigandsInfo, "-c, --chainIDs", OptionsInfo["ChainIDs"], 1639 "-l, --ligandIDs", OptionsInfo["LigandIDs"]) 1640 for ChainID in ChainsAndLigandsInfo["ChainIDs"]: 1641 for LigandID in ChainsAndLigandsInfo["LigandIDs"][ChainID]: 1642 MiscUtil.PrintInfo("ChainID: %s; LigandID: %s" % (ChainID, 1643 LigandID)) 1644 1645 """ 1646 SpecifiedChainsAndLigandsInfo = {} 1647 SpecifiedChainsAndLigandsInfo["ChainIDs"] = [] 1648 SpecifiedChainsAndLigandsInfo["LigandIDs"] = {} 1649 1650 if ChainsOptionValue is None: 1651 return SpecifiedChainsAndLigandsInfo 1652 1653 _ProcessChainIDs(ChainsAndLigandsInfo, SpecifiedChainsAndLigandsInfo, ChainsOptionName, ChainsOptionValue) 1654 1655 if LigandsOptionValue is None: 1656 return SpecifiedChainsAndLigandsInfo 1657 1658 _ProcessLigandIDs(ChainsAndLigandsInfo, SpecifiedChainsAndLigandsInfo, LigandsOptionName, LigandsOptionValue) 1659 1660 return SpecifiedChainsAndLigandsInfo 1661 1662 def _ProcessChainIDs(ChainsAndLigandsInfo, SpecifiedChainsAndLigandsInfo, ChainsOptionName, ChainsOptionValue): 1663 """Process chain IDs""" 1664 1665 MiscUtil.PrintInfo("Processing chain IDs...") 1666 1667 if re.match("^All$", ChainsOptionValue, re.I): 1668 SpecifiedChainsAndLigandsInfo["ChainIDs"] = ChainsAndLigandsInfo["ChainIDs"] 1669 return 1670 elif re.match("^(First|Auto)$", ChainsOptionValue, re.I): 1671 FirstChainID = ChainsAndLigandsInfo["ChainIDs"][0] if (len(ChainsAndLigandsInfo["ChainIDs"])) else None 1672 if FirstChainID is not None: 1673 SpecifiedChainsAndLigandsInfo["ChainIDs"].append(FirstChainID) 1674 return 1675 1676 ChainIDs = re.sub(" ", "", ChainsOptionValue) 1677 if not ChainIDs: 1678 MiscUtil.PrintError("No valid value specified using \"%s\" option." % ChainsOptionName) 1679 1680 ChainIDsList = ChainsAndLigandsInfo["ChainIDs"] 1681 SpecifiedChainIDsList = [] 1682 1683 ChainIDsWords = ChainIDs.split(",") 1684 for ChainID in ChainIDsWords: 1685 if not ChainID in ChainIDsList: 1686 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))) 1687 continue 1688 if ChainID in SpecifiedChainIDsList: 1689 MiscUtil.PrintWarning("The chain ID, %s, has already been specified using \"%s\" option. It'll be ignored." % (ChainID, ChainsOptionName)) 1690 continue 1691 SpecifiedChainIDsList.append(ChainID) 1692 1693 if not len(SpecifiedChainIDsList): 1694 MiscUtil.PrintError("No valid chain IDs \"%s\" specified using \"%s\" option." % (ChainsOptionValue, ChainsOptionName)) 1695 1696 SpecifiedChainsAndLigandsInfo["ChainIDs"] = SpecifiedChainIDsList 1697 1698 def _ProcessLigandIDs(ChainsAndLigandsInfo, SpecifiedChainsAndLigandsInfo, LigandsOptionName, LigandsOptionValue): 1699 """Process ligand IDs""" 1700 1701 MiscUtil.PrintInfo("Processing ligand IDs...") 1702 1703 # Intialize ligand IDs... 1704 for ChainID in SpecifiedChainsAndLigandsInfo["ChainIDs"]: 1705 SpecifiedChainsAndLigandsInfo["LigandIDs"][ChainID] = [] 1706 1707 if re.match("^All$", LigandsOptionValue, re.I): 1708 for ChainID in SpecifiedChainsAndLigandsInfo["ChainIDs"] : 1709 SpecifiedChainsAndLigandsInfo["LigandIDs"][ChainID] = ChainsAndLigandsInfo["LigandIDs"][ChainID] 1710 return 1711 elif re.match("^(Largest|Auto)$", LigandsOptionValue, re.I): 1712 # Setup largest ligand ID for each chain... 1713 for ChainID in SpecifiedChainsAndLigandsInfo["ChainIDs"] : 1714 LargestLigandID = ChainsAndLigandsInfo["LigandIDs"][ChainID][0] if (len(ChainsAndLigandsInfo["LigandIDs"][ChainID])) else None 1715 if LargestLigandID is not None: 1716 SpecifiedChainsAndLigandsInfo["LigandIDs"][ChainID].append(LargestLigandID) 1717 return 1718 1719 LigandIDs = re.sub(" ", "", LigandsOptionValue) 1720 if not LigandIDs: 1721 MiscUtil.PrintError("No valid value specified using \"%s\" option." % LigandsOptionName) 1722 1723 LigandIDsWords = LigandIDs.split(",") 1724 1725 for ChainID in SpecifiedChainsAndLigandsInfo["ChainIDs"]: 1726 LigandIDsList = ChainsAndLigandsInfo["LigandIDs"][ChainID] 1727 SpecifiedLigandIDsList = [] 1728 1729 for LigandID in LigandIDsWords: 1730 if not LigandID in LigandIDsList: 1731 LigandIDsListNames = ",".join(LigandIDsList) if len(LigandIDsList) else "None" 1732 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)) 1733 continue 1734 if LigandID in SpecifiedLigandIDsList: 1735 MiscUtil.PrintWarning("The ligand ID, %s, has already been specified using \"%s\" option. It'll be ignored." % (LigandID, LigandsOptionName)) 1736 continue 1737 SpecifiedLigandIDsList.append(LigandID) 1738 1739 if not len(SpecifiedLigandIDsList): 1740 MiscUtil.PrintWarning("No valid ligand IDs \"%s\" specified using \"%s\" option for chain ID, %s." % (LigandsOptionValue, LigandsOptionName, ChainID)) 1741 1742 SpecifiedChainsAndLigandsInfo["LigandIDs"][ChainID] = SpecifiedLigandIDsList 1743 1744 def ProcessResidueTypesOptionsInfo(ResidueTypesOptionName, ResidueTypesOptionValue): 1745 """Process specified residue types using command line option. 1746 1747 Arguments: 1748 ResidueTypesOptionName (str): Name of command line option. 1749 ResidueTypesOptionValue (str): Value for command line option. 1750 1751 Returns: 1752 list: A list containing names of valid residue types. 1753 dict: A dictionary containing residue types pointing to dictionaries of 1754 color names and list of residues for a residue type. 1755 1756 Examples: 1757 1758 ResidueTypesNamesInfo, ResidueTypesParamsInfo = 1759 ProcessChainsAndLigandsOptionsInfo("-r, --residueTypes", 1760 OptionsInfo["ResidueTypes"]) 1761 for ResidueTypeName in ResidueTypesNamesInfo: 1762 MiscUtil.PrintInfo("ResidueType: %s; Color: %s; Residues: %s" % 1763 (ResidueTypeName, ResidueTypeName[ResidueTypeName]["Color"], 1764 " ".join(ResidueTypeName[ResidueTypeName]["Residues"])) 1765 1766 """ 1767 1768 # Set up default values for residue types, colors, and names. 1769 ResidueTypesNamesInfo = ["Aromatic", "Hydrophobic", "Polar", "Positively_Charged", "Negatively_Charged"] 1770 1771 ResidueTypesParamsInfo = {} 1772 ResidueTypesParamsInfo["Aromatic"] = {"Color": "brightorange", "Residues" : ["HIS", "PHE", "TRP", "TYR"]} 1773 ResidueTypesParamsInfo["Hydrophobic"] = {"Color": "orange", "Residues" : ["ALA", "GLY", "VAL", "LEU", "ILE", "PRO", "MET"]} 1774 ResidueTypesParamsInfo["Polar"] = {"Color": "palegreen", "Residues" : ["ASN", "GLN", "SER", "THR", "CYS"]} 1775 ResidueTypesParamsInfo["Positively_Charged"] = {"Color": "marine", "Residues" : ["ARG", "LYS"]} 1776 ResidueTypesParamsInfo["Negatively_Charged"] = {"Color": "red", "Residues" : ["ASP", "GLU"]} 1777 1778 ResidueTypes = ResidueTypesOptionValue 1779 if re.match("^auto$", ResidueTypesOptionValue, re.I): 1780 _SetupOtherResidueTypes(ResidueTypesParamsInfo) 1781 return ResidueTypesNamesInfo, ResidueTypesParamsInfo 1782 1783 # Parse specified residue types... 1784 ResidueTypesWords = ResidueTypes.split(",") 1785 if len(ResidueTypesWords) % 3: 1786 MiscUtil.PrintError("The number of comma delimited residue type, color, and name triplets, %d, specified using \"%s\" option must be a multple of 3." % (len(ResidueTypesWords), ResidueTypesOptionName)) 1787 1788 # Set up canonical residue type names... 1789 ValidResidueTypeNames = [] 1790 CanonicalResidueTypeNamesMap = {} 1791 for Name in sorted(ResidueTypesNamesInfo): 1792 ValidResidueTypeNames.append(Name) 1793 CanonicalResidueTypeNamesMap[Name.lower()] = Name 1794 1795 # Validate and set residue types, colors, and names.. 1796 for Index in range(0, len(ResidueTypesWords), 3): 1797 TypeName = ResidueTypesWords[Index].strip() 1798 ResidueTypeColor = ResidueTypesWords[Index + 1].strip() 1799 ResidueNames = ResidueTypesWords[Index + 2].strip() 1800 1801 ResidueNames = re.sub("[ ]+", " ", ResidueNames) 1802 ResidueNamesWords = ResidueNames.split(" ") 1803 1804 CanonicalTypeName = TypeName.lower() 1805 if not CanonicalTypeName in CanonicalResidueTypeNamesMap: 1806 MiscUtil.PrintError("The residue type, %s, specified using \"%s\" option is not a valid type. Supported residue types: %s" % (TypeName, ResidueTypesOptionName, ", ".join(ValidResidueTypeNames))) 1807 ResidueTypeName = CanonicalResidueTypeNamesMap[CanonicalTypeName] 1808 1809 if not ResidueTypeColor: 1810 MiscUtil.PrintError("No color name specified for residue type, %s, using \"%s\" option, %s" % (TypeName, ResidueTypesOptionName, ResidueTypes)) 1811 1812 if not ResidueNames: 1813 MiscUtil.PrintError("No residue names specified for residue type, %s, using \"%s\" option, %s" % (TypeName, ResidueTypesOptionName, ResidueTypes)) 1814 1815 ResidueTypesParamsInfo[ResidueTypeName]["Color"] = ResidueTypeColor 1816 ResidueTypesParamsInfo[ResidueTypeName]["Residues"] = ResidueNamesWords 1817 1818 SetupOtherResidueTypes() 1819 return ResidueTypesNamesInfo, ResidueTypesParamsInfo 1820 1821 def _SetupOtherResidueTypes(ResidueTypesParamsInfo): 1822 """Setup other residue types.""" 1823 1824 # Set other residues to all specified residues. The other residues are selected by 1825 # performing a negation operation on this list during the creation of PyMOL objects. 1826 1827 ResidueNames = [] 1828 for ResiduesType in ResidueTypesParamsInfo: 1829 ResidueNames.extend(ResidueTypesParamsInfo[ResiduesType]["Residues"] ) 1830 1831 ResidueTypesParamsInfo["Other"]= {} 1832 ResidueTypesParamsInfo["Other"]["Color"] = None 1833 ResidueTypesParamsInfo["Other"]["Residues"] = ResidueNames 1834 1835 def ProcessSurfaceAtomTypesColorsOptionsInfo(ColorOptionName, ColorOptionValue): 1836 """Process specified surafce atom types colors using command line option. 1837 1838 Arguments: 1839 ColorOptionName (str): Name of command line option. 1840 ColorOptionValue (str): Value for command line option. 1841 1842 Returns: 1843 dict: A dictionary containing atom types and colors. 1844 1845 Examples: 1846 1847 AtomTypesColorNamesInfo = 1848 PyMOLUtil.ProcessSurfaceAtomTypesColorsOptionsInfo( 1849 "--surfaceAtomTypesColors", OptionsInfo["SurfaceAtomTypesColors"]) 1850 1851 """ 1852 1853 # Set up default values for atom type colors... 1854 AtomTypesColorNamesInfo = {"HydrophobicAtomsColor": "yellow", "NegativelyChargedAtomsColor": "red", "PositivelyChargedAtomsColor": "blue", "OtherAtomsColor": "gray90"} 1855 1856 AtomTypesColors = ColorOptionValue 1857 if re.match("^auto$", AtomTypesColors, re.I): 1858 return AtomTypesColorNamesInfo 1859 1860 # Parse atom type colors and values... 1861 AtomTypesColorsWords = AtomTypesColors.split(",") 1862 if len(AtomTypesColorsWords) % 2: 1863 MiscUtil.PrintError("The number of comma delimited surface atom color types and values, %d, specified using \"%s\" option must be a multple of 2." % (len(AtomTypesColorsWords), ColorOptionName)) 1864 1865 # Set up canonical atom type colors... 1866 ValidAtomTypesColors = [] 1867 CanonicalAtomTypesColorsMap = {} 1868 for Type in sorted(AtomTypesColorNamesInfo): 1869 ValidAtomTypesColors.append(Type) 1870 CanonicalAtomTypesColorsMap[Type.lower()] = Type 1871 1872 # Validate and process specified values... 1873 for Index in range(0, len(AtomTypesColorsWords), 2): 1874 Type = AtomTypesColorsWords[Index].strip() 1875 Color = AtomTypesColorsWords[Index + 1].strip() 1876 1877 Color = re.sub("[ ]+", " ", Color) 1878 ColorWords = Color.split(" ") 1879 1880 CanonicalType = Type.lower() 1881 if not CanonicalType in CanonicalAtomTypesColorsMap: 1882 MiscUtil.PrintError("The surface atom color type, %s, specified using \"%s\" option is not a valid type: Supported atom color types: %s" % (Type, ColorOptionName, ", ".join(ValidAtomTypesColors))) 1883 Type = CanonicalAtomTypesColorsMap[CanonicalType] 1884 1885 if not Color: 1886 MiscUtil.PrintError("No color type specified for atom color type, %s, using \"%s\" option." % (Type, ColorOptionName)) 1887 1888 ColorWordsLen = len(ColorWords) 1889 if not (ColorWordsLen == 1 or ColorWordsLen == 3): 1890 MiscUtil.PrintError("The number, %s, of color name or space delimited RGB values, %s, specified for atom color type, %s, using \"%s\" option must be 1 or 3." % (ColorWordsLen, Color, ColorOptionName, Type)) 1891 1892 AtomTypesColorNamesInfo[Type] = " ".join(ColorWords) 1893 1894 return AtomTypesColorNamesInfo 1895 1896 def ProcessSaltBridgesChainResiduesOptionsInfo(SaltBridgesOptionName, SaltBridgesOptionValue): 1897 """Process specified salt bridges chain residues using command line option. 1898 1899 Arguments: 1900 SaltBridgesOptionName (str): Name of command line option. 1901 SaltBridgesOptionValue (str): Value for command line option. 1902 1903 Returns: 1904 dict: A dictionary containing salt bridges residue types and residue 1905 names. 1906 1907 Examples: 1908 1909 SaltBridgesChainResiduesInfo = 1910 PyMOLUtil.ProcessSaltBridgesChainResiduesOptionsInfo( 1911 "--saltBridgesChainResidues", OptionsInfo["SaltBridgesChainResidues"]) 1912 1913 """ 1914 1915 # Set up default values for salt bridges chain residues... 1916 SaltBridgesChainResiduesInfo = {"Positively_Charged": ["ARG", "LYS", "HIS", "HSP"], "Negatively_Charged": ["ASP", "GLU"]} 1917 1918 SaltBridgesChainResidues = SaltBridgesOptionValue 1919 if re.match("^auto$", SaltBridgesChainResidues, re.I): 1920 return SaltBridgesChainResiduesInfo 1921 1922 # Parse salt bridges chain residues types and residue names... 1923 SaltBridgesChainResiduesWords = SaltBridgesChainResidues.split(",") 1924 if len(SaltBridgesChainResiduesWords) % 2: 1925 MiscUtil.PrintError("The number of comma delimited salt bridges residue types and names, %d, specified using \"%s\" option must be a multple of 2." % (len(SaltBridgesChainResiduesWords), SaltBridgesOptionName)) 1926 1927 # Set up canonical salt bridges chain residue types... 1928 ValidSaltBridgesChainResidueTypes = [] 1929 CanonicalSaltBridgesChainResiduesMap = {} 1930 for Type in sorted(SaltBridgesChainResiduesInfo): 1931 ValidSaltBridgesChainResidueTypes.append(Type) 1932 CanonicalSaltBridgesChainResiduesMap[Type.lower()] = Type 1933 1934 # Validate and process specified values... 1935 for Index in range(0, len(SaltBridgesChainResiduesWords), 2): 1936 Type = SaltBridgesChainResiduesWords[Index].strip() 1937 Residue = SaltBridgesChainResiduesWords[Index + 1].strip() 1938 1939 Residue = re.sub("[ ]+", " ", Residue) 1940 ResidueWords = Residue.split(" ") 1941 1942 CanonicalType = Type.lower() 1943 if not CanonicalType in CanonicalSaltBridgesChainResiduesMap: 1944 MiscUtil.PrintError("The salt bridges chain residue type, %s, specified using \"%s\" option is not a valid type: Supported salt bridges chain residue types: %s" % (Type, SaltBridgesOptionName, ", ".join(ValidSaltBridgesChainResidueTypes))) 1945 Type = CanonicalSaltBridgesChainResiduesMap[CanonicalType] 1946 1947 if not Residue or len(ResidueWords) == 0: 1948 MiscUtil.PrintError("No residue specified for salt bridges chain residue type, %s, using \"%s\" option." % (Type, SaltBridgesOptionName)) 1949 1950 SaltBridgesChainResiduesInfo[Type] = ResidueWords 1951 1952 return SaltBridgesChainResiduesInfo 1953 1954 def ProcessChainSelectionsOptionsInfo(SelectionOptionName, SelectionOptionValue): 1955 """Process names and selections specified using command line option. It 1956 is a pairwise list comma delimited values corresponding to PyMOL object 1957 names and selection specification 1958 1959 Arguments: 1960 SelectionOptionName (str): Name of command line option. 1961 SelectionOptionValue (str): Value for command line option. 1962 1963 Returns: 1964 dict: A dictionary containing lists f names and selection commands. 1965 1966 Examples: 1967 1968 ChainSelectionsInfo = 1969 PyMOLUtil.ProcessChainSelectionsOptionsInfo("--selectionsChain", 1970 OptionsInfo["SelectionChains"]) 1971 1972 """ 1973 1974 # Initialize... 1975 ChainSelectionsInfo = {} 1976 ChainSelectionsInfo["Names"] = [] 1977 ChainSelectionsInfo["Selections"] = [] 1978 1979 if re.match("^None$", SelectionOptionValue, re.I): 1980 return ChainSelectionsInfo 1981 1982 # Parse selection chains names and selections... 1983 ChainSelectionsWords = SelectionOptionValue.split(",") 1984 if len(ChainSelectionsWords) % 2: 1985 MiscUtil.PrintError("The number of comma delimited selection chains names and selections, %d, specified using \"%s\" option must be a multple of 2." % (len(ChainSelectionsWords), SelectionOptionName)) 1986 1987 CanonicalNamesMap = {} 1988 for Index in range(0, len(ChainSelectionsWords), 2): 1989 Name = ChainSelectionsWords[Index].strip() 1990 Selection = ChainSelectionsWords[Index + 1].strip() 1991 1992 if not len(Name): 1993 MiscUtil.PrintError("A name specified, \"%s\", using \"%s\" option is empty." % (SelectionOptionValue, SelectionOptionName)) 1994 if not len(Selection): 1995 MiscUtil.PrintError("A selection specified, \"%s\", using \"%s\" option is empty." % (SelectionOptionValue, SelectionOptionName)) 1996 1997 CanonicalName = Name.lower() 1998 if CanonicalName in CanonicalNamesMap: 1999 MiscUtil.PrintError("The name %s specified using \"%s\" option is a duplicate name." % (Name, SelectionOptionName)) 2000 CanonicalNamesMap[CanonicalName] = Name 2001 2002 if re.search("[^a-zA-Z0-9 _\-]", Name, re.I): 2003 MiscUtil.PrintError("The name %s specified using \"%s\" option contains invalid charactors. Supportted characters: alphanumeric, space, hyphen and underscore.." ) 2004 2005 ChainSelectionsInfo["Names"].append(Name) 2006 ChainSelectionsInfo["Selections"].append(Selection) 2007 2008 return ChainSelectionsInfo 2009 2010 def CalculateCenterOfMass(Selection = "all", Quiet = 0): 2011 """Calculate center of mass for a selection. 2012 2013 Arguments: 2014 Selection (str): A PyMOL selection. 2015 Quiet (int): Print information. 2016 2017 Returns: 2018 list: X, Y, Z coordinates for center of mass. 2019 2020 """ 2021 MassTotal = 0.0 2022 X, Y, Z = [0.0, 0.0, 0.0] 2023 2024 Atoms = cmd.get_model(Selection) 2025 for Atom in Atoms.atom: 2026 Mass = Atom.get_mass() 2027 MassTotal += Mass 2028 2029 X += Atom.coord[0] * Mass 2030 Y += Atom.coord[1] * Mass 2031 Z += Atom.coord[2] * Mass 2032 2033 XCOM = X/MassTotal 2034 YCOM = Y/MassTotal 2035 ZCOM = Z/MassTotal 2036 2037 if not Quiet: 2038 MiscUtil.PrintInfo("PyMOLUtil.CalculateCenterOfMass: %f, %f, %f" % (XCOM, YCOM, ZCOM)) 2039 2040 return [XCOM, YCOM, ZCOM] 2041 2042 def ConvertFileFormat(Infile, Outfile, Reinitialize = True, OutputFeedback = True): 2043 """Convert infile to outfile by automatically detecting their formats 2044 from the file extensions. 2045 2046 The formats of both input and output files must be a valid format supported 2047 by PyMOL. 2048 2049 Arguments: 2050 Infile (str): Name of input file. 2051 Outfile (str): Name of outfile file. 2052 Reinitialize (bool): Reinitialize PyMOL before loading input file. 2053 OutputFeedback (bool): Control output feedback. 2054 2055 """ 2056 2057 if not os.path.exists(Infile): 2058 MiscUtil.PrintWarning("The input file, %s, doesn't exists.%s..." % (Infile)) 2059 2060 if Reinitialize: 2061 cmd.reinitialize() 2062 2063 if not OutputFeedback: 2064 # Turn off output feedback... 2065 MiscUtil.PrintInfo("Disabling output feedback for PyMOL...") 2066 cmd.feedback("disable", "all", "output") 2067 2068 FileDir, FileName, FileExt = MiscUtil.ParseFileName(Infile) 2069 MolName = FileName 2070 2071 cmd.load(Infile, MolName) 2072 cmd.save(Outfile, MolName) 2073 cmd.delete(MolName) 2074 2075 if not OutputFeedback: 2076 # Turn it back on... 2077 MiscUtil.PrintInfo("\nEnabling output feedback for PyMOL...") 2078 cmd.feedback("enable", "all", "output") 2079 2080 def ConvertPMLFileToPSEFile(PMLFile, PSEFile, Reinitialize = True, OutputFeedback = True): 2081 """Convert PML file to PME file. 2082 2083 Arguments: 2084 PMLFile (str): Name of PML file. 2085 PSEFile (str): Name of PSE file. 2086 Reinitialize (bool): Reinitialize PyMOL before loading PML file. 2087 OutputFeedback (bool): Control output feedback. 2088 2089 """ 2090 2091 if not os.path.exists(PMLFile): 2092 MiscUtil.PrintWarning("The PML file, %s, doesn't exists.%s..." % (PMLFile)) 2093 2094 if Reinitialize: 2095 cmd.reinitialize() 2096 2097 if not OutputFeedback: 2098 # Turn off output feedback... 2099 MiscUtil.PrintInfo("Disabling output feedback for PyMOL...") 2100 cmd.feedback("disable", "all", "output") 2101 2102 cmd.do("@%s" % PMLFile) 2103 cmd.save(PSEFile) 2104 2105 if not OutputFeedback: 2106 # Turn it back on... 2107 MiscUtil.PrintInfo("\nEnabling output feedback for PyMOL...") 2108 cmd.feedback("enable", "all", "output") 2109 2110 def SetupPMLHeaderInfo(ScriptName = None, IncludeLocalPython = True): 2111 """Setup header information for generating PML files. The local Python 2112 functions are optionally embedded in the header information for their 2113 use in PML files. 2114 2115 Arguments: 2116 ScriptName (str): Name of script calling the function. 2117 IncludeLocalPython (bool): Include local Python functions. 2118 2119 Returns: 2120 str: Text containing header information for generating PML files. 2121 2122 """ 2123 if ScriptName is None: 2124 HeaderInfo = """\ 2125 # 2126 # This file is automatically generated by a script available in MayaChemTools. 2127 # 2128 cmd.reinitialize()""" 2129 else: 2130 HeaderInfo = """\ 2131 # 2132 # This file is automatically generated by the following PyMOL script available in 2133 # MayaChemTools: %s 2134 # 2135 cmd.reinitialize() """ % (ScriptName) 2136 2137 if IncludeLocalPython: 2138 PMLForLocalPython = _SetupPMLForLocalPython() 2139 HeaderInfo = "%s\n\n%s" % (HeaderInfo, PMLForLocalPython) 2140 2141 return HeaderInfo 2142 2143 def _SetupPMLForLocalPython(): 2144 """Setup local Python functions for PML file. 2145 """ 2146 2147 PMLForPython = """\ 2148 "" 2149 "Setting up local Python functions for PML script..." 2150 "" 2151 python 2152 2153 from __future__ import print_function 2154 import re 2155 2156 def ColorByHydrophobicity(Selection, ColorPalette = "RedToWhite"): 2157 \"""Color by hydrophobicity using hydrophobic values for amino acid 2158 residues corresponding to the Eisenberg hydrophobicity scale. 2159 2160 Possible values for ColorPalette: RedToWhite or WhiteToGreen from most 2161 hydrophobic amino acid to least hydrophobic. 2162 2163 The colors values for amino acids are taken from color_h script avaiable 2164 as part of the Script Library at PyMOL Wiki. 2165 2166 \""" 2167 2168 if not re.match("^(RedToWhite|WhiteToGreen)$", ColorPalette, re.I): 2169 print("Invalid ColorPalette value: %s. Valid values: RedToWhite, WhiteToGreen" % ColorPalette) 2170 2171 ResColors = {} 2172 ColorType = "" 2173 2174 if re.match("^WhiteToGreen$", ColorPalette, re.I): 2175 ColorType = "H2" 2176 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]} 2177 else: 2178 ColorType = "H1" 2179 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]} 2180 2181 # Set up colors... 2182 for ResName in ResColors: 2183 ColorName = "color_%s_%s" % (ResName, ColorType) 2184 cmd.set_color(ColorName, ResColors[ResName]) 2185 2186 ResSelection = "(%s and resn %s*)" % (Selection, ResName) 2187 cmd.color(ColorName, ResSelection) 2188 2189 cmd.extend("ColorByHydrophobicity", ColorByHydrophobicity) 2190 2191 def ColorAtomsByHydrophobicityAndCharge(Selection, HydrophobicAtomsColor = "yellow", NegativelyChargedAtomsColor = "red", PositivelyChargedAtomsColor = "blue", OtherAtomsColor = "gray90"): 2192 \"""Color atoms in amino acids by their propensity to make hydrophobic and 2193 charge interactions [REF 140]. The atom names in standard amino acid 2194 residues are used to identify atom types as shown below: 2195 2196 Hydrophobic: C atoms not bound to N or O atoms 2197 NegativelyCharged: Side chain O atoms in ASP and GLU 2198 PositivelyCharged: Side chain N atoms in ARG and LYS 2199 Others: Remaining atoms in polar and other residues 2200 2201 The following color scheme is used by default: 2202 2203 Hydrophobic: yellow 2204 NegativelyCharged: red 2205 PositivelyCharged: blue 2206 Others: gray90 2207 2208 The amino acid atom names to color specific atoms are taken from YRB.py 2209 script [ REF 140]. The color values may also be specified as comma delimited 2210 RGB triplets. For example: HydrophobicAtomsColor = "0.950 0.78 0.0", 2211 NegativelyChargedAtomsColor = "1.0 0.4 0.4", PositivelyChargedAtomsColor 2212 = "0.2 0.5 0.8", OtherAtomsColor = "0.95 0.95 0.95" 2213 2214 \""" 2215 2216 # Process colors... 2217 Colors = {"HydrophobicAtomsColor": HydrophobicAtomsColor, "NegativelyChargedAtomsColor": NegativelyChargedAtomsColor, "PositivelyChargedAtomsColor": PositivelyChargedAtomsColor, "OtherAtomsColor": OtherAtomsColor} 2218 ColorsRGB = {} 2219 for ColorKey, ColorValue in Colors.items(): 2220 if re.search(" ", ColorValue): 2221 ColorRGB = ColorValue.split(" ") 2222 else: 2223 ColorRGB = cmd.get_color_tuple(cmd.get_color_index(ColorValue)) 2224 ColorsRGB[ColorKey] = ColorRGB 2225 2226 # Set up colors... 2227 for ColorKey, ColorValue in ColorsRGB.items(): 2228 cmd.set_color(ColorKey, ColorValue) 2229 2230 # Set up colors for atom names across all resiudes... 2231 AtomColors = {"OtherAtomsColor": "N,C,CA,O", "HydrophobicAtomsColor": "CB"} 2232 2233 # Set up colors for atom names across specific resiudes... 2234 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"}} 2235 2236 # Color atom names across all resiudes... 2237 for ColorName in AtomColors: 2238 AtomNames = AtomColors[ColorName] 2239 AtomsSelection = "(%s and name %s)" % (Selection, AtomNames) 2240 cmd.color(ColorName, AtomsSelection) 2241 2242 # Color hydrogen atoms across all residues to other color... 2243 AtomsSelection = "(%s and hydro)" % (Selection) 2244 cmd.color("OtherAtomsColor", AtomsSelection) 2245 2246 # Color atom names across specific resiudes... 2247 for ResName in ResAtomColors: 2248 for ColorName in ResAtomColors[ResName]: 2249 AtomNames = ResAtomColors[ResName][ColorName] 2250 AtomsSelection = "(%s and resn %s and name %s)" % (Selection, ResName, AtomNames) 2251 cmd.color(ColorName, AtomsSelection) 2252 2253 cmd.extend("ColorAtomsByHydrophobicityAndCharge", ColorAtomsByHydrophobicityAndCharge) 2254 2255 def CheckAndDeleteEmptyObjects(ObjectNames, ParentObjectName = None): 2256 \"""Delete an empty objects along with optionally deleting their parent. 2257 2258 \""" 2259 2260 ObjectNamesList = ObjectNames.split(",") 2261 2262 AllObjectsEmpty = True 2263 for ObjectName in ObjectNamesList: 2264 ObjectName = ObjectName.strip() 2265 if cmd.count_atoms("(%s)" % ObjectName): 2266 AllObjectsEmpty = False 2267 else: 2268 cmd.delete("%s" % ObjectName) 2269 2270 if AllObjectsEmpty and ParentObjectName is not None: 2271 cmd.delete("%s" % ParentObjectName) 2272 2273 cmd.extend("CheckAndDeleteEmptyObjects", CheckAndDeleteEmptyObjects) 2274 2275 python end""" 2276 2277 return PMLForPython 2278 2279 def SetupPMLForEnableDisable(Name, Enable = True): 2280 """Setup PML command for enabling or disabling display of a PyMOL object. 2281 2282 Arguments: 2283 Name (str): Name of a PyMOL object. 2284 Enable (bool): Display status. 2285 2286 Returns: 2287 str: PML command for enabling or disabling display of an object. 2288 2289 """ 2290 2291 if Enable: 2292 PML = """cmd.enable("%s")""" % Name 2293 else: 2294 PML = """cmd.disable("%s")""" % Name 2295 2296 return PML 2297 2298 def SetupPMLForGroup(GroupName, GroupMembersList, Enable = None, Action = None): 2299 """Setup PML commands for creating a group from a list of group members. The 2300 display and open status of the group may be optionally set. The 'None' values 2301 for Enable and Action imply usage of PyMOL defaults for the creation of group. 2302 2303 Arguments: 2304 GroupName (str): Name of a PyMOL group. 2305 GroupMembersList (list): List of group member names. 2306 Enable (bool): Display status of group. 2307 Action (str): Open or close status of group object. 2308 2309 Returns: 2310 str: PML commands for creating a group object. 2311 2312 """ 2313 2314 PMLCmds = [] 2315 2316 GroupMembers = " ".join(GroupMembersList) 2317 PMLCmds.append("""cmd.group("%s", "%s")""" % (GroupName, GroupMembers)) 2318 2319 if Enable is not None: 2320 if Enable: 2321 PMLCmds.append("""cmd.enable("%s")""" % GroupName) 2322 else: 2323 PMLCmds.append("""cmd.disable("%s")""" % GroupName) 2324 2325 if Action is not None: 2326 PMLCmds.append("""cmd.group("%s", action="%s")""" % (GroupName, Action)) 2327 2328 PML = "\n".join(PMLCmds) 2329 2330 return PML 2331 2332 def SetupPMLForLigandView(Name, Selection, LigandResName, Enable = True, IgnoreHydrogens = False): 2333 """Setup PML commands for creating a ligand view corresponding to a ligand 2334 present in a selection. The ligand is identified using organic selection 2335 operator available in PyMOL in conjunction with the specified ligand ID. 2336 The ligand is colored by atom types and displayed as 'sticks'. 2337 2338 Arguments: 2339 Name (str): Name of a new PyMOL ligand object. 2340 Selection (str): PyMOL selection containing ligand. 2341 LigandResName (str): Ligand ID. 2342 Enable (bool): Display status of ligand object. 2343 IgnoreHydrogens (bool): Ignore hydrogens. 2344 2345 Returns: 2346 str: PML commands for a ligand view. 2347 2348 """ 2349 2350 PMLCmds = [] 2351 2352 IgnoreHydrogensClause = " and (not hydro)" if IgnoreHydrogens else "" 2353 PMLCmds.append("""cmd.create("%s", "((%s) and organic and (resn %s)%s)")""" % (Name, Selection, LigandResName, IgnoreHydrogensClause)) 2354 2355 PMLCmds.append("""cmd.hide("everything", "%s")""" % (Name)) 2356 PMLCmds.append("""util.cbag("%s", _self = cmd)""" % (Name)) 2357 PMLCmds.append("""cmd.show("sticks", "%s")""" % (Name)) 2358 PMLCmds.append(SetupPMLForEnableDisable(Name, Enable)) 2359 2360 PML = "\n".join(PMLCmds) 2361 2362 return PML 2363 2364 def SetupPMLForLigandsInputFileView(Name, InputFile, Enable = True, IgnoreHydrogens = False): 2365 """Setup PML commands for creating a ligand view corresponding to ligands 2366 present in a SD file. The ligand is colored by atom types and displayed as 'sticks'. 2367 2368 Arguments: 2369 Name (str): Name of a new PyMOL ligand(s) object. 2370 InputFile (str): Name of input file. 2371 Enable (bool): Display status of ligand object. 2372 IgnoreHydrogens (bool): Ignore hydrogens. 2373 2374 Returns: 2375 str: PML commands for a ligand view. 2376 2377 """ 2378 2379 PMLCmds = [] 2380 2381 PMLCmds.append("""cmd.load("%s", "%s")""" % (InputFile, Name)) 2382 2383 PMLCmds.append("""cmd.hide("everything", "%s")""" % (Name)) 2384 PMLCmds.append("""util.cbag("%s", _self = cmd)""" % (Name)) 2385 PMLCmds.append("""cmd.show("sticks", "%s")""" % (Name)) 2386 if IgnoreHydrogens: 2387 PMLCmds.append("""cmd.remove("(%s and hydro)")""" % (Name)) 2388 2389 PMLCmds.append(SetupPMLForEnableDisable(Name, Enable)) 2390 2391 PML = "\n".join(PMLCmds) 2392 2393 return PML 2394 2395 def SetupPMLForLigandPocketView(Name, Selection, LigandSelection, DistanceCutoff, Enable = True, IgnoreHydrogens = False): 2396 """Setup PML commands for creating a ligand binding pocket view 2397 corresponding all residues present in a selection within a specified 2398 distance from a ligand selection. The solvent and inorganic portions of 2399 the selection are not included in the binding pocket. The pocket residues 2400 are shown as 'lines'. The hydrogen atoms are not displayed. 2401 2402 Arguments: 2403 Name (str): Name of a new PyMOL binding pocket object. 2404 Selection (str): PyMOL selection containing binding pocket residues. 2405 LigandSelection (str): PyMOL selection containing ligand. 2406 DistanceCutoff (float): Distance cutoff from ligand for selecting 2407 binding pockect residues. 2408 Enable (bool): Display status of binding pocket object. 2409 IgnoreHydrogens (bool): Ignore hydrogens. 2410 2411 Returns: 2412 str: PML commands for a ligand binding pocket view. 2413 2414 """ 2415 2416 PMLCmds = [] 2417 2418 IgnoreHydrogensClause = " and (not hydro)" if IgnoreHydrogens else "" 2419 PMLCmds.append("""cmd.create("%s", "((byresidue (%s) within %.1f of (%s)) and (not solvent) and (not inorganic) and (not organic)%s)")""" % (Name, Selection, DistanceCutoff, LigandSelection, IgnoreHydrogensClause)) 2420 2421 PMLCmds.append("""cmd.hide("everything", "%s")""" % (Name)) 2422 PMLCmds.append("""cmd.show("lines", "(%s)")""" % (Name)) 2423 PMLCmds.append("""cmd.hide("(%s and hydro)")""" % (Name)) 2424 PMLCmds.append(SetupPMLForEnableDisable(Name, Enable)) 2425 2426 PML = "\n".join(PMLCmds) 2427 2428 return PML 2429 2430 def SetupPMLForLigandPocketSolventView(Name, Selection, LigandSelection, DistanceCutoff, Enable = True): 2431 """Setup PML commands for creating a ligand binding pocket view 2432 corresponding to only solvent residues present in a selection within a 2433 specified distance from a ligand selection. The solvent pocket residues 2434 are shown as 'lines' and 'nonbonded'. 2435 2436 Arguments: 2437 Name (str): Name of a new PyMOL solvent binding pocket object. 2438 Selection (str): PyMOL selection containing binding pocket residues. 2439 LigandSelection (str): PyMOL selection containing ligand. 2440 DistanceCutoff (float): Distance cutoff from ligand for selecting 2441 binding pocket solvent residues. 2442 Enable (bool): Display status of binding pocket object. 2443 2444 Returns: 2445 str: PML commands for a ligand binding pocket view only showing solvent 2446 residues. 2447 2448 """ 2449 2450 PMLCmds = [] 2451 PMLCmds.append("""cmd.create("%s", "((byresidue (%s) within %.1f of (%s)) and solvent)")""" % (Name, Selection, DistanceCutoff, LigandSelection)) 2452 PMLCmds.append("""cmd.hide("everything", "%s")""" % (Name)) 2453 PMLCmds.append("""cmd.show("nonbonded", "%s")""" % (Name)) 2454 PMLCmds.append("""cmd.show("lines", "%s")""" % (Name)) 2455 PMLCmds.append(SetupPMLForEnableDisable(Name, Enable)) 2456 2457 PML = "\n".join(PMLCmds) 2458 2459 return PML 2460 2461 def SetupPMLForLigandPocketInorganicView(Name, Selection, LigandSelection, DistanceCutoff, Enable = True): 2462 """Setup PML commands for creating a ligand binding pocket view 2463 corresponding to only inorganic residues present in a selection within a 2464 specified distance from a ligand selection. The inorganic pocket residues 2465 are shown as 'lines' and 'nonbonded'. 2466 2467 Arguments: 2468 Name (str): Name of a new PyMOL solvent binding pocket object. 2469 Selection (str): PyMOL selection containing binding pocket residues. 2470 LigandSelection (str): PyMOL selection containing ligand. 2471 DistanceCutoff (float): Distance cutoff from ligand for selecting 2472 binding pocket inorganic residues. 2473 Enable (bool): Display status of binding pocket object. 2474 2475 Returns: 2476 str: PML commands for a ligand binding pocket view only showing inorganic 2477 residues. 2478 2479 """ 2480 2481 PMLCmds = [] 2482 PMLCmds.append("""cmd.create("%s", "((byresidue (%s) within %.1f of (%s)) and inorganic)")""" % (Name, Selection, DistanceCutoff, LigandSelection)) 2483 PMLCmds.append("""cmd.hide("everything", "%s")""" % (Name)) 2484 PMLCmds.append("""cmd.show("nonbonded", "%s")""" % (Name)) 2485 PMLCmds.append("""cmd.show("lines", "%s")""" % (Name)) 2486 PMLCmds.append(SetupPMLForEnableDisable(Name, Enable)) 2487 2488 PML = "\n".join(PMLCmds) 2489 2490 return PML 2491 2492 def SetupPMLForDistanceContactsView(Name, Selection1, Selection2, Enable = True, Color = "yellow", Cutoff = None, IgnoreHydrogens = True): 2493 """Setup PML commands for creating distance contacts view between a pair of 2494 selections. The distance contact view is generated using 'cmd.distance' command. 2495 The distance labels are shown by default. 2496 2497 Arguments: 2498 Name (str): Name of a new PyMOL distance contacts object. 2499 Selection1 (str): First PyMOL selection. 2500 Selection2 (str): Second PyMOL selection. 2501 Enable (bool): Display status of distance contacts object. 2502 Color (str): Color for distance contact lines and labels. 2503 DistanceCutoff (float): None or distance cutoff for distance contacts. 2504 IgnoreHydrogens (bool): Ignore hydrogens for distance contacts. 2505 2506 Returns: 2507 str: PML commands for distance contacts view between a pair of selections. 2508 2509 """ 2510 2511 if IgnoreHydrogens: 2512 Selection1 = "(%s) and (not hydro)" % Selection1 2513 Selection2 = "(%s) and (not hydro)" % Selection2 2514 2515 PMLCmds = [] 2516 if Cutoff is None: 2517 PMLCmds.append("""cmd.distance("%s","(%s)","(%s)", quiet = 1, mode = 0, label = 1, reset = 1)""" % (Name, Selection1, Selection2)) 2518 else: 2519 PMLCmds.append("""cmd.distance("%s","(%s)","(%s)", cutoff = %.1f, quiet = 1, mode = 0, label = 1, reset = 1)""" % (Name, Selection1, Selection2, Cutoff)) 2520 2521 PMLCmds.append(SetupPMLForDeepColoring(Name, Color)) 2522 PMLCmds.append(SetupPMLForEnableDisable(Name, Enable)) 2523 2524 PML = "\n".join(PMLCmds) 2525 2526 return PML 2527 2528 def SetupPMLForHalogenContactsView(Name, Selection1, Selection2, Enable = True, Color = "magenta", Cutoff = None, IgnoreHydrogens = True): 2529 """Setup PML commands for creating halogen distance contacts view between a 2530 pair of selections. The Selection1 corresponds to the selection containing halogens. 2531 The halogen contact view is generated using 'cmd.distance' command. The 2532 distance labels are shown by default. 2533 2534 Arguments: 2535 Name (str): Name of a new PyMOL halogen contacts object. 2536 Selection1 (str): First PyMOL selection containing halogens. 2537 Selection2 (str): Second PyMOL selection. 2538 Enable (bool): Display status of halogen contacts object. 2539 Color (str): Color for halogen contact lines and labels. 2540 DistanceCutoff (float): None or distance cutoff for distance contacts. 2541 IgnoreHydrogens (bool): Ignore hydrogens for halogen contacts. 2542 2543 Returns: 2544 str: PML commands for halogen contacts view between a pair of selections. 2545 2546 """ 2547 2548 HalogenSelection1 = "(%s) and (elem F,Cl,Br,I)" % Selection1 2549 2550 return SetupPMLForDistanceContactsView(Name, HalogenSelection1, Selection2, Enable, Color, Cutoff) 2551 2552 def SetupPMLForPiPiContactsView(Name, Selection1, Selection2, Enable = True, Color = "yellow", Cutoff = None): 2553 """Setup PML commands for creating pi pi contacts view between a pair of 2554 selections. The pi pi contact view is generated using 'cmd.distance' command 2555 with support for mode 6 and may require incentive version of PyMOL. The 2556 distance labels are shown by default. 2557 2558 Arguments: 2559 Name (str): Name of a new PyMOL pi pi contacts object. 2560 Selection1 (str): First PyMOL selection. 2561 Selection2 (str): Second PyMOL selection. 2562 Enable (bool): Display status of pi pi contacts object. 2563 Color (str): Color for pi pi contact lines and labels. 2564 DistanceCutoff (float): None or distance cutoff for pi pi contacts. 2565 2566 Returns: 2567 str: PML commands for pi pi contacts view between a pair of selections. 2568 2569 """ 2570 2571 Mode = 6 2572 return _SetupPMLForPiContactsView(Name, Selection1, Selection2, Mode, Enable, Color, Cutoff) 2573 2574 def SetupPMLForPiCationContactsView(Name, Selection1, Selection2, Enable = True, Color = "yellow", Cutoff = None): 2575 """Setup PML commands for creating pi cation contacts view between a pair of 2576 selections. The pi pi contact view is generated using 'cmd.distance' command 2577 with support for mode 7 and may require incentive version of PyMOL. The 2578 distance labels are shown by default. 2579 2580 Arguments: 2581 Name (str): Name of a new PyMOL pi cation contacts object. 2582 Selection1 (str): First PyMOL selection. 2583 Selection2 (str): Second PyMOL selection. 2584 Enable (bool): Display status of pi cation contacts object. 2585 Color (str): Color for pi pi contact lines and labels. 2586 DistanceCutoff (float): None or distance cutoff for pi cation contacts. 2587 2588 Returns: 2589 str: PML commands for pi pi contacts view between a pair of selections. 2590 2591 """ 2592 2593 Mode = 7 2594 return _SetupPMLForPiContactsView(Name, Selection1, Selection2, Mode, Enable, Color, Cutoff) 2595 2596 def _SetupPMLForPiContactsView(Name, Selection1, Selection2, Mode, Enable = True, Color = "yellow", Cutoff = None): 2597 """Setup PML commands for creating pi pi or pi cation contacts view between a 2598 selections. The pi pi and pi cation contact views are generated using 'cmd.distance' 2599 command. 2600 """ 2601 2602 PMLCmds = [] 2603 if Cutoff is None: 2604 PMLCmds.append("""cmd.distance("%s","(%s)","(%s)", quiet = 1, mode = %s, label = 1, reset = 1)""" % (Name, Selection1, Selection2, Mode)) 2605 else: 2606 PMLCmds.append("""cmd.distance("%s","(%s)","(%s)", cutoff = %.1f, quiet = 1, mode = %s, label = 1, reset = 1)""" % (Name, Selection1, Selection2, Cutoff, Mode)) 2607 2608 PMLCmds.append(SetupPMLForDeepColoring(Name, Color)) 2609 PMLCmds.append(SetupPMLForEnableDisable(Name, Enable)) 2610 2611 PML = "\n".join(PMLCmds) 2612 2613 return PML 2614 2615 def SetupPMLForPolarContactsView(Name, Selection1, Selection2, Enable = True, Color = "yellow", Cutoff = None): 2616 """Setup PML commands for creating polar contacts view between a pair of 2617 selections. The polar contact view is generated using 'cmd.dist' command. The 2618 distance labels are shown by default. 2619 2620 Arguments: 2621 Name (str): Name of a new PyMOL polar contacts object. 2622 Selection1 (str): First PyMOL selection. 2623 Selection2 (str): Second PyMOL selection. 2624 Enable (bool): Display status of polar contacts object. 2625 Color (str): Color for polar contact lines and labels. 2626 DistanceCutoff (float): None or distance cutoff for polar contacts. 2627 2628 Returns: 2629 str: PML commands for polar contacts view between a pair of selections. 2630 2631 """ 2632 2633 PMLCmds = [] 2634 if Cutoff is None: 2635 PMLCmds.append("""cmd.distance("%s","(%s)","(%s)", quiet = 1, mode = 2, label = 1, reset = 1)""" % (Name, Selection1, Selection2)) 2636 else: 2637 PMLCmds.append("""cmd.distance("%s","(%s)","(%s)", cutoff = %.1f, quiet = 1, mode = 2, label = 1, reset = 1)""" % (Name, Selection1, Selection2, Cutoff)) 2638 2639 PMLCmds.append(SetupPMLForDeepColoring(Name, Color)) 2640 PMLCmds.append(SetupPMLForEnableDisable(Name, Enable)) 2641 2642 PML = "\n".join(PMLCmds) 2643 2644 return PML 2645 2646 def SetupPMLForHydrophobicContactsView(Name, Selection1, Selection2, Enable = True, Color = "yellow", Cutoff = None): 2647 """Setup PML commands for creating hydrophobic contacts view between a pair of 2648 selections. The hydrophobic contacts are shown between pairs of carbon atoms not 2649 connected to hydrogen bond donor or acceptors atoms as identified by PyMOL. The 2650 distance labels are shown by default. 2651 2652 Arguments: 2653 Name (str): Name of a new PyMOL polar contacts object. 2654 Selection1 (str): First PyMOL selection. 2655 Selection2 (str): Second PyMOL selection. 2656 Enable (bool): Display status of polar contacts object. 2657 Color (str): Color for polar contact lines and labels. 2658 Cutoff (float): None or distance cutoff for hydrophobic contacts. 2659 2660 Returns: 2661 str: PML commands for polar contacts view between a pair of selections. 2662 2663 """ 2664 2665 PMLCmds = [] 2666 2667 HydrophobicSelectionAtoms1 = "((%s) and (elem C) and (not bound_to (donors or acceptors)))" % (Selection1) 2668 HydrophobicSelectionAtoms2 = "((%s) and (elem C) and (not bound_to (donors or acceptors)))" % (Selection2) 2669 2670 if Cutoff is None: 2671 PMLCmds.append("""cmd.distance("%s","(%s)","(%s)", quiet = 1, mode = 0, label = 1, reset = 1)""" % (Name, HydrophobicSelectionAtoms1, HydrophobicSelectionAtoms2)) 2672 else: 2673 PMLCmds.append("""cmd.distance("%s","(%s)","(%s)", cutoff = %.1f, quiet = 1, mode = 0, label = 1, reset = 1)""" % (Name, HydrophobicSelectionAtoms1, HydrophobicSelectionAtoms2, Cutoff)) 2674 2675 PMLCmds.append(SetupPMLForDeepColoring(Name, Color)) 2676 PMLCmds.append(SetupPMLForEnableDisable(Name, Enable)) 2677 2678 PML = "\n".join(PMLCmds) 2679 2680 return PML 2681 2682 def SetupPMLForDeepColoring(Name, Color): 2683 """Setup PML command for deep coloring based on PyMOL version number. 2684 2685 Arguments: 2686 Name (str): Name of a PyMOL object. 2687 Color (str): Color for PyMOL object. 2688 2689 Returns: 2690 str: PML command for deep coloring. 2691 2692 """ 2693 2694 if cmd.get_version()[1] < 2.0: 2695 return("""util.color_deep("%s", "%s")""" % (Color, Name)) 2696 else: 2697 return("""cmd.color_deep("%s", "%s")""" % (Color, Name)) 2698 2699 def SetupPMLForAlignment(Method, RefSelection, FitSelection): 2700 """Setup PML commands for aligning a pair of selection using a specified 2701 alignment method. 2702 2703 Arguments: 2704 Name (str): Name of a PyMOL object. 2705 2706 Returns: 2707 str: PML commands for aligning a pair of selections. 2708 2709 """ 2710 2711 PMLCmds = [] 2712 if re.match("^align$", Method, re.I): 2713 PMLCmds.append("""cmd.align("(%s)", "(%s)")""" % (FitSelection, RefSelection)) 2714 elif re.match("^cealign$", Method, re.I): 2715 PMLCmds.append("""cmd.cealign("(%s)", "(%s)")""" % (RefSelection, FitSelection)) 2716 elif re.match("^super$", Method, re.I): 2717 PMLCmds.append("""cmd.super("(%s)", "(%s)")""" % (FitSelection, RefSelection)) 2718 else: 2719 MiscUtil.PrintWarning("PyMOLUtil.SetupPMLForAlignment: Invalid method name: %s" % Method) 2720 2721 PML = "\n".join(PMLCmds) 2722 2723 return PML 2724 2725 def SetupPMLForBFactorCartoonView(Name, Selection, ColorPalette = "blue_white_red", Enable = True): 2726 """Setup PML commands for creating a B factor cartoon view for a specified 2727 selection. The B factor values must be available for the atoms. The atoms 2728 are colored using a color spectrum corresponding to a specified color 2729 palette. Any valid PyMOL color palette name may be used. 2730 2731 Arguments: 2732 Name (str): Name of a new PyMOL B factor cartoon object. 2733 Selection (str): Name of PyMOL selection. 2734 ColorPalette (str): Name of color palette to use for color spectrum. 2735 Enable (bool): Display status of B factor putty object. 2736 2737 Returns: 2738 str: PML commands for B factor putty view. 2739 2740 """ 2741 2742 return _SetupPMLForBFactorView(Name, Selection, ColorPalette, Enable, Putty = False) 2743 2744 def SetupPMLForBFactorPuttyView(Name, Selection, ColorPalette = "blue_white_red", Enable = True): 2745 """Setup PML commands for creating a B factor putty view for a specified 2746 selection. The B factor values must be available for the atoms. The atoms 2747 are colored using a color spectrum corresponding to a specified color 2748 palette. Any valid PyMOL color palette name may be used. 2749 2750 Arguments: 2751 Name (str): Name of a new PyMOL B factor putty object. 2752 Selection (str): Name of PyMOL selection. 2753 ColorPalette (str): Name of color palette to use for color spectrum. 2754 Enable (bool): Display status of B factor putty object. 2755 2756 Returns: 2757 str: PML commands for B factor putty view. 2758 2759 """ 2760 2761 return _SetupPMLForBFactorView(Name, Selection, ColorPalette, Enable, Putty = True) 2762 2763 def _SetupPMLForBFactorView(Name, Selection, ColorPalette = "blue_white_red", Enable = True, Putty = True): 2764 """Setup PML commands for creating a B factor cartoon or putty view for a 2765 specified selection. The B factor values must be available for the atoms. 2766 """ 2767 2768 PMLCmds = [] 2769 PMLCmds.append("""cmd.create("%s", "(%s)")""" % (Name, Selection)) 2770 PMLCmds.append("""cmd.hide("everything", "%s")""" % (Name)) 2771 PMLCmds.append("""cmd.spectrum("b", "%s", "(%s)")""" % (ColorPalette, Name)) 2772 PMLCmds.append("""cmd.show("cartoon", "%s")""" % (Name)) 2773 if Putty: 2774 PMLCmds.append("""cmd.cartoon("putty", "%s")""" % (Name)) 2775 PMLCmds.append(SetupPMLForEnableDisable(Name, Enable)) 2776 2777 PML = "\n".join(PMLCmds) 2778 2779 return PML 2780 def SetupPMLForHydrophobicSurfaceView(Name, Selection, ColorPalette = "RedToWhite", Enable = True, DisplayAs = "cartoon"): 2781 """Setup PML commands for creating a hydrophobic surface view for a specified 2782 selection. The surfaces are colored using a specified color palette. This is only valid 2783 for amino acids. 2784 2785 Arguments: 2786 Name (str): Name of a new PyMOL hydrophobic surface object. 2787 Selection (str): Name of PyMOL selection. 2788 ColorPalette (str): Name of color palette to use for coloring surfaces. 2789 Possible values: RedToWhite or WhiteToGreen for most hydrophobic 2790 to least hydrophobic amino acids. 2791 Enable (bool): Display status of surface object. 2792 DisplayAs (str): Any additional valid display type such as lines, 2793 sticks, ribbon, cartoon, or None. 2794 2795 Returns: 2796 str: PML commands for hydrophobic surface view. 2797 2798 """ 2799 2800 PMLCmds = _GetPMLCmdsForSurfaceView(Name, Selection, DisplayAs) 2801 PMLCmds.append("""ColorByHydrophobicity("%s", "%s")""" % (Name, ColorPalette)) 2802 PMLCmds.append(SetupPMLForEnableDisable(Name, Enable)) 2803 2804 PML = "\n".join(PMLCmds) 2805 2806 return PML 2807 2808 def SetupPMLForHydrophobicAndChargeSurfaceView(Name, Selection, HydrophobicAtomsColor = "yellow", NegativelyChargedAtomsColor = "red", PositivelyChargedAtomsColor = "blue", OtherAtomsColor = "gray90", Enable = True, DisplayAs = "cartoon"): 2809 """Setup PML commands for creating a surface colored by hydrophobic and 2810 charge [ REF 140] properties of atoms in amino acids. The atom names in 2811 standard amino acid residues are used to identify atom types as shown below: 2812 2813 Hydrophobic: C atoms not bound to N or O atoms; NegativelyCharged: Side 2814 chain O atoms in ASP and GLU; PositivelyCharged: Side chain N atoms in 2815 ARG and LYS; Others: Remaining atoms in polar and other residues 2816 2817 The amino acid atom names to color specific atoms are taken from YRB.py 2818 script [ REF 140]. The color values may also be specified as comma delimited 2819 RGB triplets. For example: HydrophobicAtomsColor = "0.950 0.78 0.0", 2820 NegativelyChargedAtomsColor = "1.0 0.4 0.4", PositivelyChargedAtomsColor 2821 = "0.2 0.5 0.8", OtherAtomsColor = "0.95 0.95 0.95" 2822 2823 Arguments: 2824 Name (str): Name of a new PyMOL hydrophobic surface object. 2825 Selection (str): Name of PyMOL selection. 2826 HydrophobicAtomsColor (str): Color name or space delimited RGB values 2827 NegativelyChargedAtomsColor (str): Color name or space delimited RGB values 2828 PositivelyChargedAtomsColor (str): Color name or space delimited RGB values 2829 OtherAtomsColor (str): Color name or space delimited RGB values 2830 Enable (bool): Display status of surface object. 2831 DisplayAs (str): Any additional valid display type such as lines, 2832 sticks, ribbon, cartoon, or None. 2833 2834 Returns: 2835 str: PML commands for hydrophobic and charge surface view. 2836 2837 """ 2838 2839 PMLCmds = _GetPMLCmdsForSurfaceView(Name, Selection, DisplayAs) 2840 PMLCmds.append("""ColorAtomsByHydrophobicityAndCharge("%s", "%s", "%s", "%s", "%s")""" % (Name, HydrophobicAtomsColor, NegativelyChargedAtomsColor, PositivelyChargedAtomsColor, OtherAtomsColor)) 2841 PMLCmds.append(SetupPMLForEnableDisable(Name, Enable)) 2842 2843 PML = "\n".join(PMLCmds) 2844 2845 return PML 2846 2847 def SetupPMLForSurfaceView(Name, Selection, Enable = True, DisplayAs = "cartoon", Color = "None"): 2848 """Setup PML commands for creating a molecular surface view for a specified 2849 selection. 2850 2851 Arguments: 2852 Name (str): Name of a new PyMOL molecular surface object. 2853 Selection (str): Name of PyMOL selection. 2854 Enable (bool): Display status of surface object. 2855 DisplayAs (str): Any additional valid display type such as lines, 2856 sticks, ribbon, cartoon, or None. 2857 Color (str): Surafce color. 2858 2859 Returns: 2860 str: PML commands for molecular surface view. 2861 2862 """ 2863 2864 PMLCmds = _GetPMLCmdsForSurfaceView(Name, Selection, DisplayAs) 2865 if Color is not None: 2866 PMLCmds.append(SetupPMLForDeepColoring(Name, Color)) 2867 PMLCmds.append(SetupPMLForEnableDisable(Name, Enable)) 2868 2869 PML = "\n".join(PMLCmds) 2870 2871 return PML 2872 2873 def _GetPMLCmdsForSurfaceView(Name, Selection, DisplayAs = "cartoon"): 2874 """Setup PML command for surface view.""" 2875 2876 PMLCmds = [] 2877 PMLCmds.append("""cmd.create("%s", "(%s)")""" % (Name, Selection)) 2878 PMLCmds.append("""cmd.hide("everything", "%s")""" % (Name)) 2879 if DisplayAs is not None: 2880 PMLCmds.append("""cmd.show("%s", "%s")""" % (DisplayAs, Name)) 2881 PMLCmds.append("""cmd.show("surface", "%s")""" % (Name)) 2882 2883 return PMLCmds 2884 2885 def SetupPMLForSelectionDisplayView(Name, Selection, DisplayAs, Color = None, Enable = True, IgnoreHydrogens = False): 2886 """Setup PML commands for creating a specific molecular display view for a 2887 selection. 2888 2889 Arguments: 2890 Name (str): Name of a new PyMOL object. 2891 Selection (str): Name of PyMOL selection. 2892 DisplayAs (str): Any valid display type such as lines, sticks, ribbon, 2893 cartoon, or surface 2894 Color (str): Color name or use default color. 2895 Enable (bool): Display status of object. 2896 IgnoreHydrogens (bool): Ignore hydrogens. 2897 2898 Returns: 2899 str: PML commands for molecular selection view. 2900 2901 """ 2902 2903 PMLCmds = [] 2904 if IgnoreHydrogens: 2905 PMLCmds.append("""cmd.create("%s", "((%s) and (not hydro))")""" % (Name, Selection)) 2906 else: 2907 PMLCmds.append("""cmd.create("%s", "(%s)")""" % (Name, Selection)) 2908 PMLCmds.append("""cmd.hide("everything", "%s")""" % (Name)) 2909 PMLCmds.append("""cmd.show("%s", "%s")""" % (DisplayAs, Name)) 2910 if Color is not None: 2911 PMLCmds.append(SetupPMLForDeepColoring(Name, Color)) 2912 PMLCmds.append(SetupPMLForEnableDisable(Name, Enable)) 2913 2914 PML = "\n".join(PMLCmds) 2915 2916 return PML 2917 2918 def SetupPMLForBallAndStickView(Name, Selection, Enable = True, SphereScale = 0.3, StickRadius = 0.2): 2919 """Setup PML commands for creating a ball and stick view for a specified 2920 selection. 2921 2922 Arguments: 2923 Name (str): Name of a new PyMOL ball and stick object. 2924 Selection (str): Name of PyMOL selection. 2925 Enable (bool): Display status of ball and stick object. 2926 SphereScale (float): Scaling factor for sphere radii. 2927 StickScale (float): Scaling factor for stick radii. 2928 2929 Returns: 2930 str: PML commands for ball and stick view. 2931 2932 """ 2933 2934 PMLCmds = [] 2935 PMLCmds.append("""cmd.create("%s", "(%s)")""" % (Name, Selection)) 2936 PMLCmds.append("""cmd.hide("everything", "%s")""" % (Name)) 2937 PMLCmds.append("""cmd.show("sphere", "%s")""" % (Name)) 2938 PMLCmds.append("""cmd.show("sticks", "%s")""" % (Name)) 2939 PMLCmds.append("""cmd.set("sphere_scale", %.1f, "%s")""" % (SphereScale, Name)) 2940 PMLCmds.append("""cmd.set("stick_radius", %.1f, "%s")""" % (StickRadius, Name)) 2941 2942 PMLCmds.append(SetupPMLForEnableDisable(Name, Enable)) 2943 2944 PML = "\n".join(PMLCmds) 2945 2946 return PML 2947 2948 def SetupPMLForInorganicView(Name, Selection, Enable = True): 2949 """Setup PML commands for creating a inorganic view corresponding to 2950 inorganic residues present in a selection. The inorganic residues are 2951 identified using inorganic selection operator available in PyMOL. The 2952 inorganic residues are displayed as 'lines' and 'nonbonded'. 2953 2954 Arguments: 2955 Name (str): Name of a new PyMOL inorganic object. 2956 Selection (str): Name of PyMOL selection. 2957 Enable (bool): Display status of inorganic object. 2958 2959 Returns: 2960 str: PML commands for inorganic view. 2961 2962 """ 2963 2964 PMLCmds = [] 2965 PMLCmds.append("""cmd.create("%s", "((%s) and inorganic)")""" % (Name, Selection)) 2966 PMLCmds.append("""cmd.show("nonbonded", "%s")""" % (Name)) 2967 PMLCmds.append("""cmd.show("lines", "%s")""" % (Name)) 2968 PMLCmds.append(SetupPMLForEnableDisable(Name, Enable)) 2969 2970 PML = "\n".join(PMLCmds) 2971 2972 return PML 2973 2974 def SetupPMLForSolventView(Name, Selection, Enable = True): 2975 """Setup PML commands for creating a solvent view corresponding to 2976 solvent residues present in a selection. The solvent residues are 2977 identified using solvent selection operator available in PyMOL. The 2978 solvent residues are displayed as 'nonbonded'. 2979 2980 Arguments: 2981 Name (str): Name of a new PyMOL solvent object. 2982 Selection (str): Name of PyMOL selection. 2983 Enable (bool): Display status of inorganic object. 2984 2985 Returns: 2986 str: PML commands for solvent view. 2987 2988 """ 2989 2990 PMLCmds = [] 2991 PMLCmds.append("""cmd.create("%s", "((%s) and solvent)")""" % (Name, Selection)) 2992 PMLCmds.append("""cmd.show("nonbonded", "%s")""" % (Name)) 2993 PMLCmds.append(SetupPMLForEnableDisable(Name, Enable)) 2994 2995 PML = "\n".join(PMLCmds) 2996 2997 return PML 2998 2999 def SetupPMLForDisulfideBondsView(Name, Selection, DisplayAs, Enable = True): 3000 """Setup PML commands for creating a view corresponding to 3001 disulfide bonds present in a selection. 3002 3003 Arguments: 3004 Name (str): Name of a new PyMOL disulfide bonds object. 3005 Selection (str): Name of PyMOL selection. 3006 DisplayAs (str): Any valid display type such as lines, sticks, ribbon, 3007 cartoon, or surface 3008 Enable (bool): Display status of disulfide bonds object. 3009 3010 Returns: 3011 str: PML commands for disulfide bonds view. 3012 3013 """ 3014 3015 PMLCmds = [] 3016 3017 DisulfideBondsSelection = "(byres (((%s) and (resn CYS+CYX) and (name SG)) and bound_to ((%s) and (resn CYS+CYX) and (name SG))))" % (Selection, Selection) 3018 PMLCmds.append("""cmd.create("%s", "(%s)")""" % (Name, DisulfideBondsSelection)) 3019 PMLCmds.append("""cmd.hide("everything", "%s")""" % (Name)) 3020 PMLCmds.append("""util.cbag("%s", _self = cmd)""" % (Name)) 3021 PMLCmds.append("""cmd.show("%s", "%s")""" % (DisplayAs, Name)) 3022 PMLCmds.append(SetupPMLForEnableDisable(Name, Enable)) 3023 3024 PML = "\n".join(PMLCmds) 3025 3026 return PML 3027 3028 def SetupPMLForSaltBridgesResiduesView(Name, Selection, Residues, DisplayAs, Enable = True): 3029 """Setup PML commands for creating a view corresponding to residues 3030 for salt bridges present in a selection. 3031 3032 Arguments: 3033 Name (str): Name of a new PyMOL disulfide bonds object. 3034 Selection (str): Name of PyMOL selection. 3035 Residues (list): List of residues. 3036 DisplayAs (str): Any valid display type such as lines, sticks, ribbon, 3037 cartoon, or surface 3038 Enable (bool): Display status of salt bridges residues object. 3039 3040 Returns: 3041 str: PML commands for salt bridges residues view. 3042 3043 """ 3044 3045 PMLCmds = [] 3046 3047 SaltBridgesResiduesSelection = "((%s) and (resn %s) and (not name N+O) and (not hydro))" % (Selection, "+".join(Residues) ) 3048 3049 PMLCmds.append("""cmd.create("%s", "(%s)")""" % (Name, SaltBridgesResiduesSelection)) 3050 PMLCmds.append("""cmd.hide("everything", "%s")""" % (Name)) 3051 PMLCmds.append("""util.cbag("%s", _self = cmd)""" % (Name)) 3052 PMLCmds.append("""cmd.show("%s", "%s")""" % (DisplayAs, Name)) 3053 PMLCmds.append(SetupPMLForEnableDisable(Name, Enable)) 3054 3055 PML = "\n".join(PMLCmds) 3056 3057 return PML 3058 3059 def SetupPMLForPolymerChainView(Name, Selection, Enable = True): 3060 """Setup PML commands for creating a polymer chain view corresponding 3061 to backbone and sidechain residues in a selection. The polymer chain is 3062 displayed as 'cartoon'. 3063 3064 Arguments: 3065 Name (str): Name of a new PyMOL polymer chain object. 3066 Selection (str): Name of PyMOL selection. 3067 Enable (bool): Display status of chain object. 3068 3069 Returns: 3070 str: PML commands for polymer chain view. 3071 3072 """ 3073 3074 PMLCmds = [] 3075 PMLCmds.append("""cmd.create("%s", "((%s) and (backbone or sidechain))")""" % (Name, Selection)) 3076 PMLCmds.append("""cmd.hide("everything", "%s")""" % (Name)) 3077 PMLCmds.append("""util.cbag("%s", _self = cmd)""" % (Name)) 3078 PMLCmds.append("""cmd.show("cartoon", "%s")""" % (Name)) 3079 PMLCmds.append(SetupPMLForEnableDisable(Name, Enable)) 3080 3081 3082 PML = "\n".join(PMLCmds) 3083 3084 return PML 3085 3086 3087 def SetupPMLForPolymerComplexView(MoleculeName, PDBFile, Enable = True, ShowSolvent = True, ShowInorganic = True, ShowLines = True): 3088 """Setup PML commands for creating a polymer complex view for all chains 3089 in a PDB file. The solvent and inorganic residues are also shown by default. 3090 The polymer chains are displayed as 'cartoon'. The 'line' display for the 3091 polymer chains is also shown and may be turned off. The organic residues are 3092 displayed as 'sticks'. The solvent and inorganic residues are displayed as 3093 'nonbonded' and 'lines'. 3094 3095 Arguments: 3096 MoleculeName (str): Name of a new PyMOL molecule object. 3097 PDBFile (str): Name of PDB file. 3098 Enable (bool): Display status of chain object. 3099 ShowSolvent (bool): Display solvent residues. 3100 ShowInorganic (bool): Display inorganic residues. 3101 ShowLines (bool): Display lines for polymer chains. 3102 3103 Returns: 3104 str: PML commands for polymer complex view. 3105 3106 """ 3107 3108 PMLCmds = [] 3109 3110 PMLCmds.append("""cmd.load("%s", "%s")""" % (PDBFile, MoleculeName)) 3111 PML = _SetupPMLForPolymerComplexView(MoleculeName, Enable, ShowSolvent, ShowInorganic, ShowLines) 3112 PMLCmds.append(PML) 3113 3114 PML = "\n".join(PMLCmds) 3115 3116 return PML 3117 3118 def SetupPMLForPolymerChainComplexView(ChainComplexName, Selection, ChainName, Enable = True, ShowSolvent = True, ShowInorganic = True, ShowLines = True): 3119 """Setup PML commands for creating a polymer chain complex view for a specified 3120 chain in a selection. The solvent and inorganic residues are also shown by 3121 default. The polymer chain is displayed as 'cartoon'. The 'line' display for the 3122 polymer chain is also shown and may be turned off. The organic residues are 3123 displayed as 'sticks'. The solvent and inorganic residues are displayed as 3124 'nonbonded' and 'lines'. 3125 3126 Arguments: 3127 ChainComplexName (str): Name of a new PyMOL polymer chain complex. 3128 Selection (str): Name of PyMOL selection. 3129 ChainName (str): Name of a chain. 3130 Enable (bool): Display status of chain object. 3131 ShowSolvent (bool): Display solvent residues. 3132 ShowInorganic (bool): Display inorganic residues. 3133 ShowLines (bool): Display lines for polymer chain. 3134 3135 Returns: 3136 str: PML commands for polymer chain complex view. 3137 3138 """ 3139 3140 PMLCmds = [] 3141 3142 PMLCmds.append("""cmd.create("%s", "(%s and chain %s)")""" % (ChainComplexName, Selection, ChainName)) 3143 PML = _SetupPMLForPolymerComplexView(ChainComplexName, Enable, ShowSolvent, ShowInorganic, ShowLines) 3144 PMLCmds.append(PML) 3145 3146 PML = "\n".join(PMLCmds) 3147 3148 return PML 3149 3150 def _SetupPMLForPolymerComplexView(Name, Enable = True, ShowSolvent = True, ShowInorganic = True, ShowLines = False): 3151 """Setup PML for creating a polymer complex view.""" 3152 3153 PMLCmds = [] 3154 3155 PMLCmds.append("""cmd.hide("everything", "%s")""" % (Name)) 3156 PMLCmds.append("""cmd.show("cartoon", "%s")""" % (Name)) 3157 PMLCmds.append("""util.cba(33, "%s", _self = cmd)""" % (Name)) 3158 PMLCmds.append("""cmd.show("sticks", "(organic and (%s))")""" % (Name)) 3159 if ShowSolvent: 3160 PMLCmds.append("""cmd.show("nonbonded", "(solvent and (%s))")""" % (Name)) 3161 if ShowInorganic: 3162 PMLCmds.append("""cmd.show("nonbonded", "(inorganic and (%s))")""" % (Name)) 3163 3164 if ShowLines: 3165 PMLCmds.append("""cmd.show("lines", "%s")""" % (Name)) 3166 else: 3167 if ShowInorganic: 3168 PMLCmds.append("""cmd.show("lines", "(inorganic and (%s))")""" % (Name)) 3169 3170 PMLCmds.append("""cmd.set_bond("valence", "1", "%s", quiet = 1)""" % (Name)) 3171 PMLCmds.append(SetupPMLForEnableDisable(Name, Enable)) 3172 3173 PML = "\n".join(PMLCmds) 3174 3175 return PML