1 #!/bin/env python 2 # 3 # File: PyMOLVisualizeCryoEMDensity.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 import xml.etree.ElementTree as ElementTree 38 39 # PyMOL imports... 40 try: 41 import pymol 42 # Finish launching PyMOL in a command line mode for batch processing (-c) 43 # along with the following options: disable loading of pymolrc and plugins (-k); 44 # suppress start up messages (-q) 45 pymol.finish_launching(['pymol', '-ckq']) 46 except ImportError as ErrMsg: 47 sys.stderr.write("\nFailed to import PyMOL module/package: %s\n" % ErrMsg) 48 sys.stderr.write("Check/update your PyMOL environment and try again.\n\n") 49 sys.exit(1) 50 51 # MayaChemTools imports... 52 try: 53 from docopt import docopt 54 import MiscUtil 55 import PyMOLUtil 56 except ImportError as ErrMsg: 57 sys.stderr.write("\nFailed to import MayaChemTools module/package: %s\n" % ErrMsg) 58 sys.stderr.write("Check/update your MayaChemTools environment and try again.\n\n") 59 sys.exit(1) 60 61 ScriptName = os.path.basename(sys.argv[0]) 62 Options = {} 63 OptionsInfo = {} 64 65 def main(): 66 """Start execution of the script.""" 67 68 MiscUtil.PrintInfo("\n%s (PyMOL v%s; MayaChemTools v%s; %s): Starting...\n" % (ScriptName, pymol.cmd.get_version()[0], MiscUtil.GetMayaChemToolsVersion(), time.asctime())) 69 70 (WallClockTime, ProcessorTime) = MiscUtil.GetWallClockAndProcessorTime() 71 72 # Retrieve command line arguments and options... 73 RetrieveOptions() 74 75 # Process and validate command line arguments and options... 76 ProcessOptions() 77 78 # Perform actions required by the script... 79 GenerateCryoEMDensityVisualization() 80 81 MiscUtil.PrintInfo("\n%s: Done...\n" % ScriptName) 82 MiscUtil.PrintInfo("Total time: %s" % MiscUtil.GetFormattedElapsedTime(WallClockTime, ProcessorTime)) 83 84 def GenerateCryoEMDensityVisualization(): 85 """Generate cryo-EM density visualization.""" 86 87 Outfile = OptionsInfo["PMLOutfile"] 88 OutFH = open(Outfile, "w") 89 if OutFH is None: 90 MiscUtil.PrintError("Failed to open output fie %s " % Outfile) 91 92 MiscUtil.PrintInfo("\nGenerating file %s..." % Outfile) 93 94 # Setup header... 95 WritePMLHeader(OutFH, ScriptName) 96 WritePyMOLParameters(OutFH) 97 98 # Load reffile for alignment.. 99 if OptionsInfo["Align"]: 100 WriteAlignReference(OutFH) 101 102 # Setup view for each input file... 103 FirstComplex = True 104 FirstComplexFirstChainName = None 105 for FileIndex in range(0, len(OptionsInfo["InfilesInfo"]["InfilesNames"])): 106 # Setup PyMOL object names... 107 PyMOLObjectNames = SetupPyMOLObjectNames(FileIndex) 108 109 # Setup complex view... 110 WriteComplexView(OutFH, FileIndex, PyMOLObjectNames, FirstComplex) 111 112 SpecifiedChainsAndLigandsInfo = OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"][FileIndex] 113 FirstChain = True 114 for ChainID in SpecifiedChainsAndLigandsInfo["ChainIDs"]: 115 if FirstComplex and FirstChain: 116 FirstComplexFirstChainName = PyMOLObjectNames["Chains"][ChainID]["ChainAlone"] 117 118 WriteChainView(OutFH, FileIndex, PyMOLObjectNames, ChainID) 119 120 # Setup ligand views... 121 FirstLigand = True 122 for LigandID in SpecifiedChainsAndLigandsInfo["LigandIDs"][ChainID]: 123 WriteChainLigandView(OutFH, FileIndex, PyMOLObjectNames, ChainID, LigandID) 124 125 # Set up ligand level group... 126 Enable, Action = [False, "close"] 127 if FirstLigand: 128 FirstLigand = False 129 Enable, Action = [True, "open"] 130 GenerateAndWritePMLForGroup(OutFH, PyMOLObjectNames["Ligands"][ChainID][LigandID]["ChainLigandGroup"], PyMOLObjectNames["Ligands"][ChainID][LigandID]["ChainLigandGroupMembers"], Enable, Action) 131 132 # Setup Chain level group... 133 Enable, Action = [False, "close"] 134 if FirstChain: 135 FirstChain = False 136 Enable, Action = [True, "open"] 137 GenerateAndWritePMLForGroup(OutFH, PyMOLObjectNames["Chains"][ChainID]["ChainGroup"], PyMOLObjectNames["Chains"][ChainID]["ChainGroupMembers"], Enable, Action) 138 139 # Set up complex level group... 140 Enable, Action = [False, "close"] 141 if FirstComplex: 142 FirstComplex = False 143 Enable, Action = [True, "open"] 144 GenerateAndWritePMLForGroup(OutFH, PyMOLObjectNames["PDBGroup"], PyMOLObjectNames["PDBGroupMembers"], Enable, Action) 145 146 # Delete empty PyMOL objects... 147 DeleteEmptyPyMOLObjects(OutFH, FileIndex, PyMOLObjectNames) 148 149 if OptionsInfo["Align"]: 150 DeleteAlignReference(OutFH) 151 152 if FirstComplexFirstChainName is not None: 153 OutFH.write("""\ncmd.orient("%s", animate = -1)\n""" % FirstComplexFirstChainName) 154 else: 155 OutFH.write("""\ncmd.orient("visible", animate = -1)\n""") 156 157 OutFH.close() 158 159 # Generate PSE file as needed... 160 if OptionsInfo["PSEOut"]: 161 GeneratePyMOLSessionFile() 162 163 def WritePMLHeader(OutFH, ScriptName): 164 """Write out PML setting up complex view.""" 165 166 HeaderInfo = PyMOLUtil.SetupPMLHeaderInfo(ScriptName) 167 OutFH.write("%s\n" % HeaderInfo) 168 169 def WritePyMOLParameters(OutFH): 170 """Write out PyMOL global parameters.""" 171 172 PMLCmds = [] 173 PMLCmds.append("""cmd.set("mesh_width", %.2f)""" % (OptionsInfo["MeshWidth"])) 174 PMLCmds.append("""cmd.set("transparency", %.2f, "", 0)""" % (OptionsInfo["SurfaceTransparency"])) 175 PMLCmds.append("""cmd.set("label_font_id", %s)""" % (OptionsInfo["LabelFontID"])) 176 177 if OptionsInfo["VolumeColorRampCreate"]: 178 ColorRampName = OptionsInfo["VolumeColorRampName"] 179 ContourLevel = OptionsInfo["VolumeColorRampContourLevel"] 180 LowerContourLevel = ContourLevel - 0.3 181 UpperContourLevel = ContourLevel + 0.3 182 PMLCmds.append("""cmd.volume_ramp_new("%s", "%.2f blue 0.00 %.2f cyan 0.20 %.2f blue 0.00")""" % (ColorRampName, LowerContourLevel, ContourLevel, UpperContourLevel)) 183 184 PML = "\n".join(PMLCmds) 185 186 OutFH.write("""\n""\n"Setting up PyMOL gobal parameters..."\n""\n""") 187 OutFH.write("%s\n" % PML) 188 189 def WriteAlignReference(OutFH): 190 """Setup object for alignment reference.""" 191 192 RefFileInfo = OptionsInfo["RefFileInfo"] 193 RefFile = RefFileInfo["RefFileName"] 194 RefName = RefFileInfo["PyMOLObjectName"] 195 196 PMLCmds = [] 197 PMLCmds.append("""cmd.load("%s", "%s")""" % (RefFile, RefName)) 198 PMLCmds.append("""cmd.hide("everything", "%s")""" % (RefName)) 199 PMLCmds.append("""cmd.disable("%s")""" % (RefName)) 200 PML = "\n".join(PMLCmds) 201 202 OutFH.write("""\n""\n"Loading %s and setting up view for align reference..."\n""\n""" % RefFile) 203 OutFH.write("%s\n" % PML) 204 205 def WriteAlignComplex(OutFH, FileIndex, PyMOLObjectNames): 206 """Setup alignment of complex to reference.""" 207 208 RefFileInfo = OptionsInfo["RefFileInfo"] 209 RefName = RefFileInfo["PyMOLObjectName"] 210 211 ComplexName = PyMOLObjectNames["Complex"] 212 213 if re.match("^FirstChain$", OptionsInfo["AlignMode"], re.I): 214 RefFirstChainID = RefFileInfo["ChainsAndLigandsInfo"]["ChainIDs"][0] 215 RefAlignSelection = "%s and chain %s" % (RefName, RefFirstChainID) 216 217 ComplexFirstChainID = RetrieveFirstChainID(FileIndex) 218 ComplexAlignSelection = "%s and chain %s" % (ComplexName, ComplexFirstChainID) 219 else: 220 RefAlignSelection = RefName 221 ComplexAlignSelection = ComplexName 222 223 PML = PyMOLUtil.SetupPMLForAlignment(OptionsInfo["AlignMethod"], RefAlignSelection, ComplexAlignSelection) 224 OutFH.write("""\n""\n"Aligning %s against reference %s ..."\n""\n""" % (ComplexAlignSelection, RefAlignSelection)) 225 OutFH.write("%s\n" % PML) 226 227 def DeleteAlignReference(OutFH): 228 """Delete alignment reference object.""" 229 230 RefName = OptionsInfo["RefFileInfo"]["PyMOLObjectName"] 231 OutFH.write("""\n""\n"Deleting alignment reference object %s..."\n""\n""" % RefName) 232 OutFH.write("""cmd.delete("%s")\n""" % RefName) 233 234 def WriteComplexView(OutFH, FileIndex, PyMOLObjectNames, FirstComplex): 235 """Write out PML for viewing polymer complex along with cryo-EM density.""" 236 237 # Setup complex... 238 Infile = OptionsInfo["InfilesInfo"]["InfilesNames"][FileIndex] 239 PML = PyMOLUtil.SetupPMLForPolymerComplexView(PyMOLObjectNames["Complex"], Infile, True) 240 OutFH.write("""\n""\n"Loading %s and setting up view for complex..."\n""\n""" % Infile) 241 OutFH.write("%s\n" % PML) 242 243 if OptionsInfo["Align"]: 244 # No need to align complex on to itself... 245 if not (re.match("^FirstInputFile$", OptionsInfo["AlignRefFile"], re.I) and FirstComplex): 246 WriteAlignComplex(OutFH, FileIndex, PyMOLObjectNames) 247 248 # Setup cryo-EM density maps and meshes... 249 DensityMapFile = OptionsInfo["DensityMapFilesNames"][FileIndex] 250 ContourLevel = OptionsInfo["MeshLevels"][FileIndex] 251 WriteComplexCryoEMDensityMapView(OutFH, PyMOLObjectNames, DensityMapFile, ContourLevel) 252 253 # Setup complex group... 254 GenerateAndWritePMLForGroup(OutFH, PyMOLObjectNames["ComplexGroup"], PyMOLObjectNames["ComplexGroupMembers"], False, "close") 255 256 def WriteComplexCryoEMDensityMapView(OutFH, PyMOLObjectNames, MapFileName, ContourLevel): 257 """Write out PML for viewing cryoEM density map.""" 258 259 # Load cryo-EM density map and setup mesh views... 260 Info = """\ 261 "" 262 "Loading cryo-EM density map %s and setting up mesh view for complex..." 263 "" """ % MapFileName 264 OutFH.write("\n%s\n" % Info) 265 266 MapName = PyMOLObjectNames["ComplexCryoEMMap"] 267 ComplexName = PyMOLObjectNames["Complex"] 268 269 Color = OptionsInfo["MeshColor"] 270 VolumeColorRamp = OptionsInfo["VolumeColorRampName"] 271 272 VolumeName = PyMOLObjectNames["ComplexCryoEMVolume"] 273 MeshName = PyMOLObjectNames["ComplexCryoEMMesh"] 274 SurfaceName = PyMOLObjectNames["ComplexCryoEMSurface"] 275 276 AlignMapToObjectName = ComplexName if OptionsInfo["Align"] else None 277 EnableMap = True 278 PML = SetupPMLForCryoEMDensityMap(MapFileName, MapName, AlignMapToObjectName, EnableMap) 279 OutFH.write("%s\n" % PML) 280 281 EnableMesh = OptionsInfo["MeshComplex"] 282 283 EnableVolume = OptionsInfo["VolumeComplex"] 284 if EnableVolume and EnableMesh: 285 EnableVolume = False 286 287 EnableSurface = OptionsInfo["SurfaceComplex"] 288 if EnableSurface and (EnableVolume or EnableMesh): 289 EnableSurface = False 290 291 if OptionsInfo["VolumeComplex"]: 292 PML = SetupPMLForCryoEMDensityVolume(MapName, VolumeName, VolumeColorRamp, Enable = EnableVolume, Selection = ComplexName) 293 OutFH.write("\n%s\n" % PML) 294 295 if OptionsInfo["MeshComplex"]: 296 PML = SetupPMLForCryoEMDensityMesh(MapName, MeshName, ContourLevel, Color, Enable = EnableMesh, Selection = ComplexName) 297 OutFH.write("\n%s\n" % PML) 298 299 if OptionsInfo["SurfaceComplex"]: 300 PML = SetupPMLForCryoEMDensitySurface(MapName, SurfaceName, ContourLevel, Color, Enable = EnableSurface, Selection = ComplexName) 301 OutFH.write("\n%s\n" % PML) 302 303 GenerateAndWritePMLForGroup(OutFH, PyMOLObjectNames["ComplexCryoEMGroup"], PyMOLObjectNames["ComplexCryoEMGroupMembers"], True, "close") 304 305 def WriteChainView(OutFH, FileIndex, PyMOLObjectNames, ChainID): 306 """Write out PML for viewing chain.""" 307 308 OutFH.write("""\n""\n"Setting up views for chain %s..."\n""\n""" % ChainID) 309 310 ChainComplexName = PyMOLObjectNames["Chains"][ChainID]["ChainComplex"] 311 312 # Setup chain complex group view... 313 WriteChainComplexAndMeshViews(OutFH, FileIndex, PyMOLObjectNames, ChainID) 314 315 # Setup chain view... 316 WriteChainAloneViews(OutFH, FileIndex, PyMOLObjectNames, ChainID) 317 318 # Setup chain solvent view... 319 PML = PyMOLUtil.SetupPMLForSolventView(PyMOLObjectNames["Chains"][ChainID]["Solvent"], ChainComplexName, False) 320 OutFH.write("\n%s\n" % PML) 321 322 # Setup chain inorganic view... 323 PML = PyMOLUtil.SetupPMLForInorganicView(PyMOLObjectNames["Chains"][ChainID]["Inorganic"], ChainComplexName, False) 324 OutFH.write("\n%s\n" % PML) 325 326 def WriteChainComplexAndMeshViews(OutFH, FileIndex, PyMOLObjectNames, ChainID): 327 """Write chain complex and mesh views.""" 328 329 # Setup chain complex... 330 ChainComplexName = PyMOLObjectNames["Chains"][ChainID]["ChainComplex"] 331 PML = PyMOLUtil.SetupPMLForPolymerChainComplexView(ChainComplexName, PyMOLObjectNames["Complex"], ChainID, True) 332 OutFH.write("%s\n" % PML) 333 334 SpecifiedChainsAndLigandsInfo = OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"][FileIndex] 335 336 MeshChainComplex = SpecifiedChainsAndLigandsInfo["MeshChainComplex"][ChainID] 337 VolumeChainComplex = SpecifiedChainsAndLigandsInfo["VolumeChainComplex"][ChainID] 338 SurfaceChainComplex = SpecifiedChainsAndLigandsInfo["SurfaceChainComplex"][ChainID] 339 340 EnableVolumeChainComplex = SpecifiedChainsAndLigandsInfo["EnableVolumeChainComplex"][ChainID] 341 EnableMeshChainComplex = SpecifiedChainsAndLigandsInfo["EnableMeshChainComplex"][ChainID] 342 EnableSurfaceChainComplex = SpecifiedChainsAndLigandsInfo["EnableSurfaceChainComplex"][ChainID] 343 344 if MeshChainComplex or VolumeChainComplex or SurfaceChainComplex: 345 # Set up cryoEM mesh and group... 346 MapName = PyMOLObjectNames["ComplexCryoEMMap"] 347 ContourLevel = OptionsInfo["MeshLevels"][FileIndex] 348 Color = OptionsInfo["MeshColor"] 349 350 VolumeColorRamp = OptionsInfo["VolumeColorRampName"] 351 352 VolumeName = PyMOLObjectNames["Chains"][ChainID]["ChainComplexCryoEMVolume"] 353 MeshName = PyMOLObjectNames["Chains"][ChainID]["ChainComplexCryoEMMesh"] 354 SurfaceName = PyMOLObjectNames["Chains"][ChainID]["ChainComplexCryoEMSurface"] 355 356 if VolumeChainComplex: 357 PML = SetupPMLForCryoEMDensityVolume(MapName, VolumeName, VolumeColorRamp, Enable = EnableVolumeChainComplex, Selection = ChainComplexName) 358 OutFH.write("\n%s\n" % PML) 359 360 if MeshChainComplex: 361 PML = SetupPMLForCryoEMDensityMesh(MapName, MeshName, ContourLevel, Color, Enable = EnableMeshChainComplex, Selection = ChainComplexName) 362 OutFH.write("\n%s\n" % PML) 363 364 if SurfaceChainComplex: 365 PML = SetupPMLForCryoEMDensitySurface(MapName, SurfaceName, ContourLevel, Color, Enable = EnableSurfaceChainComplex, Selection = ChainComplexName) 366 OutFH.write("\n%s\n" % PML) 367 368 GenerateAndWritePMLForGroup(OutFH, PyMOLObjectNames["Chains"][ChainID]["ChainComplexCryoEMGroup"], PyMOLObjectNames["Chains"][ChainID]["ChainComplexCryoEMGroupMembers"], True, "close") 369 370 # Setup chain complex group... 371 EnableChainComplexGroup = SpecifiedChainsAndLigandsInfo["EnableChainComplexGroup"][ChainID] 372 GenerateAndWritePMLForGroup(OutFH, PyMOLObjectNames["Chains"][ChainID]["ChainComplexGroup"], PyMOLObjectNames["Chains"][ChainID]["ChainComplexGroupMembers"], EnableChainComplexGroup, "close") 373 374 def WriteChainAloneViews(OutFH, FileIndex, PyMOLObjectNames, ChainID): 375 """Write individual chain views.""" 376 377 ChainComplexName = PyMOLObjectNames["Chains"][ChainID]["ChainComplex"] 378 379 # Setup chain view... 380 ChainName = PyMOLObjectNames["Chains"][ChainID]["ChainAlone"] 381 PML = PyMOLUtil.SetupPMLForPolymerChainView(ChainName, ChainComplexName, Enable = True) 382 OutFH.write("\n%s\n" % PML) 383 384 # Setup chain putty by B-factor view... 385 if OptionsInfo["BFactorChainCartoonPutty"]: 386 BFactorPuttyName = PyMOLObjectNames["Chains"][ChainID]["ChainAloneBFactorPutty"] 387 PML = PyMOLUtil.SetupPMLForBFactorPuttyView(BFactorPuttyName, ChainName, ColorPalette = OptionsInfo["BFactorColorPalette"], Enable = False) 388 OutFH.write("\n%s\n" % PML) 389 390 # Setup chain selections view... 391 SetupChainSelectionsView(OutFH, FileIndex, PyMOLObjectNames, ChainID) 392 393 # Setup chain group... 394 SpecifiedChainsAndLigandsInfo = OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"][FileIndex] 395 EnableChainAloneGroup = SpecifiedChainsAndLigandsInfo["EnableChainAloneGroup"][ChainID] 396 GenerateAndWritePMLForGroup(OutFH, PyMOLObjectNames["Chains"][ChainID]["ChainAloneGroup"], PyMOLObjectNames["Chains"][ChainID]["ChainAloneGroupMembers"], EnableChainAloneGroup, "close") 397 398 def SetupChainSelectionsView(OutFH, FileIndex, PyMOLObjectNames, ChainID): 399 """Setup chain selectons view.""" 400 401 if not OptionsInfo["ChainSelections"]: 402 return 403 404 ChainName = PyMOLObjectNames["Chains"][ChainID]["ChainAlone"] 405 SelectionsGroupIDPrefix = "ChainAloneSelections" 406 407 for Index in range(0, len(OptionsInfo["ChainSelectionsInfo"]["Names"])): 408 SelectionName = OptionsInfo["ChainSelectionsInfo"]["Names"][Index] 409 SpecifiedSelection = OptionsInfo["ChainSelectionsInfo"]["Selections"][Index] 410 411 SelectionNameGroupID = SelectionName 412 413 # Setup selection object... 414 SelectionObjectID = "%s%sSelection" % (SelectionsGroupIDPrefix, SelectionNameGroupID) 415 SelectionObjectName = PyMOLObjectNames["Chains"][ChainID][SelectionObjectID] 416 SelectionCmd = "(%s and (%s))" % (ChainName, SpecifiedSelection) 417 PML = PyMOLUtil.SetupPMLForSelectionDisplayView(SelectionObjectName, SelectionCmd, OptionsInfo["SelectionsChainStyle"], Enable = True) 418 OutFH.write("\n%s\n" % PML) 419 420 # Set up cryo-EM mesh and group... 421 CryoEMVolumeID = "%s%sCryoEMVolume" % (SelectionsGroupIDPrefix, SelectionNameGroupID) 422 CryoEMMeshID = "%s%sCryoEMMesh" % (SelectionsGroupIDPrefix, SelectionNameGroupID) 423 CryoEMSurfaceID = "%s%sCryoEMSurface" % (SelectionsGroupIDPrefix, SelectionNameGroupID) 424 CryoEMMeshGroupID = "%s%sCryoEMGroup" % (SelectionsGroupIDPrefix, SelectionNameGroupID) 425 CryoEMMeshGroupMembersID = "%s%sCryoEMGroupMembers" % (SelectionsGroupIDPrefix, SelectionNameGroupID) 426 427 CryoEMVolumeName = PyMOLObjectNames["Chains"][ChainID][CryoEMVolumeID] 428 CryoEMMeshName = PyMOLObjectNames["Chains"][ChainID][CryoEMMeshID] 429 CryoEMSurfaceName = PyMOLObjectNames["Chains"][ChainID][CryoEMSurfaceID] 430 CryoEMMeshGroupName = PyMOLObjectNames["Chains"][ChainID][CryoEMMeshGroupID] 431 CryoEMMeshGroupMembers = PyMOLObjectNames["Chains"][ChainID][CryoEMMeshGroupMembersID] 432 433 MapName = PyMOLObjectNames["ComplexCryoEMMap"] 434 ContourLevel = OptionsInfo["MeshLevels"][FileIndex] 435 Color = OptionsInfo["MeshColor"] 436 437 PML = SetupPMLForCryoEMDensityVolume(MapName, CryoEMVolumeName, OptionsInfo["VolumeColorRampName"], Enable = False, Selection = SelectionObjectName) 438 OutFH.write("\n%s\n" % PML) 439 440 PML = SetupPMLForCryoEMDensityMesh(MapName, CryoEMMeshName, ContourLevel, Color, Enable = True, Selection = SelectionObjectName) 441 OutFH.write("\n%s\n" % PML) 442 443 PML = SetupPMLForCryoEMDensitySurface(MapName, CryoEMSurfaceName, ContourLevel, Color, Enable = False, Selection = SelectionObjectName) 444 OutFH.write("\n%s\n" % PML) 445 446 GenerateAndWritePMLForGroup(OutFH, CryoEMMeshGroupName, CryoEMMeshGroupMembers, True, "close") 447 448 # Setup groups for named selections... 449 SelectionsNameGroupID = "%s%sGroup" % (SelectionsGroupIDPrefix, SelectionNameGroupID) 450 SelectionsNameGroupMembersID = "%s%sGroupMembers" % (SelectionsGroupIDPrefix, SelectionNameGroupID) 451 GenerateAndWritePMLForGroup(OutFH, PyMOLObjectNames["Chains"][ChainID][SelectionsNameGroupID], PyMOLObjectNames["Chains"][ChainID][SelectionsNameGroupMembersID], True, "open") 452 453 # Setup a group for selections... 454 SelectionsGroupID = "%sGroup" % (SelectionsGroupIDPrefix) 455 SelectionsGroupMembersID = "%sGroupMembers" % (SelectionsGroupIDPrefix) 456 GenerateAndWritePMLForGroup(OutFH, PyMOLObjectNames["Chains"][ChainID][SelectionsGroupID], PyMOLObjectNames["Chains"][ChainID][SelectionsGroupMembersID], False, "close") 457 458 def WriteChainLigandView(OutFH, FileIndex, PyMOLObjectNames, ChainID, LigandID): 459 """Write out PML for viewing ligand in a chain.""" 460 461 for GroupID in ["Ligand", "Pocket", "PocketSolvent", "PocketInorganic"]: 462 ComplexName = PyMOLObjectNames["Chains"][ChainID]["ChainComplex"] 463 LigandName = PyMOLObjectNames["Ligands"][ChainID][LigandID]["Ligand"] 464 465 # Setup main object... 466 GroupTypeObjectID = "%s" % (GroupID) 467 GroupTypeObjectName = PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupTypeObjectID] 468 469 if re.match("^Ligand$", GroupID, re.I): 470 OutFH.write("""\n""\n"Setting up views for ligand %s in chain %s..."\n""\n""" % (LigandID, ChainID)) 471 PML = PyMOLUtil.SetupPMLForLigandView(GroupTypeObjectName, ComplexName, LigandID, Enable = True, IgnoreHydrogens = OptionsInfo["IgnoreHydrogens"]) 472 OutFH.write("%s\n" % PML) 473 elif re.match("^Pocket$", GroupID, re.I): 474 OutFH.write("""\n""\n"Setting up views for pocket around ligand %s in chain %s..."\n""\n""" % (LigandID, ChainID)) 475 PML = PyMOLUtil.SetupPMLForLigandPocketView(GroupTypeObjectName, ComplexName, LigandName, OptionsInfo["PocketDistanceCutoff"], Enable = True, IgnoreHydrogens = OptionsInfo["IgnoreHydrogens"]) 476 OutFH.write("%s\n" % PML) 477 OutFH.write("""cmd.set("label_color", "%s", "%s")\n""" % (OptionsInfo["PocketLabelColor"], GroupTypeObjectName)) 478 elif re.match("^PocketSolvent$", GroupID, re.I): 479 OutFH.write("""\n""\n"Setting up views for solvent in pockect around ligand %s in chain %s..."\n""\n""" % (LigandID, ChainID)) 480 PML = PyMOLUtil.SetupPMLForLigandPocketSolventView(GroupTypeObjectName, ComplexName, LigandName, OptionsInfo["PocketDistanceCutoff"], Enable = True) 481 OutFH.write("%s\n" % PML) 482 elif re.match("^PocketInorganic$", GroupID, re.I): 483 OutFH.write("""\n""\n"Setting up views for inorganic in pockect around ligand %s in chain %s..."\n""\n""" % (LigandID, ChainID)) 484 PML = PyMOLUtil.SetupPMLForLigandPocketInorganicView(GroupTypeObjectName, ComplexName, LigandName, OptionsInfo["PocketDistanceCutoff"], Enable = True) 485 OutFH.write("%s\n" % PML) 486 487 # Set up cryoEM mesh and group... 488 CryoEMMeshGroupID = "%sCryoEMMeshGroup" % (GroupID) 489 CryoEMMeshGroupMembersID = "%sCryoEMMeshGroupMembers" % (GroupID) 490 CryoEMVolumeID = "%sCryoEMVolume" % (GroupID) 491 CryoEMMeshID = "%sCryoEMMesh" % (GroupID) 492 CryoEMSurfaceID = "%sCryoEMSurface" % (GroupID) 493 494 CryoEMMapName = PyMOLObjectNames["ComplexCryoEMMap"] 495 CryoEMVolumeName = PyMOLObjectNames["Ligands"][ChainID][LigandID][CryoEMVolumeID] 496 CryoEMMeshName = PyMOLObjectNames["Ligands"][ChainID][LigandID][CryoEMMeshID] 497 CryoEMSurfaceName = PyMOLObjectNames["Ligands"][ChainID][LigandID][CryoEMSurfaceID] 498 CryoEMMeshGroupName = PyMOLObjectNames["Ligands"][ChainID][LigandID][CryoEMMeshGroupID] 499 CryoEMMeshGroupMembers = PyMOLObjectNames["Ligands"][ChainID][LigandID][CryoEMMeshGroupMembersID] 500 501 PML = SetupPMLForCryoEMDensityVolume(CryoEMMapName, CryoEMVolumeName, OptionsInfo["VolumeColorRampName"], Enable = False, Selection = GroupTypeObjectName) 502 OutFH.write("\n%s\n" % PML) 503 504 ContourLevel = OptionsInfo["MeshLevels"][FileIndex] 505 PML = SetupPMLForCryoEMDensityMesh(CryoEMMapName, CryoEMMeshName, ContourLevel, OptionsInfo["MeshColor"], Enable = True, Selection = GroupTypeObjectName) 506 OutFH.write("\n%s\n" % PML) 507 508 PML = SetupPMLForCryoEMDensitySurface(CryoEMMapName, CryoEMSurfaceName, ContourLevel, OptionsInfo["MeshColor"], Enable = False, Selection = GroupTypeObjectName) 509 OutFH.write("\n%s\n" % PML) 510 511 GenerateAndWritePMLForGroup(OutFH, CryoEMMeshGroupName, CryoEMMeshGroupMembers, True, "close") 512 513 # Set up polar contacts... 514 if re.match("^(Pocket|PocketSolvent|PocketInorganic)$", GroupID, re.I): 515 PolarContactsID = "%sPolarContacts" % (GroupID) 516 PolarContactsName = PyMOLObjectNames["Ligands"][ChainID][LigandID][PolarContactsID] 517 518 PolarContactsColor = OptionsInfo["PocketContactsLigandColor"] 519 if re.match("^PocketSolvent$", GroupID, re.I): 520 PolarContactsColor = OptionsInfo["PocketContactsSolventColor"] 521 elif re.match("^PocketInorganic$", GroupID, re.I): 522 PolarContactsColor = OptionsInfo["PocketContactsInorganicColor"] 523 524 PML = PyMOLUtil.SetupPMLForPolarContactsView(PolarContactsName, LigandName, GroupTypeObjectName, Enable = False, Color = PolarContactsColor, Cutoff = OptionsInfo["PocketContactsCutoff"]) 525 OutFH.write("\n%s\n" % PML) 526 527 OutFH.write("""cmd.set("label_color", "%s", "%s")\n""" % (PolarContactsColor, PolarContactsName)) 528 529 # Set up hydrophobic contacts... 530 if re.match("^Pocket$", GroupID, re.I): 531 HydrophobicContactsID = "%sHydrophobicContacts" % (GroupID) 532 HydrophobicContactsName = PyMOLObjectNames["Ligands"][ChainID][LigandID][HydrophobicContactsID] 533 HydrophobicContactsColor = OptionsInfo["PocketContactsLigandHydrophobicColor"] 534 535 PML = PyMOLUtil.SetupPMLForHydrophobicContactsView(HydrophobicContactsName, LigandName, GroupTypeObjectName, Enable = False, Color = HydrophobicContactsColor, Cutoff = OptionsInfo["PocketContactsCutoff"]) 536 OutFH.write("\n%s\n" % PML) 537 OutFH.write("""cmd.set("label_color", "%s", "%s")\n""" % (HydrophobicContactsColor, HydrophobicContactsName)) 538 539 # Set up hydrophobic surface... 540 if re.match("^Pocket$", GroupID, re.I) and OptionsInfo["PocketSurface"]: 541 HydrophobicSurfaceID = "%sHydrophobicSurface" % (GroupID) 542 HydrophobicSurfaceName = PyMOLObjectNames["Ligands"][ChainID][LigandID][HydrophobicSurfaceID] 543 PML = PyMOLUtil.SetupPMLForHydrophobicSurfaceView(HydrophobicSurfaceName, GroupTypeObjectName, ColorPalette = "RedToWhite", Enable = False) 544 OutFH.write("\n%s\n" % PML) 545 546 OutFH.write("""cmd.set("label_color", "%s", "%s")\n""" % (OptionsInfo["PocketLabelColor"], HydrophobicSurfaceName)) 547 548 # Setup group.... 549 GroupNameID = "%sGroup" % (GroupID) 550 GroupMembersID = "%sGroupMembers" % (GroupID) 551 GroupName = PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupNameID] 552 GroupMembers = PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupMembersID] 553 554 Action = "close" 555 Enable = False 556 if re.match("^(Ligand|Pocket)$", GroupID, re.I): 557 Action = "open" 558 Enable = True 559 GenerateAndWritePMLForGroup(OutFH, GroupName, GroupMembers, Enable, Action) 560 561 def GenerateAndWritePMLForGroup(OutFH, GroupName, GroupMembers, Enable = False, Action = "close"): 562 """Generate and write PML for group.""" 563 564 PML = PyMOLUtil.SetupPMLForGroup(GroupName, GroupMembers, Enable, Action) 565 OutFH.write("""\n""\n"Setting up group %s..."\n""\n""" % GroupName) 566 OutFH.write("%s\n" % PML) 567 568 def SetupPMLForCryoEMDensityMap(MapFileName, MapName, AlignMapToObjectName = None, Enable = True): 569 """Setup PML for loading and viewing cryo-EM density map.""" 570 571 PMLCmds = [] 572 PMLCmds.append("""cmd.load("%s", "%s")""" % (MapFileName, MapName)) 573 if AlignMapToObjectName is not None: 574 PMLCmds.append("""cmd.matrix_copy("%s", "%s")""" % (AlignMapToObjectName, MapName)) 575 576 PMLCmds.append(PyMOLUtil.SetupPMLForEnableDisable(MapName, Enable)) 577 578 PML = "\n".join(PMLCmds) 579 580 return PML 581 582 def SetupPMLForCryoEMDensityMesh(MapName, MeshName, SigmaLevel, Color, Enable = True, Selection = None): 583 """Setup PML for cryo-EM density mesh.""" 584 585 Carve = OptionsInfo["MeshCarveRadius"] 586 587 PMLCmds = [] 588 if Selection is None: 589 PMLCmds.append("""cmd.isomesh("%s", "%s", %.1f)""" % (MeshName, MapName, SigmaLevel)) 590 else: 591 PMLCmds.append("""cmd.isomesh("%s", "%s", %.1f, "(%s)", carve = %.1f)""" % (MeshName, MapName, SigmaLevel, Selection, Carve)) 592 PMLCmds.append(PyMOLUtil.SetupPMLForDeepColoring(MeshName, Color)) 593 PMLCmds.append(PyMOLUtil.SetupPMLForEnableDisable(MeshName, Enable)) 594 595 PML = "\n".join(PMLCmds) 596 597 return PML 598 599 def SetupPMLForCryoEMDensityVolume(MapName, VolumeName, VolumeColorRamp, Enable = True, Selection = None): 600 """Setup PML for cryo-EM density volume.""" 601 602 Carve = OptionsInfo["VolumeCarveRadius"] 603 604 PMLCmds = [] 605 if Selection is None: 606 PMLCmds.append("""cmd.volume("%s", "%s", "%s")""" % (VolumeName, MapName, VolumeColorRamp)) 607 else: 608 PMLCmds.append("""cmd.volume("%s", "%s", "%s", "(%s)", carve = %.1f)""" % (VolumeName, MapName, VolumeColorRamp, Selection, Carve)) 609 PMLCmds.append(PyMOLUtil.SetupPMLForEnableDisable(VolumeName, Enable)) 610 611 PML = "\n".join(PMLCmds) 612 613 return PML 614 615 def SetupPMLForCryoEMDensitySurface(MapName, SurfaceName, SigmaLevel, Color, Enable = True, Selection = None): 616 """Setup PML for cryo-EM density surface.""" 617 618 Carve = OptionsInfo["MeshCarveRadius"] 619 620 PMLCmds = [] 621 if Selection is None: 622 PMLCmds.append("""cmd.isosurface("%s", "%s", %.1f)""" % (SurfaceName, MapName, SigmaLevel)) 623 else: 624 PMLCmds.append("""cmd.isosurface("%s", "%s", %.1f, "(%s)", carve = %.1f)""" % (SurfaceName, MapName, SigmaLevel, Selection, Carve)) 625 PMLCmds.append(PyMOLUtil.SetupPMLForDeepColoring(SurfaceName, Color)) 626 PMLCmds.append(PyMOLUtil.SetupPMLForEnableDisable(SurfaceName, Enable)) 627 628 PML = "\n".join(PMLCmds) 629 630 return PML 631 632 def GeneratePyMOLSessionFile(): 633 """Generate PME file from PML file.""" 634 635 PSEOutfile = OptionsInfo["PSEOutfile"] 636 PMLOutfile = OptionsInfo["PMLOutfile"] 637 638 MiscUtil.PrintInfo("\nGenerating file %s..." % PSEOutfile) 639 640 PyMOLUtil.ConvertPMLFileToPSEFile(PMLOutfile, PSEOutfile) 641 642 if not os.path.exists(PSEOutfile): 643 MiscUtil.PrintWarning("Failed to generate PSE file, %s..." % (PSEOutfile)) 644 645 if not OptionsInfo["PMLOut"]: 646 MiscUtil.PrintInfo("Deleting file %s..." % PMLOutfile) 647 os.remove(PMLOutfile) 648 649 def DeleteEmptyPyMOLObjects(OutFH, FileIndex, PyMOLObjectNames): 650 """Delete empty PyMOL objects.""" 651 652 if OptionsInfo["AllowEmptyObjects"]: 653 return 654 655 SpecifiedChainsAndLigandsInfo = OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"][FileIndex] 656 for ChainID in SpecifiedChainsAndLigandsInfo["ChainIDs"]: 657 OutFH.write("""\n""\n"Checking and deleting empty objects for chain %s..."\n""\n""" % (ChainID)) 658 659 # Delete any chain level objects... 660 WritePMLToCheckAndDeleteEmptyObjects(OutFH, PyMOLObjectNames["Chains"][ChainID]["Solvent"]) 661 WritePMLToCheckAndDeleteEmptyObjects(OutFH, PyMOLObjectNames["Chains"][ChainID]["Inorganic"]) 662 663 for LigandID in SpecifiedChainsAndLigandsInfo["LigandIDs"][ChainID]: 664 # Delete ligand level objects... 665 for GroupID in ["Pocket", "PocketSolvent", "PocketInorganic"]: 666 GroupNameID = "%sGroup" % (GroupID) 667 GroupName = PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupNameID] 668 669 GroupTypeObjectID = "%s" % (GroupID) 670 GroupTypeObjectName = PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupTypeObjectID] 671 672 WritePMLToCheckAndDeleteEmptyObjects(OutFH, GroupTypeObjectName, GroupName) 673 674 def WritePMLToCheckAndDeleteEmptyObjects(OutFH, ObjectName, ParentObjectName = None): 675 """Write PML to check and delete empty PyMOL objects.""" 676 677 if ParentObjectName is None: 678 PML = """CheckAndDeleteEmptyObjects("%s")""" % (ObjectName) 679 else: 680 PML = """CheckAndDeleteEmptyObjects("%s", "%s")""" % (ObjectName, ParentObjectName) 681 682 OutFH.write("%s\n" % PML) 683 684 def SetupPyMOLObjectNames(FileIndex): 685 """Setup hierarchy of PyMOL groups and objects for ligand centric views of 686 cryo-EM density for chains and ligands present in input file. 687 """ 688 689 PyMOLObjectNames = {} 690 PyMOLObjectNames["Chains"] = {} 691 PyMOLObjectNames["Ligands"] = {} 692 693 # Setup groups and objects for complex... 694 SetupPyMOLObjectNamesForComplex(FileIndex, PyMOLObjectNames) 695 696 # Setup groups and objects for chain... 697 SpecifiedChainsAndLigandsInfo = OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"][FileIndex] 698 for ChainID in SpecifiedChainsAndLigandsInfo["ChainIDs"]: 699 SetupPyMOLObjectNamesForChain(FileIndex, PyMOLObjectNames, ChainID) 700 701 # Setup groups and objects for ligand... 702 for LigandID in SpecifiedChainsAndLigandsInfo["LigandIDs"][ChainID]: 703 SetupPyMOLObjectNamesForLigand(FileIndex, PyMOLObjectNames, ChainID, LigandID) 704 705 return PyMOLObjectNames 706 707 def SetupPyMOLObjectNamesForComplex(FileIndex, PyMOLObjectNames): 708 """Stetup groups and objects for complex.""" 709 710 PDBFileRoot = OptionsInfo["InfilesInfo"]["InfilesRoots"][FileIndex] 711 712 PDBGroupName = "%s" % PDBFileRoot 713 PyMOLObjectNames["PDBGroup"] = PDBGroupName 714 PyMOLObjectNames["PDBGroupMembers"] = [] 715 716 ComplexGroupName = "%s.Complex" % PyMOLObjectNames["PDBGroup"] 717 PyMOLObjectNames["ComplexGroup"] = ComplexGroupName 718 PyMOLObjectNames["PDBGroupMembers"].append(ComplexGroupName) 719 720 PyMOLObjectNames["Complex"] = "%s.Complex" % ComplexGroupName 721 722 CryoEMMeshGroupName = "%s.CryoEM" % (ComplexGroupName) 723 CryoEMMapName = "%s.Map" % (CryoEMMeshGroupName) 724 CryoEMVolumeName = "%s.Volume" % (CryoEMMeshGroupName) 725 CryoEMMeshName = "%s.Mesh" % (CryoEMMeshGroupName) 726 CryoEMSurfaceName = "%s.Surface" % (CryoEMMeshGroupName) 727 728 PyMOLObjectNames["ComplexCryoEMGroup"] = CryoEMMeshGroupName 729 PyMOLObjectNames["ComplexCryoEMMap"] = CryoEMMapName 730 PyMOLObjectNames["ComplexCryoEMVolume"] = CryoEMVolumeName 731 PyMOLObjectNames["ComplexCryoEMMesh"] = CryoEMMeshName 732 PyMOLObjectNames["ComplexCryoEMSurface"] = CryoEMSurfaceName 733 734 PyMOLObjectNames["ComplexCryoEMGroupMembers"] = [] 735 PyMOLObjectNames["ComplexCryoEMGroupMembers"].append(CryoEMMapName) 736 if OptionsInfo["VolumeComplex"]: 737 PyMOLObjectNames["ComplexCryoEMGroupMembers"].append(CryoEMVolumeName) 738 if OptionsInfo["MeshComplex"]: 739 PyMOLObjectNames["ComplexCryoEMGroupMembers"].append(CryoEMMeshName) 740 if OptionsInfo["SurfaceComplex"]: 741 PyMOLObjectNames["ComplexCryoEMGroupMembers"].append(CryoEMSurfaceName) 742 743 PyMOLObjectNames["ComplexGroupMembers"] = [] 744 PyMOLObjectNames["ComplexGroupMembers"].append(PyMOLObjectNames["Complex"]) 745 PyMOLObjectNames["ComplexGroupMembers"].append(PyMOLObjectNames["ComplexCryoEMGroup"]) 746 747 def SetupPyMOLObjectNamesForChain(FileIndex, PyMOLObjectNames, ChainID): 748 """Setup groups and objects for chain.""" 749 750 PDBGroupName = PyMOLObjectNames["PDBGroup"] 751 752 SpecifiedChainsAndLigandsInfo = OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"][FileIndex] 753 MeshChainComplex = SpecifiedChainsAndLigandsInfo["MeshChainComplex"][ChainID] 754 VolumeChainComplex = SpecifiedChainsAndLigandsInfo["VolumeChainComplex"][ChainID] 755 SurfaceChainComplex = SpecifiedChainsAndLigandsInfo["SurfaceChainComplex"][ChainID] 756 757 PyMOLObjectNames["Chains"][ChainID] = {} 758 PyMOLObjectNames["Ligands"][ChainID] = {} 759 760 # Set up chain group and chain objects... 761 ChainGroupName = "%s.Chain%s" % (PDBGroupName, ChainID) 762 PyMOLObjectNames["Chains"][ChainID]["ChainGroup"] = ChainGroupName 763 PyMOLObjectNames["PDBGroupMembers"].append(ChainGroupName) 764 PyMOLObjectNames["Chains"][ChainID]["ChainGroupMembers"] = [] 765 766 # Setup chain complex group and objects... 767 ChainComplexGroupName = "%s.Complex" % (ChainGroupName) 768 PyMOLObjectNames["Chains"][ChainID]["ChainComplexGroup"] = ChainComplexGroupName 769 PyMOLObjectNames["Chains"][ChainID]["ChainGroupMembers"].append(ChainComplexGroupName) 770 771 PyMOLObjectNames["Chains"][ChainID]["ChainComplex"] = "%s.Complex" % (ChainComplexGroupName) 772 773 CryoEMMeshGroupName = "%s.CryoEM" % (ChainComplexGroupName) 774 CryoEMVolumeName = "%s.Volume" % (CryoEMMeshGroupName) 775 CryoEMMeshName = "%s.Mesh" % (CryoEMMeshGroupName) 776 CryoEMSurfaceName = "%s.Surface" % (CryoEMMeshGroupName) 777 778 PyMOLObjectNames["Chains"][ChainID]["ChainComplexCryoEMGroup"] = CryoEMMeshGroupName 779 PyMOLObjectNames["Chains"][ChainID]["ChainComplexCryoEMVolume"] = CryoEMVolumeName 780 PyMOLObjectNames["Chains"][ChainID]["ChainComplexCryoEMMesh"] = CryoEMMeshName 781 PyMOLObjectNames["Chains"][ChainID]["ChainComplexCryoEMSurface"] = CryoEMSurfaceName 782 783 PyMOLObjectNames["Chains"][ChainID]["ChainComplexCryoEMGroupMembers"] = [] 784 if VolumeChainComplex: 785 PyMOLObjectNames["Chains"][ChainID]["ChainComplexCryoEMGroupMembers"].append(CryoEMVolumeName) 786 if MeshChainComplex: 787 PyMOLObjectNames["Chains"][ChainID]["ChainComplexCryoEMGroupMembers"].append(CryoEMMeshName) 788 if SurfaceChainComplex: 789 PyMOLObjectNames["Chains"][ChainID]["ChainComplexCryoEMGroupMembers"].append(CryoEMSurfaceName) 790 791 NameIDs = ["ChainComplex"] 792 if MeshChainComplex or VolumeChainComplex or SurfaceChainComplex : 793 NameIDs.append("ChainComplexCryoEMGroup") 794 795 PyMOLObjectNames["Chains"][ChainID]["ChainComplexGroupMembers"] = [] 796 for NameID in NameIDs: 797 Name = PyMOLObjectNames["Chains"][ChainID][NameID] 798 PyMOLObjectNames["Chains"][ChainID]["ChainComplexGroupMembers"].append(Name) 799 800 # Setup up a group for individual chains... 801 ChainAloneGroupName = "%s.Chain" % (ChainGroupName) 802 PyMOLObjectNames["Chains"][ChainID]["ChainAloneGroup"] = ChainAloneGroupName 803 PyMOLObjectNames["Chains"][ChainID]["ChainGroupMembers"].append(ChainAloneGroupName) 804 805 PyMOLObjectNames["Chains"][ChainID]["ChainAloneGroupMembers"] = [] 806 807 Name = "%s.Chain" % (ChainAloneGroupName) 808 PyMOLObjectNames["Chains"][ChainID]["ChainAlone"] = Name 809 PyMOLObjectNames["Chains"][ChainID]["ChainAloneGroupMembers"].append(Name) 810 811 if OptionsInfo["BFactorChainCartoonPutty"]: 812 Name = "%s.BFactor" % (ChainAloneGroupName) 813 PyMOLObjectNames["Chains"][ChainID]["ChainAloneBFactorPutty"] = Name 814 PyMOLObjectNames["Chains"][ChainID]["ChainAloneGroupMembers"].append(Name) 815 816 if OptionsInfo["ChainSelections"]: 817 # Setup selections group and its subgroups.. 818 SelectionsGroupName = "%s.Selections" % (ChainAloneGroupName) 819 820 SelectionsGroupIDPrefix = "ChainAloneSelections" 821 SelectionsGroupID = "%sGroup" % SelectionsGroupIDPrefix 822 823 # Add selections group to chain alone group... 824 PyMOLObjectNames["Chains"][ChainID][SelectionsGroupID] = SelectionsGroupName 825 PyMOLObjectNames["Chains"][ChainID]["ChainAloneGroupMembers"].append(SelectionsGroupName) 826 827 # Initialize selections group members... 828 SelectionsGroupMembersID = "%sGroupMembers" % SelectionsGroupIDPrefix 829 PyMOLObjectNames["Chains"][ChainID][SelectionsGroupMembersID] = [] 830 831 # Setup selections name sub group and its members... 832 for SelectionName in OptionsInfo["ChainSelectionsInfo"]["Names"]: 833 SelectionNameGroupID = SelectionName 834 835 SelectionsNameGroupName = "%s.%s" % (SelectionsGroupName, SelectionName) 836 SelectionsNameGroupID = "%s%sGroup" % (SelectionsGroupIDPrefix, SelectionNameGroupID) 837 838 # Add selections name sub group to selections group... 839 PyMOLObjectNames["Chains"][ChainID][SelectionsNameGroupID] = SelectionsNameGroupName 840 PyMOLObjectNames["Chains"][ChainID][SelectionsGroupMembersID].append(SelectionsNameGroupName) 841 842 # Initialize selections names sub group members... 843 SelectionsNameGroupMembersID = "%s%sGroupMembers" % (SelectionsGroupIDPrefix, SelectionNameGroupID) 844 PyMOLObjectNames["Chains"][ChainID][SelectionsNameGroupMembersID] = [] 845 846 # Add selection object to selections name group... 847 SelectionObjectName = "%s.Selection" % (SelectionsNameGroupName) 848 SelectionObjectID = "%s%sSelection" % (SelectionsGroupIDPrefix, SelectionNameGroupID) 849 850 PyMOLObjectNames["Chains"][ChainID][SelectionObjectID] = SelectionObjectName 851 PyMOLObjectNames["Chains"][ChainID][SelectionsNameGroupMembersID].append(SelectionObjectName) 852 853 # Setup cryo-EM mesh group and add it to selections name group... 854 CryoEMMeshGroupName = "%s.CryoEM" % (SelectionsNameGroupName) 855 CryoEMMeshGroupID = "%s%sCryoEMGroup" % (SelectionsGroupIDPrefix, SelectionNameGroupID) 856 857 PyMOLObjectNames["Chains"][ChainID][CryoEMMeshGroupID] = CryoEMMeshGroupName 858 PyMOLObjectNames["Chains"][ChainID][SelectionsNameGroupMembersID].append(CryoEMMeshGroupName) 859 860 # Initialize cryo-EM mesh group members... 861 CryoEMMeshGroupMembersID = "%s%sCryoEMGroupMembers" % (SelectionsGroupIDPrefix, SelectionNameGroupID) 862 PyMOLObjectNames["Chains"][ChainID][CryoEMMeshGroupMembersID] = [] 863 864 # Setup members of cryo-EM mesh group... 865 CryoEMVolumeName = "%s.Volume" % (CryoEMMeshGroupName) 866 CryoEMVolumeID = "%s%sCryoEMVolume" % (SelectionsGroupIDPrefix, SelectionNameGroupID) 867 CryoEMMeshName = "%s.Mesh" % (CryoEMMeshGroupName) 868 CryoEMMeshID = "%s%sCryoEMMesh" % (SelectionsGroupIDPrefix, SelectionNameGroupID) 869 CryoEMSurfaceName = "%s.Surface" % (CryoEMMeshGroupName) 870 CryoEMSurfaceID = "%s%sCryoEMSurface" % (SelectionsGroupIDPrefix, SelectionNameGroupID) 871 872 PyMOLObjectNames["Chains"][ChainID][CryoEMVolumeID] = CryoEMVolumeName 873 PyMOLObjectNames["Chains"][ChainID][CryoEMMeshID] = CryoEMMeshName 874 PyMOLObjectNames["Chains"][ChainID][CryoEMSurfaceID] = CryoEMSurfaceName 875 876 PyMOLObjectNames["Chains"][ChainID][CryoEMMeshGroupMembersID].append(CryoEMVolumeName) 877 PyMOLObjectNames["Chains"][ChainID][CryoEMMeshGroupMembersID].append(CryoEMMeshName) 878 PyMOLObjectNames["Chains"][ChainID][CryoEMMeshGroupMembersID].append(CryoEMSurfaceName) 879 880 # Setup solvent and inorganic objects for chain... 881 for NameID in ["Solvent", "Inorganic"]: 882 Name = "%s.%s" % (ChainGroupName, NameID) 883 PyMOLObjectNames["Chains"][ChainID][NameID] = Name 884 PyMOLObjectNames["Chains"][ChainID]["ChainGroupMembers"].append(Name) 885 886 def SetupPyMOLObjectNamesForLigand(FileIndex, PyMOLObjectNames, ChainID, LigandID): 887 """Stetup groups and objects for ligand.""" 888 889 PyMOLObjectNames["Ligands"][ChainID][LigandID] = {} 890 891 ChainGroupName = PyMOLObjectNames["Chains"][ChainID]["ChainGroup"] 892 893 # Setup a chain level ligand group... 894 ChainLigandGroupName = "%s.Ligand%s" % (ChainGroupName, LigandID) 895 PyMOLObjectNames["Ligands"][ChainID][LigandID]["ChainLigandGroup"] = ChainLigandGroupName 896 PyMOLObjectNames["Chains"][ChainID]["ChainGroupMembers"].append(ChainLigandGroupName) 897 898 PyMOLObjectNames["Ligands"][ChainID][LigandID]["ChainLigandGroupMembers"] = [] 899 900 # Set up groups and objects for a specific ligand group... 901 for GroupType in ["Ligand", "Pocket", "Pocket_Solvent", "Pocket_Inorganic"]: 902 GroupID = re.sub("_", "", GroupType) 903 GroupName = "%s.%s" % (ChainLigandGroupName, GroupType) 904 905 GroupNameID = "%sGroup" % (GroupID) 906 GroupMembersID = "%sGroupMembers" % (GroupID) 907 908 PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupNameID] = GroupName 909 PyMOLObjectNames["Ligands"][ChainID][LigandID]["ChainLigandGroupMembers"].append(GroupName) 910 911 GroupTypeObjectName = "%s.%s" % (GroupName, GroupType) 912 GroupTypeObjectID = "%s" % (GroupID) 913 PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupTypeObjectID] = GroupTypeObjectName 914 915 CryoEMMeshGroupName = "%s.CryoEM" % (GroupName) 916 CryoEMVolumeName = "%s.Volume" % (CryoEMMeshGroupName) 917 CryoEMMeshName = "%s.Mesh" % (CryoEMMeshGroupName) 918 CryoEMSurfaceName = "%s.Surface" % (CryoEMMeshGroupName) 919 920 CryoEMMeshGroupID = "%sCryoEMMeshGroup" % (GroupID) 921 CryoEMMeshGroupMembersID = "%sCryoEMMeshGroupMembers" % (GroupID) 922 CryoEMVolumeID = "%sCryoEMVolume" % (GroupID) 923 CryoEMMeshID = "%sCryoEMMesh" % (GroupID) 924 CryoEMSurfaceID = "%sCryoEMSurface" % (GroupID) 925 926 PyMOLObjectNames["Ligands"][ChainID][LigandID][CryoEMMeshGroupID] = CryoEMMeshGroupName 927 PyMOLObjectNames["Ligands"][ChainID][LigandID][CryoEMVolumeID] = CryoEMVolumeName 928 PyMOLObjectNames["Ligands"][ChainID][LigandID][CryoEMMeshID] = CryoEMMeshName 929 PyMOLObjectNames["Ligands"][ChainID][LigandID][CryoEMSurfaceID] = CryoEMSurfaceName 930 PyMOLObjectNames["Ligands"][ChainID][LigandID][CryoEMMeshGroupMembersID] = [] 931 PyMOLObjectNames["Ligands"][ChainID][LigandID][CryoEMMeshGroupMembersID].append(CryoEMVolumeName) 932 PyMOLObjectNames["Ligands"][ChainID][LigandID][CryoEMMeshGroupMembersID].append(CryoEMMeshName) 933 PyMOLObjectNames["Ligands"][ChainID][LigandID][CryoEMMeshGroupMembersID].append(CryoEMSurfaceName) 934 935 PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupMembersID] = [] 936 NameIDs = [GroupTypeObjectID, CryoEMMeshGroupID] 937 938 for NameID in NameIDs: 939 Name = PyMOLObjectNames["Ligands"][ChainID][LigandID][NameID] 940 PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupMembersID].append(Name) 941 942 if re.match("^Ligand$", GroupType, re.I): 943 # No other object needed for Ligand group... 944 continue 945 946 PolarContactsName = "%s.Polar_Contacts" % (GroupName) 947 PolarContactsID = "%sPolarContacts" % (GroupID) 948 PyMOLObjectNames["Ligands"][ChainID][LigandID][PolarContactsID] = PolarContactsName 949 PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupMembersID].append(PolarContactsName) 950 951 if not re.match("^Pocket$", GroupType, re.I): 952 # No other object needed for any other group besides Pocket... 953 continue 954 955 if not OptionsInfo["PocketSurface"]: 956 continue 957 958 HydrophobicContactsName = "%s.Hydrophobic_Contacts" % (GroupName) 959 HydrophobicContactsID = "%sHydrophobicContacts" % (GroupID) 960 PyMOLObjectNames["Ligands"][ChainID][LigandID][HydrophobicContactsID] = HydrophobicContactsName 961 PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupMembersID].append(HydrophobicContactsName) 962 963 HydrophobicSurfaceName = "%s.Surface" % (GroupName) 964 HydrophobicSurfaceID = "%sHydrophobicSurface" % (GroupID) 965 PyMOLObjectNames["Ligands"][ChainID][LigandID][HydrophobicSurfaceID] = HydrophobicSurfaceName 966 PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupMembersID].append(HydrophobicSurfaceName) 967 968 def ProcessDensityMapFiles(): 969 """Process density map files.""" 970 971 DensityMapFiles = OptionsInfo["DensityMapFiles"] 972 if re.match("^auto$", DensityMapFiles, re.I): 973 ProcessAutoDensityMapFiles() 974 else: 975 ProcessSpecifiedDensityMapFiles() 976 977 def ProcessSpecifiedDensityMapFiles(): 978 """Process specified density map files.""" 979 980 OptionsInfo["DensityMapFilesNames"] = [] 981 982 MiscUtil.PrintInfo("\nProcessing cryo-EM density file names...") 983 984 DensityMapFiles = re.sub(" ", "", OptionsInfo["DensityMapFiles"]) 985 if not DensityMapFiles: 986 MiscUtil.PrintError("No valid value specified using \"--densityMapFiles\" option.") 987 988 DensityMapFilesWords = DensityMapFiles.split(",") 989 DensityMapFilesWordsCount = len(DensityMapFilesWords) 990 991 InfilesNamesCount = len(OptionsInfo["InfilesNames"]) 992 993 if DensityMapFilesWordsCount != InfilesNamesCount: 994 MiscUtil.PrintError("The number of comma delimited cryo-EM density map files, %d, specified using \"--DensityMapFiles\" must be equal to the number of input files, %s, specified using \"-i, --infiles\" option." % (DensityMapFilesWordsCount, InfilesNamesCount)) 995 996 for Index in range(0, InfilesNamesCount): 997 Infile = OptionsInfo["InfilesNames"][Index] 998 DensityMapFile = DensityMapFilesWords[Index] 999 1000 if not os.path.exists(DensityMapFile): 1001 MiscUtil.PrintError("The cryo-EM density ED map file, %s, specified using option \"--DensityMapFiles\", corresponding to input file, %s, doesn't exist.\n" % (DensityMapFile, Infile)) 1002 1003 OptionsInfo["DensityMapFilesNames"].append(DensityMapFile) 1004 1005 def ProcessAutoDensityMapFiles(): 1006 """Set up and process name of density map files.""" 1007 1008 OptionsInfo["DensityMapFilesNames"] = [] 1009 InfilesNamesCount = len(OptionsInfo["InfilesNames"]) 1010 1011 MiscUtil.PrintInfo("\nSetting cryo-EM density file names...") 1012 1013 for Index in range(0, InfilesNamesCount): 1014 Infile = OptionsInfo["InfilesNames"][Index] 1015 1016 EMDBID = RetrieveEMDBID(Infile) 1017 if EMDBID is None: 1018 MiscUtil.PrintError("Failed to retrieve EMDB ID from input file %s to automatically set density map file name. Use option \"-d, --densityMapFiles \" to specify density map file name and try again." % Infile) 1019 1020 DensityMapFile = None 1021 MapFileRoot = "emd_%s" % EMDBID 1022 MapFile1 = "%s.map.gz" % MapFileRoot 1023 MapFile2 = "%s.map" % MapFileRoot 1024 if os.path.exists(MapFile1): 1025 DensityMapFile = MapFile1 1026 elif os.path.exists(MapFile2): 1027 DensityMapFile = MapFile2 1028 else: 1029 MiscUtil.PrintError("Density map files %s or %s don't exist. Use option \"-d, --densityMapFiles \" to specify density map file name and try again" % (MapFile1, MapFile2)) 1030 1031 MiscUtil.PrintInfo("Setting density map file name as %s for input file %s..." % (DensityMapFile, Infile)) 1032 OptionsInfo["DensityMapFilesNames"].append(DensityMapFile) 1033 1034 def RetrieveRecommededContourLevel(Infile): 1035 """Retrieve recommened contour level.""" 1036 1037 if Infile in OptionsInfo["InfilesRecommededContourLevels"]: 1038 RecommendedContourLevel = OptionsInfo["InfilesRecommededContourLevels"][Infile] 1039 return RecommendedContourLevel 1040 1041 RecommendedContourLevel = None 1042 EMDBID = RetrieveEMDBID(Infile) 1043 if EMDBID is None: 1044 MiscUtil.PrintWarning("Failed to retrieve EMDB ID from input file %s to detect local header file already downloaded from EMDB server..." % Infile) 1045 OptionsInfo["InfilesRecommededContourLevels"][Infile] = RecommendedContourLevel 1046 return RecommendedContourLevel 1047 1048 MetadataHeaderFile = "emd-%s.xml" % (EMDBID) 1049 if not os.path.exists(MetadataHeaderFile): 1050 MiscUtil.PrintWarning("Failed to find a local header file, %s, for EMDB ID %s..." % (MetadataHeaderFile, EMDBID)) 1051 OptionsInfo["InfilesRecommededContourLevels"][Infile] = RecommendedContourLevel 1052 return RecommendedContourLevel 1053 1054 MiscUtil.PrintInfo("\nRetrieving recommeded contour level from header file, %s, for input file, %s..." % (MetadataHeaderFile, Infile)) 1055 1056 ContourLevel = None 1057 Source = None 1058 XMLTree = ElementTree.parse(MetadataHeaderFile) 1059 XMLRoot = XMLTree.getroot() 1060 1061 MapElement = XMLTree.find("map") 1062 if MapElement is not None: 1063 ContourLevelElement = MapElement.find("contourLevel") 1064 if ContourLevelElement is not None: 1065 ContourLevel = ContourLevelElement.text 1066 Source = ContourLevelElement.get("source") 1067 1068 if ContourLevel is not None: 1069 if Source is None: 1070 Source = "NA" 1071 MiscUtil.PrintInfo("Retrieved recommended (Source: %s) contour level %s..." % (Source, ContourLevel)) 1072 RecommendedContourLevel = ContourLevel 1073 1074 OptionsInfo["InfilesRecommededContourLevels"][Infile] = RecommendedContourLevel 1075 1076 return RecommendedContourLevel 1077 1078 def RetrieveEMDBID(Infile): 1079 """Retrieve EMDB ID from input file.""" 1080 1081 if Infile in OptionsInfo["InfilesEMDBIDs"]: 1082 EMDBID = OptionsInfo["InfilesEMDBIDs"][Infile] 1083 return EMDBID 1084 1085 EMDBID = None 1086 FileDir, FileName, FileExt = MiscUtil.ParseFileName(Infile) 1087 1088 if re.match("^pdb$", FileExt, re.I): 1089 EMDBID = RetriveEMDBIDFromPDBFile(Infile) 1090 elif re.match("^cif$", FileExt, re.I): 1091 EMDBID = RetriveEMDBIDFromCIFFile(Infile) 1092 else: 1093 EMDBID = None 1094 1095 OptionsInfo["InfilesEMDBIDs"][Infile] = EMDBID 1096 1097 return EMDBID 1098 1099 def RetriveEMDBIDFromPDBFile(Infile): 1100 """Retrieve EMDB ID from PDB file.""" 1101 1102 EMDBID = None 1103 InfileFH = open(Infile, "r") 1104 if InfileFH is None: 1105 MiscUtil.PrintError("Couldn't open input file: %s.\n" % (Infile)) 1106 1107 MiscUtil.PrintInfo("\nRetrieving EMDB ID from input file %s..." % Infile) 1108 1109 EMDBID = None 1110 for Line in InfileFH: 1111 Line = Line.rstrip() 1112 if re.match("^REMARK", Line, re.I): 1113 if re.search("DB: EMDB", Line, re.I): 1114 for Word in Line.split(" "): 1115 # Retrieve string with EMD- 1116 if re.search("EMD-", Word, re.I): 1117 Word = Word.strip() 1118 EMDBID = re.sub("EMD-", "", Word) 1119 break 1120 break 1121 InfileFH.close() 1122 1123 return EMDBID 1124 1125 def RetriveEMDBIDFromCIFFile(Infile): 1126 """Retrieve EMDB ID from CIF file.""" 1127 1128 InfileFH = open(Infile, "r") 1129 if InfileFH is None: 1130 MiscUtil.PrintError("Couldn't open input file: %s.\n" % (Infile)) 1131 1132 MiscUtil.PrintInfo("\nRetrieving EMDB ID from input file %s..." % Infile) 1133 1134 EMDBID = None 1135 for Line in InfileFH: 1136 Line = Line.rstrip() 1137 if re.match("^EMDB EMD", Line, re.I): 1138 for Word in Line.split(" "): 1139 # Retrieve string with EMD- 1140 if re.search("EMD-", Word, re.I): 1141 Word = Word.strip() 1142 EMDBID = re.sub("EMD-", "", Word) 1143 break 1144 break 1145 InfileFH.close() 1146 1147 return EMDBID 1148 1149 def RetrieveInfilesInfo(): 1150 """Retrieve information for input files.""" 1151 1152 InfilesInfo = {} 1153 1154 InfilesInfo["InfilesNames"] = [] 1155 InfilesInfo["InfilesRoots"] = [] 1156 InfilesInfo["ChainsAndLigandsInfo"] = [] 1157 1158 for Infile in OptionsInfo["InfilesNames"]: 1159 FileDir, FileName, FileExt = MiscUtil.ParseFileName(Infile) 1160 InfileRoot = FileName 1161 1162 ChainsAndLigandInfo = PyMOLUtil.GetChainsAndLigandsInfo(Infile, InfileRoot) 1163 1164 InfilesInfo["InfilesNames"].append(Infile) 1165 InfilesInfo["InfilesRoots"].append(InfileRoot) 1166 InfilesInfo["ChainsAndLigandsInfo"].append(ChainsAndLigandInfo) 1167 1168 OptionsInfo["InfilesInfo"] = InfilesInfo 1169 1170 def RetrieveRefFileInfo(): 1171 """Retrieve information for ref file.""" 1172 1173 RefFileInfo = {} 1174 if not OptionsInfo["Align"]: 1175 OptionsInfo["RefFileInfo"] = RefFileInfo 1176 return 1177 1178 RefFile = OptionsInfo["RefFileName"] 1179 1180 FileDir, FileName, FileExt = MiscUtil.ParseFileName(RefFile) 1181 RefFileRoot = FileName 1182 1183 if re.match("^FirstInputFile$", OptionsInfo["AlignRefFile"], re.I): 1184 ChainsAndLigandInfo = OptionsInfo["InfilesInfo"]["ChainsAndLigandsInfo"][0] 1185 else: 1186 MiscUtil.PrintInfo("\nRetrieving chain and ligand information for alignment reference file %s..." % RefFile) 1187 ChainsAndLigandInfo = PyMOLUtil.GetChainsAndLigandsInfo(RefFile, RefFileRoot) 1188 1189 RefFileInfo["RefFileName"] = RefFile 1190 RefFileInfo["RefFileRoot"] = RefFileRoot 1191 RefFileInfo["PyMOLObjectName"] = "AlignRef_%s" % RefFileRoot 1192 RefFileInfo["ChainsAndLigandsInfo"] = ChainsAndLigandInfo 1193 1194 OptionsInfo["RefFileInfo"] = RefFileInfo 1195 1196 def ProcessChainAndLigandIDs(): 1197 """Process specified chain and ligand IDs for infiles.""" 1198 1199 OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"] = [] 1200 1201 for FileIndex in range(0, len(OptionsInfo["InfilesInfo"]["InfilesNames"])): 1202 MiscUtil.PrintInfo("\nProcessing specified chain and ligand IDs for input file %s..." % OptionsInfo["InfilesInfo"]["InfilesNames"][FileIndex]) 1203 1204 ChainsAndLigandsInfo = OptionsInfo["InfilesInfo"]["ChainsAndLigandsInfo"][FileIndex] 1205 SpecifiedChainsAndLigandsInfo = PyMOLUtil.ProcessChainsAndLigandsOptionsInfo(ChainsAndLigandsInfo, "-c, --chainIDs", OptionsInfo["ChainIDs"], "-l, --ligandIDs", OptionsInfo["LigandIDs"]) 1206 ProcessChainMeshesVolumesAndSurfacesOptions(SpecifiedChainsAndLigandsInfo) 1207 OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"].append(SpecifiedChainsAndLigandsInfo) 1208 1209 CheckPresenceOfValidLigandIDs(ChainsAndLigandsInfo, SpecifiedChainsAndLigandsInfo) 1210 1211 def CheckPresenceOfValidLigandIDs(ChainsAndLigandsInfo, SpecifiedChainsAndLigandsInfo): 1212 """Check presence of valid ligand IDs.""" 1213 1214 MiscUtil.PrintInfo("\nSpecified chain IDs: %s" % (", ".join(SpecifiedChainsAndLigandsInfo["ChainIDs"]))) 1215 1216 for ChainID in SpecifiedChainsAndLigandsInfo["ChainIDs"]: 1217 if len (SpecifiedChainsAndLigandsInfo["LigandIDs"][ChainID]): 1218 MiscUtil.PrintInfo("Chain ID: %s; Specified LigandIDs: %s" % (ChainID, ", ".join(SpecifiedChainsAndLigandsInfo["LigandIDs"][ChainID]))) 1219 else: 1220 MiscUtil.PrintInfo("Chain IDs: %s; Specified LigandIDs: None" % (ChainID)) 1221 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)) 1222 1223 def RetrieveFirstChainID(FileIndex): 1224 """Get first chain ID.""" 1225 1226 ChainsAndLigandsInfo = OptionsInfo["InfilesInfo"]["ChainsAndLigandsInfo"][FileIndex] 1227 1228 FirstChainID = None 1229 if len(ChainsAndLigandsInfo["ChainIDs"]): 1230 FirstChainID = ChainsAndLigandsInfo["ChainIDs"][0] 1231 1232 return FirstChainID 1233 1234 def ProcessChainMeshesVolumesAndSurfacesOptions(SpecifiedChainsAndLigandsInfo): 1235 """Process options to create meshes and surfaces for chains.""" 1236 1237 SpecifiedChainsAndLigandsInfo["VolumeChainComplex"] = {} 1238 SpecifiedChainsAndLigandsInfo["MeshChainComplex"] = {} 1239 SpecifiedChainsAndLigandsInfo["SurfaceChainComplex"] = {} 1240 1241 SpecifiedChainsAndLigandsInfo["EnableVolumeChainComplex"] = {} 1242 SpecifiedChainsAndLigandsInfo["EnableMeshChainComplex"] = {} 1243 SpecifiedChainsAndLigandsInfo["EnableSurfaceChainComplex"] = {} 1244 1245 SpecifiedChainsAndLigandsInfo["EnableChainComplexGroup"] = {} 1246 SpecifiedChainsAndLigandsInfo["EnableChainAloneGroup"] = {} 1247 1248 for ChainID in SpecifiedChainsAndLigandsInfo["ChainIDs"]: 1249 LigandsPresent = True if len(SpecifiedChainsAndLigandsInfo["LigandIDs"][ChainID]) else False 1250 1251 # Create and enable mesh or volume in auto mode... 1252 if re.match("^auto$", OptionsInfo["MeshChainComplex"], re.I): 1253 MeshChainComplex = False if LigandsPresent else True 1254 EnableMeshChainComplex = False if LigandsPresent else True 1255 else: 1256 MeshChainComplex = True if re.match("^Yes$", OptionsInfo["MeshChainComplex"], re.I) else False 1257 EnableMeshChainComplex = True if re.match("^Yes$", OptionsInfo["MeshChainComplex"], re.I) else False 1258 1259 if re.match("^auto$", OptionsInfo["VolumeChainComplex"], re.I): 1260 VolumeChainComplex = False if LigandsPresent else True 1261 EnableVolumeChainComplex = False if LigandsPresent else True 1262 else: 1263 VolumeChainComplex = True if re.match("^Yes$", OptionsInfo["VolumeChainComplex"], re.I) else False 1264 EnableVolumeChainComplex = True if re.match("^Yes$", OptionsInfo["VolumeChainComplex"], re.I) else False 1265 1266 if MeshChainComplex and EnableMeshChainComplex: 1267 EnableVolumeChainComplex = False 1268 1269 # Create and enable surface in auto mode based on the status of mesh and volume... 1270 if re.match("^auto$", OptionsInfo["SurfaceChainComplex"], re.I): 1271 SurfaceChainComplex = False if LigandsPresent else True 1272 EnableSurfaceChainComplex = False if LigandsPresent else True 1273 1274 if MeshChainComplex or VolumeChainComplex: 1275 SurfaceChainComplex = False 1276 EnableSurfaceChainComplex = False 1277 else: 1278 SurfaceChainComplex = True if re.match("^Yes$", OptionsInfo["SurfaceChainComplex"], re.I) else False 1279 EnableSurfaceChainComplex = True if re.match("^Yes$", OptionsInfo["SurfaceChainComplex"], re.I) else False 1280 1281 if (MeshChainComplex and EnableMeshChainComplex) or (VolumeChainComplex or EnableVolumeChainComplex): 1282 EnableSurfaceChainComplex = False 1283 1284 if LigandsPresent: 1285 EnableChainComplexGroup = False 1286 EnableChainAloneGroup = True 1287 else: 1288 EnableChainComplexGroup = True 1289 EnableChainAloneGroup = False 1290 1291 SpecifiedChainsAndLigandsInfo["VolumeChainComplex"][ChainID] = VolumeChainComplex 1292 SpecifiedChainsAndLigandsInfo["MeshChainComplex"][ChainID] = MeshChainComplex 1293 SpecifiedChainsAndLigandsInfo["SurfaceChainComplex"][ChainID] = SurfaceChainComplex 1294 1295 SpecifiedChainsAndLigandsInfo["EnableVolumeChainComplex"][ChainID] = EnableVolumeChainComplex 1296 SpecifiedChainsAndLigandsInfo["EnableMeshChainComplex"][ChainID] = EnableMeshChainComplex 1297 SpecifiedChainsAndLigandsInfo["EnableSurfaceChainComplex"][ChainID] = EnableSurfaceChainComplex 1298 1299 SpecifiedChainsAndLigandsInfo["EnableChainComplexGroup"][ChainID] = EnableChainComplexGroup 1300 SpecifiedChainsAndLigandsInfo["EnableChainAloneGroup"][ChainID] = EnableChainAloneGroup 1301 1302 def ProcessChainSelections(): 1303 """Process custom selections for chains.""" 1304 1305 ChainSelectionsInfo = PyMOLUtil.ProcessChainSelectionsOptionsInfo("--selectionsChain", OptionsInfo["SelectionsChain"]) 1306 OptionsInfo["ChainSelectionsInfo"] = ChainSelectionsInfo 1307 1308 ChainSelections = True if len(OptionsInfo["ChainSelectionsInfo"]["Names"]) else False 1309 OptionsInfo["ChainSelections"] = ChainSelections 1310 1311 def ProcessMeshLevel(): 1312 """Process mesh level.""" 1313 1314 MeshLevel = OptionsInfo["MeshLevel"] 1315 1316 if re.match("^auto$", MeshLevel, re.I): 1317 ProcessAutoMeshLevel() 1318 else: 1319 ProcessSpecifiedMeshLevel() 1320 1321 def ProcessAutoMeshLevel(): 1322 """Process auto mesh level.""" 1323 1324 OptionsInfo["MeshLevels"] = [] 1325 InfilesNamesCount = len(OptionsInfo["InfilesNames"]) 1326 1327 MiscUtil.PrintInfo("\nSetting mesh levels...") 1328 1329 for Index in range(0, InfilesNamesCount): 1330 Infile = OptionsInfo["InfilesNames"][Index] 1331 1332 RecommededContourLevel = RetrieveRecommededContourLevel(Infile) 1333 if RecommededContourLevel is None: 1334 MiscUtil.PrintWarning("Failed to retrieve recommended mesh contour level from header. It's being set to 1.0. Use \"--meshLevel\" option to specify a different contour mesh level.") 1335 MeshLevel = 1.0 1336 else: 1337 MeshLevel = float(RecommededContourLevel) 1338 OptionsInfo["MeshLevels"].append(MeshLevel) 1339 1340 def ProcessSpecifiedMeshLevel(): 1341 """Process specified mesh level.""" 1342 1343 MiscUtil.PrintInfo("\nProcessing mesh levels...") 1344 1345 OptionsInfo["MeshLevels"] = [] 1346 InfilesNamesCount = len(OptionsInfo["InfilesNames"]) 1347 1348 MeshLevels = re.sub(" ", "", OptionsInfo["MeshLevel"]) 1349 if not MeshLevels: 1350 MiscUtil.PrintError("No valid value specified using \"--meshLevel\" option.") 1351 1352 MeshLevelWords = MeshLevels.split(",") 1353 MeshLevelWordsCount = len(MeshLevelWords) 1354 1355 if MeshLevelWordsCount != InfilesNamesCount: 1356 MiscUtil.PrintError("The number of comma delimited mesh levels, %d, specified using \"--meshLevel\" must be equal to the number of input files, %s, specified using \"-i, --infiles\" option." % (MeshLevelWordsCount, InfilesNamesCount)) 1357 1358 for Index in range(0, InfilesNamesCount): 1359 Infile = OptionsInfo["InfilesNames"][Index] 1360 MeshLevel = MeshLevelWords[Index] 1361 if not MiscUtil.IsFloat(MeshLevel): 1362 MiscUtil.PrintError("The mesh level, %s, specified using \"--meshLevel\" for input file, %s, must be a float." % (MeshLevel, Infile)) 1363 1364 MeshLevel = float(MeshLevel) 1365 OptionsInfo["MeshLevels"].append(MeshLevel) 1366 1367 def ProcessVolumeColorRamp(): 1368 """Process volume color ramp.""" 1369 1370 MiscUtil.PrintInfo("\nProcessing volume color ramp...") 1371 1372 ColorRamp = Options["--volumeColorRamp"] 1373 ColorRampName = None 1374 CreateColorRamp = False 1375 ColorRampContourLevel = None 1376 if re.match("^auto$", ColorRamp, re.I): 1377 FirstInfile = OptionsInfo["InfilesNames"][0] 1378 RecommededContourLevel = RetrieveRecommededContourLevel(FirstInfile) 1379 if RecommededContourLevel is None: 1380 ColorRampName = "default" 1381 MiscUtil.PrintWarning("Failed to retrieve recommended contour level from header file corresponding to input file, %s, to create a new ramp. Using PyMOL default volume color ramp." % (FirstInfile)) 1382 else: 1383 ColorRampName = "CryoEMAuto" 1384 CreateColorRamp = True 1385 ColorRampContourLevel = float(RecommededContourLevel) 1386 MiscUtil.PrintInfo("\nSetting up a new volume color ramp, %s, at recommended contour level, %.2f, from input file, %s..." % (ColorRampName, ColorRampContourLevel, FirstInfile)) 1387 else: 1388 ColorRampName = ColorRamp 1389 1390 OptionsInfo["VolumeColorRamp"] = ColorRamp 1391 OptionsInfo["VolumeColorRampName"] = ColorRampName 1392 OptionsInfo["VolumeColorRampCreate"] = CreateColorRamp 1393 OptionsInfo["VolumeColorRampContourLevel"] = ColorRampContourLevel 1394 1395 def ProcessOptions(): 1396 """Process and validate command line arguments and options.""" 1397 1398 MiscUtil.PrintInfo("Processing options...") 1399 1400 # Validate options... 1401 ValidateOptions() 1402 1403 OptionsInfo["Align"] = True if re.match("^Yes$", Options["--align"], re.I) else False 1404 OptionsInfo["AlignMethod"] = Options["--alignMethod"].lower() 1405 OptionsInfo["AlignMode"] = Options["--alignMode"] 1406 1407 OptionsInfo["AllowEmptyObjects"] = True if re.match("^Yes$", Options["--allowEmptyObjects"], re.I) else False 1408 1409 OptionsInfo["BFactorChainCartoonPutty"] = True if re.match("^Yes$", Options["--BFactorChainCartoonPutty"], re.I) else False 1410 OptionsInfo["BFactorColorPalette"] = Options["--BFactorColorPalette"] 1411 1412 OptionsInfo["Infiles"] = Options["--infiles"] 1413 OptionsInfo["InfilesNames"] = Options["--infileNames"] 1414 1415 OptionsInfo["InfilesEMDBIDs"] = {} 1416 OptionsInfo["InfilesRecommededContourLevels"] = {} 1417 1418 OptionsInfo["AlignRefFile"] = Options["--alignRefFile"] 1419 if re.match("^FirstInputFile$", Options["--alignRefFile"], re.I): 1420 OptionsInfo["RefFileName"] = OptionsInfo["InfilesNames"][0] 1421 else: 1422 OptionsInfo["RefFileName"] = Options["--alignRefFile"] 1423 1424 OptionsInfo["IgnoreHydrogens"] = True if re.match("^Yes$", Options["--ignoreHydrogens"], re.I) else False 1425 1426 OptionsInfo["DensityMapFiles"] = Options["--densityMapFiles"] 1427 ProcessDensityMapFiles() 1428 1429 OptionsInfo["Overwrite"] = Options["--overwrite"] 1430 OptionsInfo["PMLOut"] = True if re.match("^Yes$", Options["--PMLOut"], re.I) else False 1431 1432 OptionsInfo["Outfile"] = Options["--outfile"] 1433 FileDir, FileName, FileExt = MiscUtil.ParseFileName(OptionsInfo["Outfile"]) 1434 OptionsInfo["PSEOut"] = False 1435 if re.match("^pml$", FileExt, re.I): 1436 OptionsInfo["PMLOutfile"] = OptionsInfo["Outfile"] 1437 OptionsInfo["PMEOutfile"] = re.sub(".pml$", ".pme", OptionsInfo["Outfile"]) 1438 elif re.match("^pse$", FileExt, re.I): 1439 OptionsInfo["PSEOut"] = True 1440 OptionsInfo["PSEOutfile"] = OptionsInfo["Outfile"] 1441 OptionsInfo["PMLOutfile"] = re.sub(".pse$", ".pml", OptionsInfo["Outfile"]) 1442 if os.path.exists(OptionsInfo["PMLOutfile"]) and (not OptionsInfo["Overwrite"]): 1443 MiscUtil.PrintError("The intermediate output file to be generated, %s, already exist. Use option \"--ov\" or \"--overwrite\" and try again." % OptionsInfo["PMLOutfile"] ) 1444 1445 OptionsInfo["LabelFontID"] = int(Options["--labelFontID"]) 1446 1447 # Process mesh parameters... 1448 OptionsInfo["MeshCarveRadius"] = float(Options["--meshCarveRadius"]) 1449 OptionsInfo["MeshComplex"] = True if re.match("^Yes$", Options["--meshComplex"], re.I) else False 1450 OptionsInfo["MeshChainComplex"] = Options["--meshChainComplex"] 1451 1452 OptionsInfo["MeshWidth"] = float(Options["--meshWidth"]) 1453 OptionsInfo["MeshColor"] = Options["--meshColor"] 1454 1455 OptionsInfo["MeshLevel"] = Options["--meshLevel"] 1456 ProcessMeshLevel() 1457 1458 OptionsInfo["SurfaceComplex"] = True if re.match("^Yes$", Options["--surfaceComplex"], re.I) else False 1459 OptionsInfo["SurfaceChainComplex"] = Options["--surfaceChainComplex"] 1460 OptionsInfo["SurfaceTransparency"] = float(Options["--surfaceTransparency"]) 1461 1462 OptionsInfo["PocketContactsLigandColor"] = Options["--pocketContactsLigandColor"] 1463 OptionsInfo["PocketContactsLigandHydrophobicColor"] = Options["--pocketContactsLigandHydrophobicColor"] 1464 OptionsInfo["PocketContactsSolventColor"] = Options["--pocketContactsSolventColor"] 1465 OptionsInfo["PocketContactsInorganicColor"] = Options["--pocketContactsInorganicColor"] 1466 1467 OptionsInfo["PocketContactsCutoff"] = float(Options["--pocketContactsCutoff"]) 1468 OptionsInfo["PocketDistanceCutoff"] = float(Options["--pocketDistanceCutoff"]) 1469 1470 OptionsInfo["PocketLabelColor"] = Options["--pocketLabelColor"] 1471 OptionsInfo["PocketSurface"] = True if re.match("^Yes$", Options["--pocketSurface"], re.I) else False 1472 1473 OptionsInfo["SelectionsChain"] = Options["--selectionsChain"] 1474 OptionsInfo["SelectionsChainStyle"] = Options["--selectionsChainStyle"] 1475 ProcessChainSelections() 1476 1477 OptionsInfo["VolumeCarveRadius"] = float(Options["--volumeCarveRadius"]) 1478 OptionsInfo["VolumeComplex"] = True if re.match("^Yes$", Options["--volumeComplex"], re.I) else False 1479 OptionsInfo["VolumeChainComplex"] = Options["--volumeChainComplex"] 1480 1481 ProcessVolumeColorRamp() 1482 1483 RetrieveInfilesInfo() 1484 RetrieveRefFileInfo() 1485 1486 OptionsInfo["ChainIDs"] = Options["--chainIDs"] 1487 OptionsInfo["LigandIDs"] = Options["--ligandIDs"] 1488 1489 ProcessChainAndLigandIDs() 1490 1491 def RetrieveOptions(): 1492 """Retrieve command line arguments and options.""" 1493 1494 # Get options... 1495 global Options 1496 Options = docopt(_docoptUsage_) 1497 1498 # Set current working directory to the specified directory... 1499 WorkingDir = Options["--workingdir"] 1500 if WorkingDir: 1501 os.chdir(WorkingDir) 1502 1503 # Handle examples option... 1504 if "--examples" in Options and Options["--examples"]: 1505 MiscUtil.PrintInfo(MiscUtil.GetExamplesTextFromDocOptText(_docoptUsage_)) 1506 sys.exit(0) 1507 1508 def ValidateOptions(): 1509 """Validate option values.""" 1510 1511 MiscUtil.ValidateOptionTextValue("--align", Options["--align"], "yes no") 1512 MiscUtil.ValidateOptionTextValue("--alignMethod", Options["--alignMethod"], "align cealign super") 1513 MiscUtil.ValidateOptionTextValue("--alignMode", Options["--alignMode"], "FirstChain Complex") 1514 1515 MiscUtil.ValidateOptionTextValue("--allowEmptyObjects", Options["--allowEmptyObjects"], "yes no") 1516 1517 MiscUtil.ValidateOptionTextValue("--BFactorChainCartoonPutty", Options["--BFactorChainCartoonPutty"], "yes no") 1518 1519 # Expand infiles to handle presence of multiple input files... 1520 InfileNames = MiscUtil.ExpandFileNames(Options["--infiles"], ",") 1521 if not len(InfileNames): 1522 MiscUtil.PrintError("No input files specified for \"-i, --infiles\" option") 1523 1524 # Validate file extensions... 1525 for Infile in InfileNames: 1526 MiscUtil.ValidateOptionFilePath("-i, --infiles", Infile) 1527 MiscUtil.ValidateOptionFileExt("-i, --infiles", Infile, "pdb cif") 1528 MiscUtil.ValidateOptionsDistinctFileNames("-i, --infiles", Infile, "-o, --outfile", Options["--outfile"]) 1529 Options["--infileNames"] = InfileNames 1530 1531 MiscUtil.ValidateOptionFileExt("-o, --outfile", Options["--outfile"], "pml pse") 1532 MiscUtil.ValidateOptionsOutputFileOverwrite("-o, --outfile", Options["--outfile"], "--overwrite", Options["--overwrite"]) 1533 1534 if re.match("^yes$", Options["--align"], re.I): 1535 if not re.match("^FirstInputFile$", Options["--alignRefFile"], re.I): 1536 AlignRefFile = Options["--alignRefFile"] 1537 MiscUtil.ValidateOptionFilePath("--alignRefFile", AlignRefFile) 1538 MiscUtil.ValidateOptionFileExt("--alignRefFile", AlignRefFile, "pdb cif") 1539 MiscUtil.ValidateOptionsDistinctFileNames("--AlignRefFile", AlignRefFile, "-o, --outfile", Options["--outfile"]) 1540 1541 MiscUtil.ValidateOptionTextValue("--ignoreHydrogens", Options["--ignoreHydrogens"], "yes no") 1542 1543 MiscUtil.ValidateOptionTextValue("--PMLOut", Options["--PMLOut"], "yes no") 1544 MiscUtil.ValidateOptionIntegerValue("--labelFontID", Options["--labelFontID"], {}) 1545 1546 MiscUtil.ValidateOptionFloatValue("--meshCarveRadius", Options["--meshCarveRadius"], {">": 0.0}) 1547 MiscUtil.ValidateOptionTextValue("--meshComplex", Options["--meshComplex"], "yes no") 1548 MiscUtil.ValidateOptionTextValue("--meshChainComplex", Options["--meshChainComplex"], "yes no auto") 1549 MiscUtil.ValidateOptionFloatValue("--meshWidth", Options["--meshWidth"], {">": 0.0}) 1550 1551 MiscUtil.ValidateOptionTextValue("--PMLOut", Options["--PMLOut"], "yes no") 1552 1553 MiscUtil.ValidateOptionFloatValue("--pocketContactsCutoff", Options["--pocketContactsCutoff"], {">": 0.0}) 1554 MiscUtil.ValidateOptionFloatValue("--pocketDistanceCutoff", Options["--pocketDistanceCutoff"], {">": 0.0}) 1555 if (float(Options["--pocketContactsCutoff"]) > float(Options["--pocketDistanceCutoff"])): 1556 MiscUtil.PrintError("The value, %s, specified using option \"--pocketContactsCutoff\" must be less than value, %s, specified using \"-pocketDistanceCutoff\" option." % (Options["--pocketContactsCutoff"], Options["--pocketDistanceCutoff"])) 1557 1558 MiscUtil.ValidateOptionTextValue("--pocketSurface", Options["--pocketSurface"], "yes no") 1559 1560 MiscUtil.ValidateOptionTextValue("--surfaceComplex", Options["--surfaceComplex"], "yes no") 1561 MiscUtil.ValidateOptionTextValue("--surfaceChainComplex", Options["--surfaceChainComplex"], "yes no auto") 1562 MiscUtil.ValidateOptionFloatValue("--surfaceTransparency", Options["--surfaceTransparency"], {">=": 0.0, "<=": 1.0}) 1563 1564 MiscUtil.ValidateOptionFloatValue("--volumeCarveRadius", Options["--volumeCarveRadius"], {">": 0.0}) 1565 MiscUtil.ValidateOptionTextValue("--volumeComplex", Options["--volumeComplex"], "yes no") 1566 MiscUtil.ValidateOptionTextValue("--volumeChainComplex", Options["--volumeChainComplex"], "yes no auto") 1567 1568 # Setup a usage string for docopt... 1569 _docoptUsage_ = """ 1570 PyMOLVisualizeCryoEMDensity.py - Visualize cryo-EM density 1571 1572 Usage: 1573 PyMOLVisualizeCryoEMDensity.py [--align <yes or no>] [--alignMethod <align, cealign, super>] 1574 [--alignMode <FirstChain or Complex>] [--alignRefFile <filename>] 1575 [--allowEmptyObjects <yes or no>] [--BFactorChainCartoonPutty <yes or no>] 1576 [--BFactorColorPalette <text> ] [--chainIDs <First, All or ID1,ID2...>] 1577 [--densityMapFiles <file1,file2,file3,...>] 1578 [--ignoreHydrogens <yes or no>] [--ligandIDs <Largest, All or ID1,ID2...>] [--labelFontID <number>] 1579 [--meshCarveRadius <number>] [--meshComplex <yes or no>] 1580 [--meshChainComplex <yes, no, or auto>] [--meshColor <text>] 1581 [--meshLevel <number>] [--meshWidth <number>] [--PMLOut <yes or no>] 1582 [--pocketContactsLigandColor <text>] [--pocketContactsLigandHydrophobicColor <text>] 1583 [--pocketContactsSolventColor <text>] [--pocketContactsCutoff <number>] 1584 [--pocketContactsInorganicColor <text>] [--pocketDistanceCutoff <number>] 1585 [--pocketLabelColor <text>] [--pocketSurface <yes or no>] 1586 [--selectionsChain <ObjectName,SelectionSpec,...>] [--selectionsChainStyle <DisplayStyle>] 1587 [--surfaceComplex <yes or no>] [--surfaceChainComplex <yes, no or auto>] 1588 [--surfaceTransparency <number>] [--volumeCarveRadius <number>] 1589 [--volumeComplex <yes or no>] [--volumeChainComplex <yes, no, or auto>] 1590 [--volumeColorRamp <text>] [--overwrite] [-w <dir>] -i <infile1,infile2,...> -o <outfile> 1591 PyMOLVisualizeCryoEMDensity.py -h | --help | -e | --examples 1592 1593 Description: 1594 Generate PyMOL visualization files for viewing electron microscopy (EM) or 1595 cryo-EM density around chains, ligands, and ligand binding pockets in 1596 macromolecules including proteins and nucleic acids. 1597 1598 The supported input file formats are: Macromolecule - PDB (.pdb) or CIF(.cif), 1599 Cryo-EM Density - Collaborative Computational Project Number 4 (CCP4) ( .map) 1600 1601 The supported output file formats are: PyMOL script file (.pml), PyMOL session 1602 file (.pse) 1603 1604 The cryo-EM density and header files along with PDB files may be downloaded 1605 from appropriate servers using DownloadPDBFiles.pl script. 1606 1607 A variety of PyMOL groups and objects may be created for visualization of 1608 cryo-EM density present in map files. These groups and objects correspond to 1609 maps, volumes, meshes, surfaces,chains, ligands, inorganics, ligand binding 1610 pockets, polar interactions, and pocket hydrophobic surfaces. A complete 1611 hierarchy of all possible PyMOL groups and objects is shown below: 1612 1613 <PDBFileRoot> 1614 .Complex 1615 .Complex 1616 .CryoEM 1617 .Map 1618 .Volume 1619 .Mesh 1620 .Surface 1621 .Chain<ID> 1622 .Complex 1623 .Complex 1624 .CryoEM 1625 .Volume 1626 .Mesh 1627 .Surface 1628 .Chain 1629 .Chain 1630 .BFactor 1631 .Selections 1632 .<Name1> 1633 .Selection 1634 .CryoEM 1635 .Volume 1636 .Mesh 1637 .Surface 1638 .<Name2> 1639 ... ... .. 1640 .Solvent 1641 .Inorganic 1642 .Ligand<ID> 1643 .Ligand 1644 .Ligand 1645 .CryoEM 1646 .Volume 1647 .Mesh 1648 .Surface 1649 .Pocket 1650 .Pocket 1651 .CryoEM 1652 .Volume 1653 .Mesh 1654 .Surface 1655 .Polar_Contacts 1656 .Hydrophobic_Contacts 1657 .Surface 1658 .Pocket_Solvent 1659 .Pocket_Solvent 1660 .CryoEM 1661 .Volume 1662 .Mesh 1663 .Surface 1664 .Polar_Contacts 1665 .Pocket_Inorganic 1666 .Pocket_Inorganic 1667 .CryoEM 1668 .Volume 1669 .Mesh 1670 .Surface 1671 .Polar_Contacts 1672 .Ligand<ID> 1673 .Ligand 1674 ... ... ... 1675 .Pocket 1676 ... ... ... 1677 .Pocket_Solvent 1678 ... ... ... 1679 .Pocket_Inorganic 1680 ... ... ... 1681 .Chain<ID> 1682 ... ... ... 1683 .Ligand<ID> 1684 ... ... ... 1685 .Ligand<ID> 1686 ... ... ... 1687 .Chain<ID> 1688 ... ... ... 1689 <PDBFileRoot> 1690 .Complex 1691 ... ... ... 1692 .Chain<ID> 1693 ... ... ... 1694 .Ligand<ID> 1695 ... ... ... 1696 .Ligand<ID> 1697 ... ... ... 1698 .Chain<ID> 1699 ... ... ... 1700 1701 The meshes, volumes, and surfaces are not created for complete complex in input 1702 files by default. A word to the wise: The creation of these mesh, volume, and surface 1703 objects may slow down loading of PML file and generation of PSE file, based on the 1704 size of input complex and map files. The generation of PSE file may also fail. In 1705 addition, you may want to interactively manipulate the contour level for meshes, 1706 volumes, and surfaces. The recommended value for contour level is automatically 1707 retrieved from header files available from EM density server. The recommended 1708 value may not always work. 1709 1710 Options: 1711 -a, --align <yes or no> [default: no] 1712 Align input files to a reference file before visualization along with 1713 available cryo-EM density map files. 1714 --alignMethod <align, cealign, super> [default: super] 1715 Alignment methodology to use for aligning input files to a reference 1716 file. 1717 --alignMode <FirstChain or Complex> [default: FirstChain] 1718 Portion of input and reference files to use for spatial alignment of 1719 input files against reference file. Possible values: FirstChain or 1720 Complex. 1721 1722 The FirstChain mode allows alignment of the first chain in each input 1723 file to the first chain in the reference file along with moving the rest 1724 of the complex to coordinate space of the reference file. The complete 1725 complex in each input file is aligned to the complete complex in reference 1726 file for the Complex mode. 1727 --alignRefFile <filename> [default: FirstInputFile] 1728 Reference input file name. The default is to use the first input file 1729 name specified using '-i, --infiles' option. 1730 --allowEmptyObjects <yes or no> [default: no] 1731 Allow creation of empty PyMOL objects corresponding to solvent and 1732 inorganic atom selections across chains, ligands, and ligand binding pockets 1733 in input file(s). 1734 -b, --BFactorChainCartoonPutty <yes or no> [default: yes] 1735 A cartoon putty around individual chains colored by B factors. The minimum 1736 and maximum values for B factors are automatically detected. These values 1737 indicate spread of cryo-EM density around atoms. The 'blue_white_red' color 1738 palette is deployed for coloring the cartoon putty. 1739 --BFactorColorPalette <text> [default: blue_white_red] 1740 Color palette for coloring cartoon putty around chains generated using B 1741 factors. Any valid PyMOL color palette name is allowed. No validation is 1742 performed. The complete list of valid color palette names is a available 1743 at: pymolwiki.org/index.php/Spectrum. Examples: blue_white_red, 1744 blue_white_magenta, blue_red, green_white_red, green_red. 1745 -c, --chainIDs <First, All or ID1,ID2...> [default: First] 1746 List of chain IDs to use for visualizing cryo-EM density. Possible values: 1747 First, All, or a comma delimited list of chain IDs. The default is to use the 1748 chain ID for the first chain in each input file. 1749 -d, --densityMapFiles <file1,file2,file3,...> [default: auto] 1750 CryoEM density map file names. The EMDB ID is retrieved from PDB and CIF 1751 file to set the cryo-EM density file name during automatic detection of 1752 density files. The format of the file name is as follows: 1753 1754 emd_<EMDBID>.map.gz or emd_<EMDBID>.map 1755 1756 The density files must be present in the working directory. 1757 -e, --examples 1758 Print examples. 1759 -h, --help 1760 Print this help message. 1761 -i, --infiles <infile1,infile2,infile3...> 1762 Input file names. 1763 --ignoreHydrogens <yes or no> [default: yes] 1764 Ignore hydrogens for ligand and pocket views. 1765 -l, --ligandIDs <Largest, All or ID1,ID2...> [default: Largest] 1766 List of ligand IDs present in chains for visualizing cryo-EM density across 1767 ligands and ligand binding pockets. Possible values: Largest, All, or a comma 1768 delimited list of ligand IDs. The default is to use the largest ligand present 1769 in all or specified chains in each input file. 1770 1771 Ligands are identified using organic selection operator available in PyMOL. 1772 It'll also identify buffer molecules as ligands. The largest ligand contains 1773 the highest number of heavy atoms. 1774 --labelFontID <number> [default: 7] 1775 Font ID for drawing labels. Default: 7 (Sans Bold). Valid values: 5 to 16. 1776 The specified value must be a valid PyMOL font ID. No validation is 1777 performed. The complete lists of valid font IDs is available at: 1778 pymolwiki.org/index.php/Label_font_id. Examples: 5 - Sans; 1779 7 - Sans Bold; 9 - Serif; 10 - Serif Bold. 1780 --meshCarveRadius <number> [default: 1.6] 1781 Radius in Angstroms around atoms for including cryo-EM density. 1782 --meshComplex <yes or no> [default: no] 1783 Create meshes for complete complex in each input file using corresponding 1784 density map file. 1785 --meshChainComplex <yes, no, or auto> [default: auto] 1786 Create meshes for individual chain complex in each input file using 1787 corresponding density map file. By default, the meshes are automatically 1788 created for chain complexes without any ligands. 1789 --meshColor <text> [default: blue] 1790 Line color for meshes corresponding to density maps.. The specified value 1791 must be valid color. No validation is performed. 1792 --meshLevel <number1,number2,...> [default: auto] 1793 Comma delimited list of contour levels in sigma units for generating meshes 1794 for each input file using corresponding density map file. The default is to 1795 automatically retrieve the recommended contour levels for each input 1796 file. The header file emd-<EMDBID>.xml corresponding to an input file 1797 must be present in the working directory to automatically retrieve 1798 recommended value for mesh contour level. Otherwise, the default contour 1799 level is set to 1. 1800 1801 You may want to interactively manipulate the contour level for meshes and 1802 surfaces. The default recommended value may not always work. 1803 --meshWidth <number> [default: 0.5] 1804 Line width for mesh lines corresponding to density maps. 1805 -o, --outfile <outfile> 1806 Output file name. 1807 -p, --PMLOut <yes or no> [default: yes] 1808 Save PML file during generation of PSE file. 1809 --pocketContactsLigandColor <text> [default: orange] 1810 Color for drawing polar contacts between ligand and pocket residues. 1811 The specified value must be valid color. No validation is performed. 1812 --pocketContactsLigandHydrophobicColor <text> [default: purpleblue] 1813 Color for drawing hydrophobic contacts between ligand and pocket residues. 1814 The specified value must be valid color. No validation is performed. The 1815 hydrophobic contacts are shown between pairs of carbon atoms not 1816 connected to hydrogen bond donor or acceptors atoms as identified 1817 by PyMOL. 1818 --pocketContactsSolventColor <text> [default: marine] 1819 Color for drawing polar contacts between solvent and pocket residues. 1820 The specified value must be valid color. No validation is performed. 1821 --pocketContactsInorganicColor <text> [default: deepsalmon] 1822 Color for drawing polar contacts between inorganic and pocket residues. 1823 The specified value must be valid color. No validation is performed. 1824 --pocketContactsCutoff <number> [default: 4.0] 1825 Distance in Angstroms for identifying polar and hyrdophobic contacts 1826 between atoms in pocket residues and ligands. 1827 --pocketDistanceCutoff <number> [default: 5.0] 1828 Distance in Angstroms for identifying pocket residues around ligands. 1829 --pocketLabelColor <text> [default: magenta] 1830 Color for drawing residue or atom level labels for a pocket. The specified 1831 value must be valid color. No validation is performed. 1832 --pocketSurface <yes or no> [default: yes] 1833 Hydrophobic surface around pocket. The pocket surface is colored by 1834 hydrophobicity. It is only valid for proteins. The color of amino acids is 1835 set using the Eisenberg hydrophobicity scale. The color varies from red 1836 to white, red being the most hydrophobic amino acid. 1837 --selectionsChain <ObjectName,SelectionSpec,...> [default: None] 1838 Custom selections for chains. It is a pairwise list of comma delimited values 1839 corresponding to PyMOL object names and selection specifications. The 1840 selection specification must be a valid PyMOL specification. No validation is 1841 performed. 1842 1843 The PyMOL objects are created for each chain corresponding to the 1844 specified selections. The display style for PyMOL objects is set using 1845 value of '--selectionsChainStyle' option. 1846 1847 The specified selection specification is automatically appended to appropriate 1848 chain specification before creating PyMOL objects. 1849 1850 For example, the following specification for '--selectionsChain' option will 1851 generate PyMOL objects for chains containing Cysteines and Serines: 1852 1853 Cysteines,resn CYS,Serines,resn SER 1854 1855 --selectionsChainStyle <DisplayStyle> [default: sticks] 1856 Display style for PyMOL objects created for '--selectionsChain' option. It 1857 must be a valid PyMOL display style. No validation is performed. 1858 --surfaceComplex <yes or no> [default: no] 1859 Create surfaces for complete complex in input file(s) corresponding to density 1860 map. 1861 --surfaceChainComplex <yes, no or auto> [default: auto] 1862 Create surfaces for individual chain complexes in each input file using corresponding 1863 density map file. By default, the surfaces are automatically created for chain complexes 1864 without any ligands. 1865 --surfaceTransparency <number> [default: 0.25] 1866 Surface transparency for molecular and cryo-EM density surfaces. 1867 --overwrite 1868 Overwrite existing files. 1869 --volumeCarveRadius <number> [default: 1.6] 1870 Radius in Angstroms around atoms for including cryo-EM density. 1871 --volumeComplex <yes or no> [default: no] 1872 Create volumes for complete complex in each input file using corresponding density 1873 map file. 1874 --volumeChainComplex <yes, no, or auto> [default: auto] 1875 Create volumes for individual chain complex in each input file using corresponding 1876 density map file. By default, the volumes are automatically created for chain 1877 complexes without any ligands. 1878 --volumeColorRamp <text> [default: auto] 1879 Name of a volume color ramp for density map files. The specified value must 1880 be a valid name. No validation is performed. The following volume color ramps 1881 are currently available in PyMOL: default, 2fofc, fofc, rainbow, and rainbow2. 1882 1883 The default is to automatically create a new volume color ramp for the first 1884 input file using recommended contour level with an offset of 0.3 around this value. 1885 The header file emd-<EMDBID>.xml must be present in the working directory to 1886 automatically retrieve recommended contour level and generate a volume color ramp. 1887 Otherwise, PyMOL default volume color ramp is employed to color volumes. 1888 1889 The volume color ramp automatically created for the first input file is used for all 1890 other input files. 1891 -w, --workingdir <dir> 1892 Location of working directory which defaults to the current directory. 1893 1894 Examples: 1895 To download structure and cryo-EM data for 5K12, 5UMD, 5W81, and 5UAK 1896 before running the following examples, type: 1897 1898 % DownloadPDBFiles.pl --DensityMap yes 5K12,5UMD,5W81,5UAK 1899 1900 To visualize cryo-EM density at recommended contour level for the first 1901 chain complex in a PDB file using corresponding density map and header 1902 file, and generate a PML file type: 1903 1904 % PyMOLVisualizeCryoEMDensity.py -i 5K12.pdb -o 5K12.pml 1905 1906 To visualize cryo-EM density at recommended contour level for the first 1907 chain complex in a PDB file and highlighting densities for all cysteines and 1908 serines using corresponding density map and header file, and generate 1909 a PML file type: 1910 1911 % PyMOLVisualizeCryoEMDensity.py -i 5K12.pdb -o 5K12.pml 1912 --selectionsChain "Csysteines,resn cys,Serines,resn ser" 1913 1914 To visualize electron density for the largest ligand in chain K, and ligand 1915 binding pocket to highlight ligand interactions with pockect residues, 1916 solvents and inorganics, in a PDB and using corresponding map files, and 1917 generate a PML file, type: 1918 1919 % PyMOLVisualizeCryoEMDensity.py -c K -i 5UMD.cif -o 5UMD.pml 1920 1921 To visualize cryo-EM density for all chains along with any solvents in a 1922 PDB file and using corresponding map files, and generate a PML file, type: 1923 1924 % PyMOLVisualizeCryoEMDensity.py -c all -i 5K12.pdb -o 5K12.pml 1925 1926 To visualize cryo-EM density at a specific contour level for the first chain 1927 complex along with volume and surface in a PDB file using corresponding 1928 to a specific density map file, and generate a PML file, type: 1929 1930 % PyMOLVisualizeCryoEMDensity.py -d emd_8194.map.gz --meshLevel 1.0 1931 --surfaceChainComplex yes --volumeChainComplex yes -i 5K12.pdb 1932 -o 5K12.pml 1933 1934 To align and visualize cryo-EM density at recommended contour levels for the 1935 largest ligand in the first chain along with pockets or the first chain complex 1936 in input files using corresponding maps and header files, type: 1937 1938 % PyMOLVisualizeCryoEMDensity.py -a yes -i "5W81.pdb,5UAK.pdb" 1939 -o SampleOut.pml 1940 1941 To align and visualize cryo-EM density at recommended contour levels for all 1942 chains and ligands in input files using specified density files, type: 1943 in input files using corresponding maps and header files, type: 1944 1945 % PyMOLVisualizeCryoEMDensity.py -a yes -i "5W81.pdb,5UAK.pdb" 1946 -o SampleOut.pml -c all -l all -d "emd_8782.map.gz,emd_8516.map.gz" 1947 1948 Author: 1949 Manish Sud(msud@san.rr.com) 1950 1951 See also: 1952 DownloadPDBFiles.pl, PyMOLVisualizeCavities.py, 1953 PyMOLVisualizeElectronDensity.py, PyMOLVisualizeInterfaces.py, 1954 PyMOLVisualizeMacromolecules.py, PyMOLVisualizeSurfaceAndBuriedResidues.py 1955 1956 Copyright: 1957 Copyright (C) 2024 Manish Sud. All rights reserved. 1958 1959 The functionality available in this script is implemented using PyMOL, a 1960 molecular visualization system on an open source foundation originally 1961 developed by Warren DeLano. 1962 1963 This file is part of MayaChemTools. 1964 1965 MayaChemTools is free software; you can redistribute it and/or modify it under 1966 the terms of the GNU Lesser General Public License as published by the Free 1967 Software Foundation; either version 3 of the License, or (at your option) any 1968 later version. 1969 1970 """ 1971 1972 if __name__ == "__main__": 1973 main()