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