        1 #!/bin/env python
        2 #
        3 # File: PyMOLVisualizeCryoEMDensity.py
        4 # Author: Manish Sud <msud@san.rr.com>
        5 #
        6 # Copyright (C) 2018 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; %s) Starting...\n" % (ScriptName, pymol.cmd.get_version()[1], 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 group...
      391     SpecifiedChainsAndLigandsInfo = OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"][FileIndex]
      392     EnableChainAloneGroup = SpecifiedChainsAndLigandsInfo["EnableChainAloneGroup"][ChainID]
      393     GenerateAndWritePMLForGroup(OutFH, PyMOLObjectNames["Chains"][ChainID]["ChainAloneGroup"], PyMOLObjectNames["Chains"][ChainID]["ChainAloneGroupMembers"], EnableChainAloneGroup, "close")
      394
      395 def WriteChainLigandView(OutFH, FileIndex, PyMOLObjectNames, ChainID, LigandID):
      396     """Write out PML for viewing ligand in a chain."""
      397
      398     for GroupID in ["Ligand", "Pocket", "PocketSolvent", "PocketInorganic"]:
      399         ComplexName = PyMOLObjectNames["Chains"][ChainID]["ChainComplex"]
      400         LigandName = PyMOLObjectNames["Ligands"][ChainID][LigandID]["Ligand"]
      401
      402         # Setup main object...
      403         GroupTypeObjectID = "%s" % (GroupID)
      404         GroupTypeObjectName = PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupTypeObjectID]
      405
      406         if re.match("^Ligand$", GroupID, re.I):
      407             OutFH.write("""\n""\n"Setting up views for ligand %s in chain %s..."\n""\n""" % (LigandID, ChainID))
      408             PML = PyMOLUtil.SetupPMLForLigandView(GroupTypeObjectName, ComplexName, LigandID, True)
      409             OutFH.write("%s\n" % PML)
      410         elif re.match("^Pocket$", GroupID, re.I):
      411             OutFH.write("""\n""\n"Setting up views for pocket around ligand %s in chain %s..."\n""\n""" % (LigandID, ChainID))
      412             PML = PyMOLUtil.SetupPMLForLigandPocketView(GroupTypeObjectName, ComplexName, LigandName, OptionsInfo["PocketDistanceCutoff"], True)
      413             OutFH.write("%s\n" % PML)
      414             OutFH.write("""cmd.set("label_color", "%s", "%s")\n""" % (OptionsInfo["PocketLabelColor"], GroupTypeObjectName))
      415         elif re.match("^PocketSolvent$", GroupID, re.I):
      416             OutFH.write("""\n""\n"Setting up views for solvent in pockect around ligand %s in chain %s..."\n""\n""" % (LigandID, ChainID))
      417             PML = PyMOLUtil.SetupPMLForLigandPocketSolventView(GroupTypeObjectName, ComplexName, LigandName, OptionsInfo["PocketDistanceCutoff"], Enable = True)
      418             OutFH.write("%s\n" % PML)
      419         elif re.match("^PocketInorganic$", GroupID, re.I):
      420             OutFH.write("""\n""\n"Setting up views for inorganic in pockect around ligand %s in chain %s..."\n""\n""" % (LigandID, ChainID))
      421             PML = PyMOLUtil.SetupPMLForLigandPocketInorganicView(GroupTypeObjectName, ComplexName, LigandName, OptionsInfo["PocketDistanceCutoff"], Enable = True)
      422             OutFH.write("%s\n" % PML)
      423
      424         # Set up cryoEM mesh and group...
      425         CryoEMMeshGroupID = "%sCryoEMMeshGroup" % (GroupID)
      426         CryoEMMeshGroupMembersID = "%sCryoEMMeshGroupMembers" % (GroupID)
      427         CryoEMVolumeID = "%sCryoEMVolume" % (GroupID)
      428         CryoEMMeshID = "%sCryoEMMesh" % (GroupID)
      429         CryoEMSurfaceID = "%sCryoEMSurface" % (GroupID)
      430
      431         CryoEMMapName = PyMOLObjectNames["ComplexCryoEMMap"]
      432         CryoEMVolumeName = PyMOLObjectNames["Ligands"][ChainID][LigandID][CryoEMVolumeID]
      433         CryoEMMeshName = PyMOLObjectNames["Ligands"][ChainID][LigandID][CryoEMMeshID]
      434         CryoEMSurfaceName = PyMOLObjectNames["Ligands"][ChainID][LigandID][CryoEMSurfaceID]
      435         CryoEMMeshGroupName = PyMOLObjectNames["Ligands"][ChainID][LigandID][CryoEMMeshGroupID]
      436         CryoEMMeshGroupMembers = PyMOLObjectNames["Ligands"][ChainID][LigandID][CryoEMMeshGroupMembersID]
      437
      438         PML = SetupPMLForCryoEMDensityVolume(CryoEMMapName, CryoEMVolumeName, OptionsInfo["VolumeColorRampName"], Enable = False, Selection = GroupTypeObjectName)
      439         OutFH.write("\n%s\n" % PML)
      440
      441         ContourLevel = OptionsInfo["MeshLevels"][FileIndex]
      442         PML = SetupPMLForCryoEMDensityMesh(CryoEMMapName, CryoEMMeshName, ContourLevel, OptionsInfo["MeshColor"], Enable = True, Selection = GroupTypeObjectName)
      443         OutFH.write("\n%s\n" % PML)
      444
      445         PML = SetupPMLForCryoEMDensitySurface(CryoEMMapName, CryoEMSurfaceName, ContourLevel, OptionsInfo["MeshColor"], Enable = False, Selection = GroupTypeObjectName)
      446         OutFH.write("\n%s\n" % PML)
      447
      448         GenerateAndWritePMLForGroup(OutFH, CryoEMMeshGroupName, CryoEMMeshGroupMembers, True, "close")
      449
      450         # Set up polar contacts...
      451         if re.match("^(Pocket|PocketSolvent|PocketInorganic)$", GroupID, re.I):
      452             PolarContactsID = "%sPolarContacts" % (GroupID)
      453             PolarContactsName = PyMOLObjectNames["Ligands"][ChainID][LigandID][PolarContactsID]
      454
      455             PolarContactsColor = OptionsInfo["PocketContactsLigandColor"]
      456             if re.match("^PocketSolvent$", GroupID, re.I):
      457                 PolarContactsColor = OptionsInfo["PocketContactsSolventColor"]
      458             elif re.match("^PocketInorganic$", GroupID, re.I):
      459                 PolarContactsColor = OptionsInfo["PocketContactsInorganicColor"]
      460
      461             PML = PyMOLUtil.SetupPMLForPolarContactsView(PolarContactsName, LigandName, GroupTypeObjectName, Enable = False, Color = PolarContactsColor)
      462             OutFH.write("\n%s\n" % PML)
      463
      464             OutFH.write("""cmd.set("label_color", "%s", "%s")\n""" % (PolarContactsColor, PolarContactsName))
      465
      466         # Set up hydrophobic surface...
      467         if re.match("^Pocket$", GroupID, re.I) and OptionsInfo["PocketSurface"]:
      468             HydrophobicSurfaceID = "%sHydrophobicSurface" % (GroupID)
      469             HydrophobicSurfaceName = PyMOLObjectNames["Ligands"][ChainID][LigandID][HydrophobicSurfaceID]
      470             PML = PyMOLUtil.SetupPMLForHydrophobicSurfaceView(HydrophobicSurfaceName, GroupTypeObjectName, ColorPalette = "RedToWhite", Enable = False)
      471             OutFH.write("\n%s\n" % PML)
      472
      473             OutFH.write("""cmd.set("label_color", "%s", "%s")\n""" % (OptionsInfo["PocketLabelColor"], HydrophobicSurfaceName))
      474
      475         # Setup group....
      476         GroupNameID = "%sGroup" % (GroupID)
      477         GroupMembersID = "%sGroupMembers" % (GroupID)
      478         GroupName = PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupNameID]
      479         GroupMembers = PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupMembersID]
      480
      481         Action = "close"
      482         Enable = False
      483         if  re.match("^(Ligand|Pocket)$", GroupID, re.I):
      484             Action = "open"
      485             Enable = True
      486         GenerateAndWritePMLForGroup(OutFH, GroupName, GroupMembers, Enable, Action)
      487
      488 def GenerateAndWritePMLForGroup(OutFH, GroupName, GroupMembers, Enable = False, Action = "close"):
      489     """Generate and write PML for group. """
      490
      491     PML = PyMOLUtil.SetupPMLForGroup(GroupName, GroupMembers, Enable, Action)
      492     OutFH.write("""\n""\n"Setting up group %s..."\n""\n""" % GroupName)
      493     OutFH.write("%s\n" % PML)
      494
      495 def SetupPMLForCryoEMDensityMap(MapFileName, MapName, AlignMapToObjectName = None, Enable = True):
      496     """Setup PML for loading and viewing cryo-EM density map. """
      497
      498     PMLCmds = []
      499     PMLCmds.append("""cmd.load("%s", "%s")""" % (MapFileName, MapName))
      500     if AlignMapToObjectName is not None:
      501         PMLCmds.append("""cmd.matrix_copy("%s", "%s")""" % (AlignMapToObjectName, MapName))
      502
      503     PMLCmds.append(PyMOLUtil.SetupPMLForEnableDisable(MapName, Enable))
      504
      505     PML = "\n".join(PMLCmds)
      506
      507     return PML
      508
      509 def SetupPMLForCryoEMDensityMesh(MapName, MeshName, SigmaLevel, Color, Enable = True, Selection = None):
      510     """Setup PML for cryo-EM density mesh. """
      511
      512     Carve = OptionsInfo["MeshCarveRadius"]
      513
      514     PMLCmds = []
      515     if Selection is None:
      516         PMLCmds.append("""cmd.isomesh("%s", "%s", %.1f)""" % (MeshName, MapName, SigmaLevel))
      517     else:
      518         PMLCmds.append("""cmd.isomesh("%s", "%s", %.1f, "(%s)", carve = %.1f)""" % (MeshName, MapName, SigmaLevel, Selection, Carve))
      519     PMLCmds.append("""util.color_deep("%s", "%s")""" % (Color, MeshName))
      520     PMLCmds.append(PyMOLUtil.SetupPMLForEnableDisable(MeshName, Enable))
      521
      522     PML = "\n".join(PMLCmds)
      523
      524     return PML
      525
      526 def SetupPMLForCryoEMDensityVolume(MapName, VolumeName, VolumeColorRamp, Enable = True, Selection = None):
      527     """Setup PML for cryo-EM density volume. """
      528
      529     Carve = OptionsInfo["VolumeCarveRadius"]
      530
      531     PMLCmds = []
      532     if Selection is None:
      533         PMLCmds.append("""cmd.volume("%s", "%s", "%s")""" % (VolumeName, MapName, VolumeColorRamp))
      534     else:
      535         PMLCmds.append("""cmd.volume("%s", "%s", "%s", "(%s)", carve = %.1f)""" % (VolumeName, MapName, VolumeColorRamp, Selection, Carve))
      536     PMLCmds.append(PyMOLUtil.SetupPMLForEnableDisable(VolumeName, Enable))
      537
      538     PML = "\n".join(PMLCmds)
      539
      540     return PML
      541
      542 def SetupPMLForCryoEMDensitySurface(MapName, SurfaceName, SigmaLevel, Color, Enable = True, Selection = None):
      543     """Setup PML for cryo-EM density surface. """
      544
      545     Carve = OptionsInfo["MeshCarveRadius"]
      546
      547     PMLCmds = []
      548     if Selection is None:
      549         PMLCmds.append("""cmd.isosurface("%s", "%s", %.1f)""" % (SurfaceName, MapName, SigmaLevel))
      550     else:
      551         PMLCmds.append("""cmd.isosurface("%s", "%s", %.1f, "(%s)", carve = %.1f)""" % (SurfaceName, MapName, SigmaLevel, Selection, Carve))
      552     PMLCmds.append("""util.color_deep("%s", "%s")""" % (Color, SurfaceName))
      553     PMLCmds.append(PyMOLUtil.SetupPMLForEnableDisable(SurfaceName, Enable))
      554
      555     PML = "\n".join(PMLCmds)
      556
      557     return PML
      558
      559 def GeneratePyMOLSessionFile():
      560     """Generate PME file from PML file. """
      561
      562     PSEOutfile = OptionsInfo["PSEOutfile"]
      563     PMLOutfile = OptionsInfo["PMLOutfile"]
      564
      565     MiscUtil.PrintInfo("\nGenerating file %s..." % PSEOutfile)
      566
      567     PyMOLUtil.ConvertPMLFileToPSEFile(PMLOutfile, PSEOutfile)
      568
      569     if not os.path.exists(PSEOutfile):
      570         MiscUtil.PrintWarning("Failed to generate PSE file, %s..." % (PSEOutfile))
      571
      572     if not OptionsInfo["PMLOut"]:
      573         MiscUtil.PrintInfo("Deleting file %s..." % PMLOutfile)
      574         os.remove(PMLOutfile)
      575
      576 def DeleteEmptyPyMOLObjects(OutFH, FileIndex, PyMOLObjectNames):
      577     """Delete empty PyMOL objects. """
      578
      579     if OptionsInfo["AllowEmptyObjects"]:
      580         return
      581
      582     SpecifiedChainsAndLigandsInfo = OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"][FileIndex]
      583     for ChainID in SpecifiedChainsAndLigandsInfo["ChainIDs"]:
      584         OutFH.write("""\n""\n"Checking and deleting empty objects for chain %s..."\n""\n""" % (ChainID))
      585
      586         # Delete any chain level objects...
      587         WritePMLToCheckAndDeleteEmptyObjects(OutFH, PyMOLObjectNames["Chains"][ChainID]["Solvent"])
      588         WritePMLToCheckAndDeleteEmptyObjects(OutFH, PyMOLObjectNames["Chains"][ChainID]["Inorganic"])
      589
      590         for LigandID in SpecifiedChainsAndLigandsInfo["LigandIDs"][ChainID]:
      591             # Delete ligand level objects...
      592             for GroupID in ["Pocket", "PocketSolvent", "PocketInorganic"]:
      593                 GroupNameID = "%sGroup" % (GroupID)
      594                 GroupName = PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupNameID]
      595
      596                 GroupTypeObjectID = "%s" % (GroupID)
      597                 GroupTypeObjectName = PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupTypeObjectID]
      598
      599                 WritePMLToCheckAndDeleteEmptyObjects(OutFH, GroupTypeObjectName, GroupName)
      600
      601 def WritePMLToCheckAndDeleteEmptyObjects(OutFH, ObjectName, ParentObjectName = None):
      602     """Write PML to check and delete empty PyMOL objects. """
      603
      604     if ParentObjectName is None:
      605         PML = """CheckAndDeleteEmptyObjects("%s")""" % (ObjectName)
      606     else:
      607         PML = """CheckAndDeleteEmptyObjects("%s", "%s")""" % (ObjectName, ParentObjectName)
      608
      609     OutFH.write("%s\n" % PML)
      610
      611 def SetupPyMOLObjectNames(FileIndex):
      612     """Setup hierarchy of PyMOL groups and objects for ligand centric views of
      613     cryo-EM density for chains and ligands present in input file.
      614     """
      615
      616     PyMOLObjectNames = {}
      617     PyMOLObjectNames["Chains"] = {}
      618     PyMOLObjectNames["Ligands"] = {}
      619
      620     # Setup groups and objects for complex...
      621     SetupPyMOLObjectNamesForComplex(FileIndex, PyMOLObjectNames)
      622
      623     # Setup groups and objects for chain...
      624     SpecifiedChainsAndLigandsInfo = OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"][FileIndex]
      625     for ChainID in SpecifiedChainsAndLigandsInfo["ChainIDs"]:
      626         SetupPyMOLObjectNamesForChain(FileIndex, PyMOLObjectNames, ChainID)
      627
      628         # Setup groups and objects for ligand...
      629         for LigandID in SpecifiedChainsAndLigandsInfo["LigandIDs"][ChainID]:
      630             SetupPyMOLObjectNamesForLigand(FileIndex, PyMOLObjectNames, ChainID, LigandID)
      631
      632     return PyMOLObjectNames
      633
      634 def SetupPyMOLObjectNamesForComplex(FileIndex, PyMOLObjectNames):
      635     """Stetup groups and objects for complex. """
      636
      637     PDBFileRoot = OptionsInfo["InfilesInfo"]["InfilesRoots"][FileIndex]
      638
      639     PDBGroupName = "%s" % PDBFileRoot
      640     PyMOLObjectNames["PDBGroup"] = PDBGroupName
      641     PyMOLObjectNames["PDBGroupMembers"] = []
      642
      643     ComplexGroupName = "%s.Complex" % PyMOLObjectNames["PDBGroup"]
      644     PyMOLObjectNames["ComplexGroup"] = ComplexGroupName
      645     PyMOLObjectNames["PDBGroupMembers"].append(ComplexGroupName)
      646
      647     PyMOLObjectNames["Complex"] = "%s.Complex" % ComplexGroupName
      648
      649     CryoEMMeshGroupName = "%s.CryoEM" % (ComplexGroupName)
      650     CryoEMMapName = "%s.Map" % (CryoEMMeshGroupName)
      651     CryoEMVolumeName = "%s.Volume" % (CryoEMMeshGroupName)
      652     CryoEMMeshName = "%s.Mesh" % (CryoEMMeshGroupName)
      653     CryoEMSurfaceName = "%s.Surface" % (CryoEMMeshGroupName)
      654
      655     PyMOLObjectNames["ComplexCryoEMGroup"] = CryoEMMeshGroupName
      656     PyMOLObjectNames["ComplexCryoEMMap"] = CryoEMMapName
      657     PyMOLObjectNames["ComplexCryoEMVolume"] = CryoEMVolumeName
      658     PyMOLObjectNames["ComplexCryoEMMesh"] = CryoEMMeshName
      659     PyMOLObjectNames["ComplexCryoEMSurface"] = CryoEMSurfaceName
      660
      661     PyMOLObjectNames["ComplexCryoEMGroupMembers"] = []
      662     PyMOLObjectNames["ComplexCryoEMGroupMembers"].append(CryoEMMapName)
      663     if OptionsInfo["VolumeComplex"]:
      664         PyMOLObjectNames["ComplexCryoEMGroupMembers"].append(CryoEMVolumeName)
      665     if OptionsInfo["MeshComplex"]:
      666         PyMOLObjectNames["ComplexCryoEMGroupMembers"].append(CryoEMMeshName)
      667     if OptionsInfo["SurfaceComplex"]:
      668         PyMOLObjectNames["ComplexCryoEMGroupMembers"].append(CryoEMSurfaceName)
      669
      670     PyMOLObjectNames["ComplexGroupMembers"] = []
      671     PyMOLObjectNames["ComplexGroupMembers"].append(PyMOLObjectNames["Complex"])
      672     PyMOLObjectNames["ComplexGroupMembers"].append(PyMOLObjectNames["ComplexCryoEMGroup"])
      673
      674 def SetupPyMOLObjectNamesForChain(FileIndex, PyMOLObjectNames, ChainID):
      675     """Setup groups and objects for chain."""
      676
      677     PDBGroupName = PyMOLObjectNames["PDBGroup"]
      678
      679     SpecifiedChainsAndLigandsInfo = OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"][FileIndex]
      680     MeshChainComplex = SpecifiedChainsAndLigandsInfo["MeshChainComplex"][ChainID]
      681     VolumeChainComplex = SpecifiedChainsAndLigandsInfo["VolumeChainComplex"][ChainID]
      682     SurfaceChainComplex = SpecifiedChainsAndLigandsInfo["SurfaceChainComplex"][ChainID]
      683
      684     PyMOLObjectNames["Chains"][ChainID] = {}
      685     PyMOLObjectNames["Ligands"][ChainID] = {}
      686
      687     # Set up chain group and chain objects...
      688     ChainGroupName = "%s.Chain%s" % (PDBGroupName, ChainID)
      689     PyMOLObjectNames["Chains"][ChainID]["ChainGroup"] = ChainGroupName
      690     PyMOLObjectNames["PDBGroupMembers"].append(ChainGroupName)
      691     PyMOLObjectNames["Chains"][ChainID]["ChainGroupMembers"] = []
      692
      693     # Setup chain complex group and objects...
      694     ChainComplexGroupName = "%s.Complex" % (ChainGroupName)
      695     PyMOLObjectNames["Chains"][ChainID]["ChainComplexGroup"] = ChainComplexGroupName
      696     PyMOLObjectNames["Chains"][ChainID]["ChainGroupMembers"].append(ChainComplexGroupName)
      697
      698     PyMOLObjectNames["Chains"][ChainID]["ChainComplex"] = "%s.Complex" % (ChainComplexGroupName)
      699
      700     CryoEMMeshGroupName = "%s.CryoEM" % (ChainComplexGroupName)
      701     CryoEMVolumeName = "%s.Volume" % (CryoEMMeshGroupName)
      702     CryoEMMeshName = "%s.Mesh" % (CryoEMMeshGroupName)
      703     CryoEMSurfaceName = "%s.Surface" % (CryoEMMeshGroupName)
      704
      705     PyMOLObjectNames["Chains"][ChainID]["ChainComplexCryoEMGroup"] = CryoEMMeshGroupName
      706     PyMOLObjectNames["Chains"][ChainID]["ChainComplexCryoEMVolume"] = CryoEMVolumeName
      707     PyMOLObjectNames["Chains"][ChainID]["ChainComplexCryoEMMesh"] = CryoEMMeshName
      708     PyMOLObjectNames["Chains"][ChainID]["ChainComplexCryoEMSurface"] = CryoEMSurfaceName
      709
      710     PyMOLObjectNames["Chains"][ChainID]["ChainComplexCryoEMGroupMembers"] = []
      711     if VolumeChainComplex:
      712         PyMOLObjectNames["Chains"][ChainID]["ChainComplexCryoEMGroupMembers"].append(CryoEMVolumeName)
      713     if MeshChainComplex:
      714         PyMOLObjectNames["Chains"][ChainID]["ChainComplexCryoEMGroupMembers"].append(CryoEMMeshName)
      715     if SurfaceChainComplex:
      716         PyMOLObjectNames["Chains"][ChainID]["ChainComplexCryoEMGroupMembers"].append(CryoEMSurfaceName)
      717
      718     NameIDs = ["ChainComplex"]
      719     if MeshChainComplex or VolumeChainComplex or SurfaceChainComplex :
      720         NameIDs.append("ChainComplexCryoEMGroup")
      721
      722     PyMOLObjectNames["Chains"][ChainID]["ChainComplexGroupMembers"] = []
      723     for NameID in NameIDs:
      724         Name = PyMOLObjectNames["Chains"][ChainID][NameID]
      725         PyMOLObjectNames["Chains"][ChainID]["ChainComplexGroupMembers"].append(Name)
      726
      727     # Setup up a group for individual chains...
      728     ChainAloneGroupName = "%s.Chain" % (ChainGroupName)
      729     PyMOLObjectNames["Chains"][ChainID]["ChainAloneGroup"] = ChainAloneGroupName
      730     PyMOLObjectNames["Chains"][ChainID]["ChainGroupMembers"].append(ChainAloneGroupName)
      731
      732     PyMOLObjectNames["Chains"][ChainID]["ChainAloneGroupMembers"] = []
      733
      734     Name = "%s.Chain" % (ChainAloneGroupName)
      735     PyMOLObjectNames["Chains"][ChainID]["ChainAlone"] = Name
      736     PyMOLObjectNames["Chains"][ChainID]["ChainAloneGroupMembers"].append(Name)
      737
      738     if OptionsInfo["BFactorChainCartoonPutty"]:
      739         Name = "%s.BFactor" % (ChainAloneGroupName)
      740         PyMOLObjectNames["Chains"][ChainID]["ChainAloneBFactorPutty"] = Name
      741         PyMOLObjectNames["Chains"][ChainID]["ChainAloneGroupMembers"].append(Name)
      742
      743     # Setup solvent and inorganic objects for chain...
      744     for NameID in ["Solvent", "Inorganic"]:
      745         Name = "%s.%s" % (ChainGroupName, NameID)
      746         PyMOLObjectNames["Chains"][ChainID][NameID] = Name
      747         PyMOLObjectNames["Chains"][ChainID]["ChainGroupMembers"].append(Name)
      748
      749 def SetupPyMOLObjectNamesForLigand(FileIndex, PyMOLObjectNames, ChainID, LigandID):
      750     """Stetup groups and objects for ligand."""
      751
      752     PyMOLObjectNames["Ligands"][ChainID][LigandID] = {}
      753
      754     ChainGroupName = PyMOLObjectNames["Chains"][ChainID]["ChainGroup"]
      755
      756     # Setup a chain level ligand group...
      757     ChainLigandGroupName = "%s.Ligand%s" % (ChainGroupName, LigandID)
      758     PyMOLObjectNames["Ligands"][ChainID][LigandID]["ChainLigandGroup"] = ChainLigandGroupName
      759     PyMOLObjectNames["Chains"][ChainID]["ChainGroupMembers"].append(ChainLigandGroupName)
      760
      761     PyMOLObjectNames["Ligands"][ChainID][LigandID]["ChainLigandGroupMembers"] = []
      762
      763     # Set up groups and objects for a specific ligand group...
      764     for GroupType in ["Ligand", "Pocket", "Pocket_Solvent", "Pocket_Inorganic"]:
      765         GroupID = re.sub("_", "", GroupType)
      766         GroupName = "%s.%s" % (ChainLigandGroupName, GroupType)
      767
      768         GroupNameID = "%sGroup" % (GroupID)
      769         GroupMembersID = "%sGroupMembers" % (GroupID)
      770
      771         PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupNameID] = GroupName
      772         PyMOLObjectNames["Ligands"][ChainID][LigandID]["ChainLigandGroupMembers"].append(GroupName)
      773
      774         GroupTypeObjectName = "%s.%s" % (GroupName, GroupType)
      775         GroupTypeObjectID = "%s" % (GroupID)
      776         PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupTypeObjectID] = GroupTypeObjectName
      777
      778         CryoEMMeshGroupName = "%s.CryoEM" % (GroupName)
      779         CryoEMVolumeName = "%s.Volume" % (CryoEMMeshGroupName)
      780         CryoEMMeshName = "%s.Mesh" % (CryoEMMeshGroupName)
      781         CryoEMSurfaceName = "%s.Surface" % (CryoEMMeshGroupName)
      782
      783         CryoEMMeshGroupID = "%sCryoEMMeshGroup" % (GroupID)
      784         CryoEMMeshGroupMembersID = "%sCryoEMMeshGroupMembers" % (GroupID)
      785         CryoEMVolumeID = "%sCryoEMVolume" % (GroupID)
      786         CryoEMMeshID = "%sCryoEMMesh" % (GroupID)
      787         CryoEMSurfaceID = "%sCryoEMSurface" % (GroupID)
      788
      789         PyMOLObjectNames["Ligands"][ChainID][LigandID][CryoEMMeshGroupID] = CryoEMMeshGroupName
      790         PyMOLObjectNames["Ligands"][ChainID][LigandID][CryoEMVolumeID] = CryoEMVolumeName
      791         PyMOLObjectNames["Ligands"][ChainID][LigandID][CryoEMMeshID] = CryoEMMeshName
      792         PyMOLObjectNames["Ligands"][ChainID][LigandID][CryoEMSurfaceID] = CryoEMSurfaceName
      793         PyMOLObjectNames["Ligands"][ChainID][LigandID][CryoEMMeshGroupMembersID] = []
      794         PyMOLObjectNames["Ligands"][ChainID][LigandID][CryoEMMeshGroupMembersID].append(CryoEMVolumeName)
      795         PyMOLObjectNames["Ligands"][ChainID][LigandID][CryoEMMeshGroupMembersID].append(CryoEMMeshName)
      796         PyMOLObjectNames["Ligands"][ChainID][LigandID][CryoEMMeshGroupMembersID].append(CryoEMSurfaceName)
      797
      798         PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupMembersID] = []
      799         NameIDs = [GroupTypeObjectID, CryoEMMeshGroupID]
      800
      801         for NameID in NameIDs:
      802             Name = PyMOLObjectNames["Ligands"][ChainID][LigandID][NameID]
      803             PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupMembersID].append(Name)
      804
      805         if re.match("^Ligand$", GroupType, re.I):
      806             # No other object needed for Ligand group...
      807             continue
      808
      809         PolarContactsName = "%s.Polar_Contacts" % (GroupName)
      810         PolarContactsID = "%sPolarContacts" % (GroupID)
      811         PyMOLObjectNames["Ligands"][ChainID][LigandID][PolarContactsID] = PolarContactsName
      812         PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupMembersID].append(PolarContactsName)
      813
      814         if not re.match("^Pocket$", GroupType, re.I):
      815             # No other object needed for any other group besides Pocket...
      816             continue
      817
      818         if not OptionsInfo["PocketSurface"]:
      819             continue
      820
      821         HydrophobicSurfaceName = "%s.Surface" % (GroupName)
      822         HydrophobicSurfaceID = "%sHydrophobicSurface" % (GroupID)
      823         PyMOLObjectNames["Ligands"][ChainID][LigandID][HydrophobicSurfaceID] = HydrophobicSurfaceName
      824         PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupMembersID].append(HydrophobicSurfaceName)
      825
      826 def ProcessDensityMapFiles():
      827     """Process density map files."""
      828
      829     DensityMapFiles = OptionsInfo["DensityMapFiles"]
      830     if re.match("^auto$", DensityMapFiles, re.I):
      831         ProcessAutoDensityMapFiles()
      832     else:
      833         ProcessSpecifiedDensityMapFiles()
      834
      835 def ProcessSpecifiedDensityMapFiles():
      836     """Process specified density map files."""
      837
      838     OptionsInfo["DensityMapFilesNames"] = []
      839
      840     MiscUtil.PrintInfo("\nProcessing cryo-EM density file names...")
      841
      842     DensityMapFiles = re.sub(" ", "", OptionsInfo["DensityMapFiles"])
      843     if not DensityMapFiles:
      844         MiscUtil.PrintError("No valid value specified using \"--densityMapFiles\" option.")
      845
      846     DensityMapFilesWords = DensityMapFiles.split(",")
      847     DensityMapFilesWordsCount = len(DensityMapFilesWords)
      848
      849     InfilesNamesCount = len(OptionsInfo["InfilesNames"])
      850
      851     if DensityMapFilesWordsCount != InfilesNamesCount:
      852         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))
      853
      854     for Index in range(0, InfilesNamesCount):
      855         Infile = OptionsInfo["InfilesNames"][Index]
      856         DensityMapFile = DensityMapFilesWords[Index]
      857
      858         if not os.path.exists(DensityMapFile):
      859             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))
      860
      861         OptionsInfo["DensityMapFilesNames"].append(DensityMapFile)
      862
      863 def ProcessAutoDensityMapFiles():
      864     """Set up and process name of density map files."""
      865
      866     OptionsInfo["DensityMapFilesNames"] = []
      867     InfilesNamesCount = len(OptionsInfo["InfilesNames"])
      868
      869     MiscUtil.PrintInfo("\nSetting cryo-EM density file names...")
      870
      871     for Index in range(0, InfilesNamesCount):
      872         Infile = OptionsInfo["InfilesNames"][Index]
      873
      874         EMDBID = RetrieveEMDBID(Infile)
      875         if EMDBID is None:
      876             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)
      877
      878         DensityMapFile = None
      879         MapFileRoot = "emd_%s" % EMDBID
      880         MapFile1 = "%s.map.gz" % MapFileRoot
      881         MapFile2 = "%s.map" % MapFileRoot
      882         if os.path.exists(MapFile1):
      883             DensityMapFile = MapFile1
      884         elif os.path.exists(MapFile2):
      885             DensityMapFile = MapFile2
      886         else:
      887             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))
      888
      889         MiscUtil.PrintInfo("Setting density map file name as %s for input file %s..." % (DensityMapFile, Infile))
      890         OptionsInfo["DensityMapFilesNames"].append(DensityMapFile)
      891
      892 def RetrieveRecommededContourLevel(Infile):
      893     """Retrieve recommened contour level."""
      894
      895     if Infile in OptionsInfo["InfilesRecommededContourLevels"]:
      896         RecommendedContourLevel = OptionsInfo["InfilesRecommededContourLevels"][Infile]
      897         return RecommendedContourLevel
      898
      899     RecommendedContourLevel = None
      900     EMDBID = RetrieveEMDBID(Infile)
      901     if EMDBID is None:
      902         MiscUtil.PrintWarning("Failed to retrieve EMDB ID from input file %s to detect local header file already downloaded from EMDB server..." % Infile)
      903         OptionsInfo["InfilesRecommededContourLevels"][Infile] = RecommendedContourLevel
      904         return RecommendedContourLevel
      905
      906     MetadataHeaderFile = "emd-%s.xml" % (EMDBID)
      907     if not os.path.exists(MetadataHeaderFile):
      908         MiscUtil.PrintWarning("Failed to find a local header file, %s, for EMDB ID %s..." % (MetadataHeaderFile, EMDBID))
      909         OptionsInfo["InfilesRecommededContourLevels"][Infile] = RecommendedContourLevel
      910         return RecommendedContourLevel
      911
      912     MiscUtil.PrintInfo("\nRetrieving recommeded contour level from header file, %s, for input file, %s..." % (MetadataHeaderFile, Infile))
      913
      914     ContourLevel = None
      915     Source = None
      916     XMLTree = ElementTree.parse(MetadataHeaderFile)
      917     XMLRoot = XMLTree.getroot()
      918
      919     MapElement = XMLTree.find("map")
      920     if MapElement is not None:
      921         ContourLevelElement = MapElement.find("contourLevel")
      922         if ContourLevelElement is not None:
      923             ContourLevel = ContourLevelElement.text
      924             Source = ContourLevelElement.get("source")
      925
      926     if ContourLevel is not None:
      927         if Source is None:
      928             Source = "NA"
      929         MiscUtil.PrintInfo("Retrieved recommended (Source: %s) contour level %s..." % (Source, ContourLevel))
      930         RecommendedContourLevel = ContourLevel
      931
      932     OptionsInfo["InfilesRecommededContourLevels"][Infile] = RecommendedContourLevel
      933
      934     return RecommendedContourLevel
      935
      936 def RetrieveEMDBID(Infile):
      937     """Retrieve EMDB ID from input file. """
      938
      939     if Infile in OptionsInfo["InfilesEMDBIDs"]:
      940         EMDBID = OptionsInfo["InfilesEMDBIDs"][Infile]
      941         return EMDBID
      942
      943     EMDBID = None
      944     FileDir, FileName, FileExt = MiscUtil.ParseFileName(Infile)
      945
      946     if re.match("^pdb$", FileExt, re.I):
      947         EMDBID = RetriveEMDBIDFromPDBFile(Infile)
      948     elif re.match("^cif$", FileExt, re.I):
      949         EMDBID = RetriveEMDBIDFromCIFFile(Infile)
      950     else:
      951         EMDBID = None
      952
      953     OptionsInfo["InfilesEMDBIDs"][Infile] = EMDBID
      954
      955     return EMDBID
      956
      957 def RetriveEMDBIDFromPDBFile(Infile):
      958     """Retrieve EMDB ID from PDB file. """
      959
      960     EMDBID = None
      961     InfileFH = open(Infile, "r")
      962     if InfileFH is None:
      963         MiscUtil.PrintError("Couldn't open input file: %s.\n" % (Infile))
      964
      965     MiscUtil.PrintInfo("\nRetrieving EMDB ID from input file %s..." % Infile)
      966
      967     EMDBID = None
      968     for Line in InfileFH:
      969         Line = Line.rstrip()
      970         if re.match("^REMARK", Line, re.I):
      971             if re.search("DB: EMDB", Line, re.I):
      972                 for Word in Line.split(" "):
      973                     # Retrieve string with EMD-
      974                     if re.search("EMD-", Word, re.I):
      975                         Word = Word.strip()
      976                         EMDBID = re.sub("EMD-", "", Word)
      977                         break
      978                 break
      979     InfileFH.close()
      980
      981     return EMDBID
      982
      983 def RetriveEMDBIDFromCIFFile(Infile):
      984     """Retrieve EMDB ID from CIF file. """
      985
      986     InfileFH = open(Infile, "r")
      987     if InfileFH is None:
      988         MiscUtil.PrintError("Couldn't open input file: %s.\n" % (Infile))
      989
      990     MiscUtil.PrintInfo("\nRetrieving EMDB ID from input file %s..." % Infile)
      991
      992     EMDBID = None
      993     for Line in InfileFH:
      994         Line = Line.rstrip()
      995         if re.match("^EMDB  EMD", Line, re.I):
      996             for Word in Line.split(" "):
      997                 # Retrieve string with EMD-
      998                 if re.search("EMD-", Word, re.I):
      999                     Word = Word.strip()
     1000                     EMDBID = re.sub("EMD-", "", Word)
     1001                     break
     1002             break
     1003     InfileFH.close()
     1004
     1005     return EMDBID
     1006
     1007 def RetrieveInfilesInfo():
     1008     """Retrieve information for input files."""
     1009
     1010     InfilesInfo = {}
     1011
     1012     InfilesInfo["InfilesNames"] = []
     1013     InfilesInfo["InfilesRoots"] = []
     1014     InfilesInfo["ChainsAndLigandsInfo"] = []
     1015
     1016     for Infile in OptionsInfo["InfilesNames"]:
     1017         FileDir, FileName, FileExt = MiscUtil.ParseFileName(Infile)
     1018         InfileRoot = FileName
     1019
     1020         ChainsAndLigandInfo = PyMOLUtil.GetChainsAndLigandsInfo(Infile, InfileRoot)
     1021
     1022         InfilesInfo["InfilesNames"].append(Infile)
     1023         InfilesInfo["InfilesRoots"].append(InfileRoot)
     1024         InfilesInfo["ChainsAndLigandsInfo"].append(ChainsAndLigandInfo)
     1025
     1026     OptionsInfo["InfilesInfo"] = InfilesInfo
     1027
     1028 def RetrieveRefFileInfo():
     1029     """Retrieve information for ref file."""
     1030
     1031     RefFileInfo = {}
     1032     if not OptionsInfo["Align"]:
     1033         OptionsInfo["RefFileInfo"] = RefFileInfo
     1034         return
     1035
     1036     RefFile = OptionsInfo["RefFileName"]
     1037
     1038     FileDir, FileName, FileExt = MiscUtil.ParseFileName(RefFile)
     1039     RefFileRoot = FileName
     1040
     1041     if re.match("^FirstInputFile$", OptionsInfo["AlignRefFile"], re.I):
     1042         ChainsAndLigandInfo = OptionsInfo["InfilesInfo"]["ChainsAndLigandsInfo"][0]
     1043     else:
     1044         MiscUtil.PrintInfo("\nRetrieving chain and ligand information for alignment reference file %s..." % RefFile)
     1045         ChainsAndLigandInfo = PyMOLUtil.GetChainsAndLigandsInfo(RefFile, RefFileRoot)
     1046
     1047     RefFileInfo["RefFileName"] = RefFile
     1048     RefFileInfo["RefFileRoot"] = RefFileRoot
     1049     RefFileInfo["PyMOLObjectName"] = "AlignRef_%s" % RefFileRoot
     1050     RefFileInfo["ChainsAndLigandsInfo"] = ChainsAndLigandInfo
     1051
     1052     OptionsInfo["RefFileInfo"] = RefFileInfo
     1053
     1054 def ProcessChainAndLigandIDs():
     1055     """Process specified chain and ligand IDs for infiles."""
     1056
     1057     OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"] = []
     1058
     1059     for FileIndex in range(0, len(OptionsInfo["InfilesInfo"]["InfilesNames"])):
     1060         MiscUtil.PrintInfo("\nProcessing specified chain and ligand IDs for input file %s..." % OptionsInfo["InfilesInfo"]["InfilesNames"][FileIndex])
     1061
     1062         ChainsAndLigandsInfo = OptionsInfo["InfilesInfo"]["ChainsAndLigandsInfo"][FileIndex]
     1063         SpecifiedChainsAndLigandsInfo = PyMOLUtil.ProcessChainsAndLigandsOptionsInfo(ChainsAndLigandsInfo, "-c, --chainIDs", OptionsInfo["ChainIDs"], "-l, --ligandIDs", OptionsInfo["LigandIDs"])
     1064         ProcessChainMeshesVolumesAndSurfacesOptions(SpecifiedChainsAndLigandsInfo)
     1065         OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"].append(SpecifiedChainsAndLigandsInfo)
     1066
     1067         CheckPresenceOfValidLigandIDs(ChainsAndLigandsInfo, SpecifiedChainsAndLigandsInfo)
     1068
     1069 def CheckPresenceOfValidLigandIDs(ChainsAndLigandsInfo, SpecifiedChainsAndLigandsInfo):
     1070     """Check presence of valid ligand IDs."""
     1071
     1072     MiscUtil.PrintInfo("\nSpecified chain IDs: %s" % (", ".join(SpecifiedChainsAndLigandsInfo["ChainIDs"])))
     1073
     1074     for ChainID in SpecifiedChainsAndLigandsInfo["ChainIDs"]:
     1075         if len (SpecifiedChainsAndLigandsInfo["LigandIDs"][ChainID]):
     1076             MiscUtil.PrintInfo("Chain ID: %s; Specified LigandIDs: %s" % (ChainID, ", ".join(SpecifiedChainsAndLigandsInfo["LigandIDs"][ChainID])))
     1077         else:
     1078             MiscUtil.PrintInfo("Chain IDs: %s; Specified LigandIDs: None" % (ChainID))
     1079             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))
     1080
     1081 def RetrieveFirstChainID(FileIndex):
     1082     """Get first chain ID."""
     1083
     1084     ChainsAndLigandsInfo = OptionsInfo["InfilesInfo"]["ChainsAndLigandsInfo"][FileIndex]
     1085
     1086     FirstChainID = None
     1087     if len(ChainsAndLigandsInfo["ChainIDs"]):
     1088         FirstChainID = ChainsAndLigandsInfo["ChainIDs"][0]
     1089
     1090     return FirstChainID
     1091
     1092 def ProcessChainMeshesVolumesAndSurfacesOptions(SpecifiedChainsAndLigandsInfo):
     1093     """Process options to create meshes and surfaces for chains."""
     1094
     1095     SpecifiedChainsAndLigandsInfo["VolumeChainComplex"] = {}
     1096     SpecifiedChainsAndLigandsInfo["MeshChainComplex"] = {}
     1097     SpecifiedChainsAndLigandsInfo["SurfaceChainComplex"] = {}
     1098
     1099     SpecifiedChainsAndLigandsInfo["EnableVolumeChainComplex"] = {}
     1100     SpecifiedChainsAndLigandsInfo["EnableMeshChainComplex"] = {}
     1101     SpecifiedChainsAndLigandsInfo["EnableSurfaceChainComplex"] = {}
     1102
     1103     SpecifiedChainsAndLigandsInfo["EnableChainComplexGroup"] = {}
     1104     SpecifiedChainsAndLigandsInfo["EnableChainAloneGroup"] = {}
     1105
     1106     for ChainID in SpecifiedChainsAndLigandsInfo["ChainIDs"]:
     1107         LigandsPresent = True if len(SpecifiedChainsAndLigandsInfo["LigandIDs"][ChainID]) else False
     1108
     1109         # Create and enable mesh  or volume in auto mode...
     1110         if re.match("^auto$", OptionsInfo["MeshChainComplex"], re.I):
     1111             MeshChainComplex = False if LigandsPresent else True
     1112             EnableMeshChainComplex = False if LigandsPresent else True
     1113         else:
     1114             MeshChainComplex = True if re.match("^Yes$", OptionsInfo["MeshChainComplex"], re.I) else False
     1115             EnableMeshChainComplex = True if re.match("^Yes$", OptionsInfo["MeshChainComplex"], re.I) else False
     1116
     1117         if re.match("^auto$", OptionsInfo["VolumeChainComplex"], re.I):
     1118             VolumeChainComplex = False if LigandsPresent else True
     1119             EnableVolumeChainComplex = False if LigandsPresent else True
     1120         else:
     1121             VolumeChainComplex = True if re.match("^Yes$", OptionsInfo["VolumeChainComplex"], re.I) else False
     1122             EnableVolumeChainComplex = True if re.match("^Yes$", OptionsInfo["VolumeChainComplex"], re.I) else False
     1123
     1124         if MeshChainComplex and EnableMeshChainComplex:
     1125             EnableVolumeChainComplex = False
     1126
     1127         # Create and enable surface in auto mode based on the status of mesh and volume...
     1128         if re.match("^auto$", OptionsInfo["SurfaceChainComplex"], re.I):
     1129             SurfaceChainComplex = False if LigandsPresent else True
     1130             EnableSurfaceChainComplex = False if LigandsPresent else True
     1131
     1132             if MeshChainComplex or VolumeChainComplex:
     1133                 SurfaceChainComplex = False
     1134                 EnableSurfaceChainComplex = False
     1135         else:
     1136             SurfaceChainComplex = True if re.match("^Yes$", OptionsInfo["SurfaceChainComplex"], re.I) else False
     1137             EnableSurfaceChainComplex = True if re.match("^Yes$", OptionsInfo["SurfaceChainComplex"], re.I) else False
     1138
     1139         if (MeshChainComplex and EnableMeshChainComplex) or (VolumeChainComplex or EnableVolumeChainComplex):
     1140             EnableSurfaceChainComplex = False
     1141
     1142         if LigandsPresent:
     1143             EnableChainComplexGroup = False
     1144             EnableChainAloneGroup = True
     1145         else:
     1146             EnableChainComplexGroup = True
     1147             EnableChainAloneGroup = False
     1148
     1149         SpecifiedChainsAndLigandsInfo["VolumeChainComplex"][ChainID] = VolumeChainComplex
     1150         SpecifiedChainsAndLigandsInfo["MeshChainComplex"][ChainID] = MeshChainComplex
     1151         SpecifiedChainsAndLigandsInfo["SurfaceChainComplex"][ChainID] = SurfaceChainComplex
     1152
     1153         SpecifiedChainsAndLigandsInfo["EnableVolumeChainComplex"][ChainID] = EnableVolumeChainComplex
     1154         SpecifiedChainsAndLigandsInfo["EnableMeshChainComplex"][ChainID] = EnableMeshChainComplex
     1155         SpecifiedChainsAndLigandsInfo["EnableSurfaceChainComplex"][ChainID] = EnableSurfaceChainComplex
     1156
     1157         SpecifiedChainsAndLigandsInfo["EnableChainComplexGroup"][ChainID] = EnableChainComplexGroup
     1158         SpecifiedChainsAndLigandsInfo["EnableChainAloneGroup"][ChainID] = EnableChainAloneGroup
     1159
     1160 def ProcessMeshLevel():
     1161     """Process mesh level."""
     1162
     1163     MeshLevel = OptionsInfo["MeshLevel"]
     1164
     1165     if re.match("^auto$", MeshLevel, re.I):
     1166         ProcessAutoMeshLevel()
     1167     else:
     1168         ProcessSpecifiedMeshLevel()
     1169
     1170 def ProcessAutoMeshLevel():
     1171     """Process auto mesh level."""
     1172
     1173     OptionsInfo["MeshLevels"] = []
     1174     InfilesNamesCount = len(OptionsInfo["InfilesNames"])
     1175
     1176     MiscUtil.PrintInfo("\nSetting mesh levels...")
     1177
     1178     for Index in range(0, InfilesNamesCount):
     1179         Infile = OptionsInfo["InfilesNames"][Index]
     1180
     1181         RecommededContourLevel = RetrieveRecommededContourLevel(Infile)
     1182         if RecommededContourLevel is None:
     1183             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.")
     1184             MeshLevel = 1.0
     1185         else:
     1186             MeshLevel = float(RecommededContourLevel)
     1187         OptionsInfo["MeshLevels"].append(MeshLevel)
     1188
     1189 def ProcessSpecifiedMeshLevel():
     1190     """Process specified mesh level."""
     1191
     1192     MiscUtil.PrintInfo("\nProcessing mesh levels...")
     1193
     1194     OptionsInfo["MeshLevels"] = []
     1195     InfilesNamesCount = len(OptionsInfo["InfilesNames"])
     1196
     1197     MeshLevels = re.sub(" ", "", OptionsInfo["MeshLevel"])
     1198     if not MeshLevels:
     1199         MiscUtil.PrintError("No valid value specified using \"--meshLevel\" option.")
     1200
     1201     MeshLevelWords = MeshLevels.split(",")
     1202     MeshLevelWordsCount = len(MeshLevelWords)
     1203
     1204     if MeshLevelWordsCount != InfilesNamesCount:
     1205         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))
     1206
     1207     for Index in range(0, InfilesNamesCount):
     1208         Infile = OptionsInfo["InfilesNames"][Index]
     1209         MeshLevel = MeshLevelWords[Index]
     1210         if not MiscUtil.IsFloat(MeshLevel):
     1211             MiscUtil.PrintError("The mesh level, %s, specified using \"--meshLevel\" for input file, %s, must be a float." % (MeshLevel, Infile))
     1212
     1213         MeshLevel = float(MeshLevel)
     1214         OptionsInfo["MeshLevels"].append(MeshLevel)
     1215
     1216 def ProcessVolumeColorRamp():
     1217     """Process volume color ramp."""
     1218
     1219     MiscUtil.PrintInfo("\nProcessing volume color ramp...")
     1220
     1221     ColorRamp = Options["--volumeColorRamp"]
     1222     ColorRampName = None
     1223     CreateColorRamp = False
     1224     ColorRampContourLevel = None
     1225     if re.match("^auto$", ColorRamp, re.I):
     1226         FirstInfile = OptionsInfo["InfilesNames"][0]
     1227         RecommededContourLevel = RetrieveRecommededContourLevel(FirstInfile)
     1228         if RecommededContourLevel is None:
     1229             ColorRampName = "default"
     1230             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))
     1231         else:
     1232             ColorRampName = "CryoEMAuto"
     1233             CreateColorRamp = True
     1234             ColorRampContourLevel = float(RecommededContourLevel)
     1235             MiscUtil.PrintInfo("\nSetting up a  new volume color ramp, %s, at recommended contour level, %.2f, from input file, %s..." % (ColorRampName, ColorRampContourLevel, FirstInfile))
     1236     else:
     1237         ColorRampName = ColorRamp
     1238
     1239     OptionsInfo["VolumeColorRamp"] = ColorRamp
     1240     OptionsInfo["VolumeColorRampName"] = ColorRampName
     1241     OptionsInfo["VolumeColorRampCreate"] = CreateColorRamp
     1242     OptionsInfo["VolumeColorRampContourLevel"] = ColorRampContourLevel
     1243
     1244 def ProcessOptions():
     1245     """Process and validate command line arguments and options."""
     1246
     1247     MiscUtil.PrintInfo("Processing options...")
     1248
     1249     # Validate options...
     1250     ValidateOptions()
     1251
     1252     OptionsInfo["Align"] = True if re.match("^Yes$", Options["--align"], re.I) else False
     1253     OptionsInfo["AlignMethod"] = Options["--alignMethod"].lower()
     1254     OptionsInfo["AlignMode"] = Options["--alignMode"]
     1255
     1256     OptionsInfo["AllowEmptyObjects"] = True if re.match("^Yes$", Options["--allowEmptyObjects"], re.I) else False
     1257
     1258     OptionsInfo["BFactorChainCartoonPutty"] = True if re.match("^Yes$", Options["--BFactorChainCartoonPutty"], re.I) else False
     1259     OptionsInfo["BFactorColorPalette"] = Options["--BFactorColorPalette"]
     1260
     1261     OptionsInfo["Infiles"] = Options["--infiles"]
     1262     OptionsInfo["InfilesNames"] =  Options["--infileNames"]
     1263
     1264     OptionsInfo["InfilesEMDBIDs"] =  {}
     1265     OptionsInfo["InfilesRecommededContourLevels"] =  {}
     1266
     1267     OptionsInfo["AlignRefFile"] = Options["--alignRefFile"]
     1268     if re.match("^FirstInputFile$", Options["--alignRefFile"], re.I):
     1269         OptionsInfo["RefFileName"] = OptionsInfo["InfilesNames"][0]
     1270     else:
     1271         OptionsInfo["RefFileName"] = Options["--alignRefFile"]
     1272
     1273     OptionsInfo["DensityMapFiles"] = Options["--densityMapFiles"]
     1274     ProcessDensityMapFiles()
     1275
     1276     OptionsInfo["Overwrite"] = Options["--overwrite"]
     1277     OptionsInfo["PMLOut"] = True if re.match("^Yes$", Options["--PMLOut"], re.I) else False
     1278
     1279     OptionsInfo["Outfile"] = Options["--outfile"]
     1280     FileDir, FileName, FileExt = MiscUtil.ParseFileName(OptionsInfo["Outfile"])
     1281     OptionsInfo["PSEOut"] = False
     1282     if re.match("^pml$", FileExt, re.I):
     1283         OptionsInfo["PMLOutfile"] = OptionsInfo["Outfile"]
     1284         OptionsInfo["PMEOutfile"] = re.sub(".pml$", ".pme", OptionsInfo["Outfile"])
     1285     elif re.match("^pse$", FileExt, re.I):
     1286         OptionsInfo["PSEOut"] = True
     1287         OptionsInfo["PSEOutfile"] = OptionsInfo["Outfile"]
     1288         OptionsInfo["PMLOutfile"] = re.sub(".pse$", ".pml", OptionsInfo["Outfile"])
     1289         if os.path.exists(OptionsInfo["PMLOutfile"]) and (not OptionsInfo["Overwrite"]):
     1290             MiscUtil.PrintError("The intermediate output file to be generated, %s, already exist. Use option \"--ov\" or \"--overwrite\" and try again." % OptionsInfo["PMLOutfile"] )
     1291
     1292     OptionsInfo["LabelFontID"] = int(Options["--labelFontID"])
     1293
     1294     # Process mesh parameters...
     1295     OptionsInfo["MeshCarveRadius"] = float(Options["--meshCarveRadius"])
     1296     OptionsInfo["MeshComplex"] = True if re.match("^Yes$", Options["--meshComplex"], re.I) else False
     1297     OptionsInfo["MeshChainComplex"] = Options["--meshChainComplex"]
     1298
     1299     OptionsInfo["MeshWidth"] = float(Options["--meshWidth"])
     1300     OptionsInfo["MeshColor"] = Options["--meshColor"]
     1301
     1302     OptionsInfo["MeshLevel"] = Options["--meshLevel"]
     1303     ProcessMeshLevel()
     1304
     1305     OptionsInfo["SurfaceComplex"] = True if re.match("^Yes$", Options["--surfaceComplex"], re.I) else False
     1306     OptionsInfo["SurfaceChainComplex"] = Options["--surfaceChainComplex"]
     1307     OptionsInfo["SurfaceTransparency"] = float(Options["--surfaceTransparency"])
     1308
     1309     OptionsInfo["PocketContactsLigandColor"] = Options["--pocketContactsLigandColor"]
     1310     OptionsInfo["PocketContactsSolventColor"] = Options["--pocketContactsSolventColor"]
     1311     OptionsInfo["PocketContactsInorganicColor"] = Options["--pocketContactsInorganicColor"]
     1312
     1313     OptionsInfo["PocketDistanceCutoff"] = float(Options["--pocketDistanceCutoff"])
     1314     OptionsInfo["PocketLabelColor"] = Options["--pocketLabelColor"]
     1315     OptionsInfo["PocketSurface"] = True if re.match("^Yes$", Options["--pocketSurface"], re.I) else False
     1316
     1317     OptionsInfo["VolumeCarveRadius"] = float(Options["--volumeCarveRadius"])
     1318     OptionsInfo["VolumeComplex"] = True if re.match("^Yes$", Options["--volumeComplex"], re.I) else False
     1319     OptionsInfo["VolumeChainComplex"] = Options["--volumeChainComplex"]
     1320
     1321     ProcessVolumeColorRamp()
     1322
     1323     RetrieveInfilesInfo()
     1324     RetrieveRefFileInfo()
     1325
     1326     OptionsInfo["ChainIDs"] = Options["--chainIDs"]
     1327     OptionsInfo["LigandIDs"] = Options["--ligandIDs"]
     1328
     1329     ProcessChainAndLigandIDs()
     1330
     1331 def RetrieveOptions():
     1332     """Retrieve command line arguments and options"""
     1333
     1334     # Get options...
     1335     global Options
     1336     Options = docopt(_docoptUsage_)
     1337
     1338     # Set current working directory to the specified directory...
     1339     WorkingDir = Options["--workingdir"]
     1340     if WorkingDir:
     1341         os.chdir(WorkingDir)
     1342
     1343     # Handle examples option...
     1344     if "--examples" in Options and Options["--examples"]:
     1345         MiscUtil.PrintInfo(MiscUtil.GetExamplesTextFromDocOptText(_docoptUsage_))
     1346         sys.exit(0)
     1347
     1348 def ValidateOptions():
     1349     """Validate option values"""
     1350
     1351     MiscUtil.ValidateOptionTextValue("--align", Options["--align"], "yes no")
     1352     MiscUtil.ValidateOptionTextValue("--alignMethod", Options["--alignMethod"], "align cealign super")
     1353     MiscUtil.ValidateOptionTextValue("--alignMode", Options["--alignMode"], "FirstChain Complex")
     1354
     1355     MiscUtil.ValidateOptionTextValue("--allowEmptyObjects", Options["--allowEmptyObjects"], "yes no")
     1356
     1357     MiscUtil.ValidateOptionTextValue("--BFactorChainCartoonPutty", Options["--BFactorChainCartoonPutty"], "yes no")
     1358
     1359     # Expand infiles to handle presence of multiple input files...
     1360     InfileNames = MiscUtil.ExpandFileNames(Options["--infiles"], ",")
     1361     if not len(InfileNames):
     1362         MiscUtil.PrintError("No input files specified for \"-i, --infiles\" option")
     1363
     1364     # Validate file extensions...
     1365     for Infile in InfileNames:
     1366         MiscUtil.ValidateOptionFilePath("-i, --infiles", Infile)
     1367         MiscUtil.ValidateOptionFileExt("-i, --infiles", Infile, "pdb cif")
     1368         MiscUtil.ValidateOptionsDistinctFileNames("-i, --infiles", Infile, "-o, --outfile", Options["--outfile"])
     1369     Options["--infileNames"] = InfileNames
     1370
     1371     MiscUtil.ValidateOptionFileExt("-o, --outfile", Options["--outfile"], "pml pse")
     1372     MiscUtil.ValidateOptionsOutputFileOverwrite("-o, --outfile", Options["--outfile"], "--overwrite", Options["--overwrite"])
     1373
     1374     if re.match("^yes$", Options["--align"], re.I):
     1375         if not re.match("^FirstInputFile$", Options["--alignRefFile"], re.I):
     1376             AlignRefFile = Options["--alignRefFile"]
     1377             MiscUtil.ValidateOptionFilePath("--alignRefFile", AlignRefFile)
     1378             MiscUtil.ValidateOptionFileExt("--alignRefFile", AlignRefFile, "pdb cif")
     1379             MiscUtil.ValidateOptionsDistinctFileNames("--AlignRefFile", AlignRefFile, "-o, --outfile", Options["--outfile"])
     1380
     1381     MiscUtil.ValidateOptionTextValue("--PMLOut", Options["--PMLOut"], "yes no")
     1382     MiscUtil.ValidateOptionIntegerValue("--labelFontID", Options["--labelFontID"], {})
     1383
     1384     MiscUtil.ValidateOptionFloatValue("--meshCarveRadius", Options["--meshCarveRadius"], {">": 0.0})
     1385     MiscUtil.ValidateOptionTextValue("--meshComplex", Options["--meshComplex"], "yes no")
     1386     MiscUtil.ValidateOptionTextValue("--meshChainComplex", Options["--meshChainComplex"], "yes no auto")
     1387     MiscUtil.ValidateOptionFloatValue("--meshWidth", Options["--meshWidth"], {">": 0.0})
     1388
     1389     MiscUtil.ValidateOptionTextValue("--PMLOut", Options["--PMLOut"], "yes no")
     1390
     1391     MiscUtil.ValidateOptionFloatValue("--pocketDistanceCutoff", Options["--pocketDistanceCutoff"], {">": 0.0})
     1392     MiscUtil.ValidateOptionTextValue("--pocketSurface", Options["--pocketSurface"], "yes no")
     1393
     1394     MiscUtil.ValidateOptionTextValue("--surfaceComplex", Options["--surfaceComplex"], "yes no")
     1395     MiscUtil.ValidateOptionTextValue("--surfaceChainComplex", Options["--surfaceChainComplex"], "yes no auto")
     1396     MiscUtil.ValidateOptionFloatValue("--surfaceTransparency", Options["--surfaceTransparency"], {">=": 0.0, "<=": 1.0})
     1397
     1398     MiscUtil.ValidateOptionFloatValue("--volumeCarveRadius", Options["--volumeCarveRadius"], {">": 0.0})
     1399     MiscUtil.ValidateOptionTextValue("--volumeComplex", Options["--volumeComplex"], "yes no")
     1400     MiscUtil.ValidateOptionTextValue("--volumeChainComplex", Options["--volumeChainComplex"], "yes no auto")
     1401
     1402 # Setup a usage string for docopt...
     1403 _docoptUsage_ = """
     1404 PyMOLVisualizeCryoEMDensity.py - Visualize cryo-EM density
     1405
     1406 Usage:
     1407     PyMOLVisualizeCryoEMDensity.py  [--align <yes or no>] [--alignMethod <align, cealign, super>]
     1408                                    [--alignMode <FirstChain or Complex>] [--alignRefFile <filename>]
     1409                                    [--allowEmptyObjects <yes or no>] [--BFactorChainCartoonPutty <yes or no>]
     1410                                    [--BFactorColorPalette <text> ] [--chainIDs <First, All or ID1,ID2...>]
     1411                                    [--densityMapFiles <file1,file2,file3,...>]
     1412                                    [--ligandIDs <Largest, All or ID1,ID2...>] [--labelFontID <number>]
     1413                                    [--meshCarveRadius <number>] [--meshComplex <yes or no>]
     1414                                    [--meshChainComplex <yes, no, or auto>] [--meshColor <text>]
     1415                                    [--meshLevel <number>] [--meshWidth <number>] [--PMLOut <yes or no>]
     1416                                    [--pocketContactsLigandColor <text>] [--pocketContactsSolventColor <text>]
     1417                                    [--pocketContactsInorganicColor <text>] [--pocketDistanceCutoff <number>]
     1418                                    [--pocketLabelColor <text>] [--pocketSurface <yes or no>]
     1419                                    [--surfaceComplex <yes or no>] [--surfaceChainComplex <yes, no or auto>]
     1420                                    [--surfaceTransparency <number>] [--volumeCarveRadius <number>]
     1421                                    [--volumeComplex <yes or no>] [--volumeChainComplex <yes, no, or auto>]
     1422                                    [--volumeColorRamp <text>]   [--overwrite] [-w <dir>] -i <infile1,infile2,...> -o <outfile>
     1423     PyMOLVisualizeCryoEMDensity.py -h | --help | -e | --examples
     1424
     1425 Description:
     1426     Generate PyMOL visualization files for viewing electron microscopy (EM) or
     1427     cryo-EM density around chains, ligands, and ligand binding pockets in
     1428     macromolecules including proteins and nucleic acids.
     1429
     1430     The supported input file formats are: Macromolecule - PDB (.pdb) or CIF(.cif),
     1431     Cryo-EM Density - Collaborative Computational Project Number 4 (CCP4) ( .map)
     1432
     1433     The supported output file formats are: PyMOL script file (.pml), PyMOL session
     1434     file (.pse)
     1435
     1436     The cryo-EM density and header files along with PDB files may be downloaded
     1437     from appropriate servers using DownloadPDBFiles.pl script.
     1438
     1439     A variety of PyMOL groups and objects may be  created for visualization of
     1440     cryo-EM density present in map files. These groups and objects correspond to
     1441     maps, volumes, meshes, surfaces,chains, ligands, inorganics, ligand binding
     1442     pockets, polar interactions, and pocket hydrophobic surfaces. A complete
     1443     hierarchy of all possible PyMOL groups and objects is shown below:
     1444
     1445         <PDBFileRoot>
     1446             .Complex
     1447                 .Complex
     1448                 .CryoEM
     1449                     .Map
     1450                     .Volume
     1451                     .Mesh
     1452                     .Surface
     1453             .Chain<ID>
     1454                 .Complex
     1455                     .Complex
     1456                     .CryoEM
     1457                         .Volume
     1458                         .Mesh
     1459                         .Surface
     1460                 .Chain
     1461                     .Chain
     1462                     .BFactor
     1463                 .Solvent
     1464                 .Inorganic
     1465                 .Ligand<ID>
     1466                     .Ligand
     1467                         .Ligand
     1468                         .CryoEM
     1469                             .Volume
     1470                             .Mesh
     1471                             .Surface
     1472                     .Pocket
     1473                         .Pocket
     1474                         .CryoEM
     1475                             .Volume
     1476                             .Mesh
     1477                             .Surface
     1478                         .Polar_Contacts
     1479                         .Surface
     1480                     .Pocket_Solvent
     1481                         .Pocket_Solvent
     1482                         .CryoEM
     1483                             .Volume
     1484                             .Mesh
     1485                             .Surface
     1486                         .Polar_Contacts
     1487                     .Pocket_Inorganic
     1488                         .Pocket_Inorganic
     1489                         .CryoEM
     1490                             .Volume
     1491                             .Mesh
     1492                             .Surface
     1493                         .Polar_Contacts
     1494                 .Ligand<ID>
     1495                     .Ligand
     1496                         ... ... ...
     1497                     .Pocket
     1498                         ... ... ...
     1499                     .Pocket_Solvent
     1500                         ... ... ...
     1501                     .Pocket_Inorganic
     1502                         ... ... ...
     1503             .Chain<ID>
     1504                 ... ... ...
     1505                 .Ligand<ID>
     1506                     ... ... ...
     1507                 .Ligand<ID>
     1508                     ... ... ...
     1509             .Chain<ID>
     1510                 ... ... ...
     1511         <PDBFileRoot>
     1512             .Complex
     1513                 ... ... ...
     1514             .Chain<ID>
     1515                 ... ... ...
     1516                 .Ligand<ID>
     1517                     ... ... ...
     1518                 .Ligand<ID>
     1519                     ... ... ...
     1520             .Chain<ID>
     1521                 ... ... ...
     1522
     1523     The meshes, volumes, and surfaces  are not created for complete complex in input
     1524     files by default. A word to the wise: The creation of these mesh, volume, and surface
     1525     objects may slow down loading of PML file and generation of PSE file, based on the
     1526     size of input complex and map files. The generation of PSE file may also fail. In
     1527     addition, you may want to interactively manipulate the contour level for meshes,
     1528     volumes, and surfaces. The recommended value for contour level is automatically
     1529     retrieved from header files available from EM density server. The recommended
     1530     value may not always work.
     1531
     1532 Options:
     1533     -a, --align <yes or no>  [default: no]
     1534         Align input files to a reference file before visualization along with
     1535         available cryo-EM density map files.
     1536     --alignMethod <align, cealign, super>  [default: super]
     1537         Alignment methodology to use for aligning input files to a reference
     1538         file.
     1539     --alignMode <FirstChain or Complex>  [default: FirstChain]
     1540         Portion of input and reference files to use for spatial alignment of
     1541         input files against reference file.  Possible values: FirstChain or
     1542         Complex.
     1543
     1544         The FirstChain mode allows alignment of the first chain in each input
     1545         file to the first chain in the reference file along with moving the rest
     1546         of the complex to coordinate space of the reference file. The complete
     1547         complex in each input file is aligned to the complete complex in reference
     1548         file for the Complex mode.
     1549     --alignRefFile <filename>  [default: FirstInputFile]
     1550         Reference input file name. The default is to use the first input file
     1551         name specified using '-i, --infiles' option.
     1552     --allowEmptyObjects <yes or no>  [default: no]
     1553         Allow creation of empty PyMOL objects corresponding to solvent and
     1554         inorganic atom selections across chains, ligands, and ligand binding pockets
     1555         in input file(s).
     1556     -b, --BFactorChainCartoonPutty <yes or no>  [default: yes]
     1557         A cartoon putty around individual chains colored by B factors. The minimum
     1558         and maximum values for B factors are automatically detected. These values
     1559         indicate spread of cryo-EM density around atoms. The 'blue_white_red' color
     1560         palette is deployed for coloring the cartoon putty.
     1561     --BFactorColorPalette <text>  [default: blue_white_red]
     1562         Color palette for coloring cartoon putty around chains generated using B
     1563         factors. Any valid PyMOL color palette name is allowed. No validation is
     1564         performed. The complete list of valid color palette names is a available
     1565         at: pymolwiki.org/index.php/Spectrum. Examples: blue_white_red,
     1566         blue_white_magenta, blue_red, green_white_red, green_red.
     1567     -c, --chainIDs <First, All or ID1,ID2...>  [default: First]
     1568         List of chain IDs to use for visualizing cryo-EM density. Possible values:
     1569         First, All, or a comma delimited list of chain IDs. The default is to use the
     1570         chain ID for the first chain in each input file.
     1571     -d, --densityMapFiles <file1,file2,file3,...>  [default: auto]
     1572         CryoEM density map file names. The EMDB ID is retrieved from PDB and CIF
     1573         file to set the cryo-EM density file name during automatic detection of
     1574         density files. The format of the file name is as follows:
     1575
     1576             emd_<EMDBID>.map.gz or emd_<EMDBID>.map
     1577
     1578         The density files must be present in the working directory.
     1579     -e, --examples
     1580         Print examples.
     1581     -h, --help
     1582         Print this help message.
     1583     -i, --infiles <infile1,infile2,infile3...>
     1584         Input file names.
     1585     -l, --ligandIDs <Largest, All or ID1,ID2...>  [default: Largest]
     1586         List of ligand IDs present in chains for visualizing cryo-EM density across
     1587         ligands and ligand binding pockets. Possible values: Largest, All, or a comma
     1588         delimited list of ligand IDs. The default is to use the largest ligand present
     1589         in all or specified chains in each input file.
     1590
     1591         Ligands are identified using organic selection operator available in PyMOL.
     1592         It'll also  identify buffer molecules as ligands. The largest ligand contains
     1593         the highest number of heavy atoms.
     1594     --labelFontID <number>  [default: 7]
     1595         Font ID for drawing labels. Default: 7 (Sans Bold). Valid values: 5 to 16.
     1596         The specified value must be a valid PyMOL font ID. No validation is
     1597         performed. The complete lists of valid font IDs is available at:
     1598         pymolwiki.org/index.php/Label_font_id. Examples: 5 - Sans;
     1599         7 - Sans Bold; 9 - Serif; 10 - Serif Bold.
     1600     --meshCarveRadius <number>  [default: 1.6]
     1601         Radius in Angstroms around atoms for including cryo-EM density.
     1602     --meshComplex <yes or no>  [default: no]
     1603         Create meshes for complete complex in each input file using corresponding
     1604         density map file.
     1605     --meshChainComplex <yes, no, or auto>  [default: auto]
     1606         Create meshes for individual chain complex in each input file using
     1607         corresponding density map file. By default, the meshes are automatically
     1608         created for chain complexes without any ligands.
     1609     --meshColor <text>  [default: blue]
     1610         Line color for meshes corresponding to density maps.. The specified value
     1611         must be valid color. No validation is performed.
     1612     --meshLevel <number1,number2,...>  [default: auto]
     1613         Comma delimited list of contour levels in sigma units for generating meshes
     1614         for each input file using corresponding density map file. The default is to
     1615         automatically retrieve the recommended contour levels for each input
     1616         file. The header file emd-<EMDBID>.xml corresponding to an input file
     1617         must be present in the working directory  to automatically retrieve
     1618         recommended value for mesh contour level. Otherwise, the default contour
     1619         level is set to 1.
     1620
     1621         You may want to interactively manipulate the contour level for meshes and
     1622         surfaces. The default recommended value may not always work.
     1623     --meshWidth <number>  [default: 0.5]
     1624         Line width for mesh lines corresponding to density maps.
     1625     -o, --outfile <outfile>
     1626         Output file name.
     1627     -p, --PMLOut <yes or no>  [default: yes]
     1628         Save PML file during generation of PSE file.
     1629     --pocketContactsLigandColor <text>  [default: orange]
     1630         Color for drawing polar contacts between ligand and pocket residues.
     1631         The specified value must be valid color. No validation is performed.
     1632     --pocketContactsSolventColor <text>  [default: marine]
     1633         Color for drawing polar contacts between solvent and pocket residues.
     1634         The specified value must be valid color. No validation is performed.
     1635     --pocketContactsInorganicColor <text>  [default: deepsalmon]
     1636         Color for drawing polar contacts between inorganic and pocket residues.
     1637         The specified value must be valid color. No validation is performed.
     1638     --pocketDistanceCutoff <number>  [default: 5.0]
     1639         Distance in Angstroms for identifying pocket residues around ligands.
     1640     --pocketLabelColor <text>  [default: magenta]
     1641         Color for drawing residue or atom level labels for a pocket. The specified
     1642         value must be valid color. No validation is performed.
     1643     --pocketSurface <yes or no>  [default: yes]
     1644         Hydrophobic surface around pocket. The pocket surface is colored by
     1645         hydrophobicity. It is only valid for proteins. The color of amino acids is
     1646         set using the Eisenberg hydrophobicity scale. The color varies from red
     1647         to white, red being the most hydrophobic amino acid.
     1648     --surfaceComplex <yes or no>  [default: no]
     1649         Create surfaces for complete complex in input file(s) corresponding to density
     1650         map.
     1651     --surfaceChainComplex <yes, no or auto>  [default: auto]
     1652         Create surfaces for individual chain complexes in each input file using corresponding
     1653         density map file. By default, the surfaces are automatically created for chain complexes
     1654         without any ligands.
     1655     --surfaceTransparency <number>  [default: 0.25]
     1656         Surface transparency for molecular and cryo-EM density surfaces.
     1657     --overwrite
     1658         Overwrite existing files.
     1659     --volumeCarveRadius <number>  [default: 1.6]
     1660         Radius in Angstroms around atoms for including cryo-EM density.
     1661     --volumeComplex <yes or no>  [default: no]
     1662         Create volumes for complete complex in each input file using corresponding density
     1663         map file.
     1664     --volumeChainComplex <yes, no, or auto>  [default: auto]
     1665         Create volumes for individual chain complex in each input file using corresponding
     1666         density map file. By default, the volumes are automatically created for chain
     1667         complexes without any ligands.
     1668     --volumeColorRamp <text>  [default: auto]
     1669         Name of a volume color ramp for density map files. The specified value must
     1670         be a valid name. No validation is performed. The following volume color ramps
     1671         are currently available in PyMOL: default, 2fofc, fofc, rainbow, and rainbow2.
     1672
     1673         The default is to automatically create a new volume color ramp for the first
     1674         input file using recommended contour level with an offset of 0.3 around this value.
     1675         The header file emd-<EMDBID>.xml must be present in the working directory  to
     1676         automatically retrieve recommended contour level and generate a  volume color ramp.
     1677         Otherwise, PyMOL default volume color ramp is employed to color volumes.
     1678
     1679         The volume color ramp automatically created for the first input file is used for all
     1680         other input files.
     1681     -w, --workingdir <dir>
     1682         Location of working directory which defaults to the current directory.
     1683
     1684 Examples:
     1685     To download structure and cryo-EM data for 5K12, 5UMD, 5W81, and 5UAK
     1686     before running the following examples, type:
     1687
     1688         % DownloadPDBFiles.pl --DensityMap yes 5K12,5UMD,5W81,5UAK
     1689
     1690     To visualize cryo-EM density at recommended contour level for the first
     1691     chain complex in a PDB file using corresponding density map and header
     1692     file, and generate a PML file type:
     1693
     1694         % PyMOLVisualizeCryoEMDensity.py -i 5K12.pdb -o 5K12.pml
     1695
     1696     To visualize electron density for the largest ligand in  chain K, and ligand
     1697     binding pocket to highlight ligand interactions with pockect residues,
     1698     solvents and inorganics, in a PDB and using corresponding map files, and
     1699     generate a PML file, type:
     1700
     1701         % PyMOLVisualizeCryoEMDensity.py -c K -i 5UMD.cif -o 5UMD.pml
     1702
     1703     To visualize cryo-EM density for all  chains along with any solvents in a
     1704     PDB file and using corresponding map files, and generate a PML file, type:
     1705
     1706         % PyMOLVisualizeCryoEMDensity.py -c all -i 5K12.pdb -o 5K12.pml
     1707
     1708     To visualize cryo-EM density at a specific contour level for the first chain
     1709     complex along with volume and surface in a PDB file using corresponding
     1710     to a specific density map file, and generate a PML file, type:
     1711
     1712         % PyMOLVisualizeCryoEMDensity.py -d emd_8194.map.gz --meshLevel 1.0
     1713           --surfaceChainComplex yes --volumeChainComplex yes -i 5K12.pdb
     1714           -o 5K12.pml
     1715
     1716     To align and visualize cryo-EM density at recommended contour levels for the
     1717     largest ligand in the first chain along with pockets or the first chain complex
     1718     in input files using corresponding maps and header files, type:
     1719
     1720         % PyMOLVisualizeCryoEMDensity.py -a yes -i "5W81.pdb,5UAK.pdb"
     1721           -o SampleOut.pml
     1722
     1723     To align and visualize cryo-EM density at recommended contour levels for all
     1724     chains and ligands in input files using specified density files, type:
     1725     in input files using corresponding maps and header files, type:
     1726
     1727         % PyMOLVisualizeCryoEMDensity.py -a yes -i "5W81.pdb,5UAK.pdb"
     1728           -o SampleOut.pml -c all -l all -d "emd_8782.map.gz,emd_8516.map.gz"
     1729
     1730 Author:
     1731     Manish Sud(msud@san.rr.com)
     1732
     1733 See also:
     1734     DownloadPDBFiles.pl,  PyMOLVisualizeElectronDensity.py,
     1735     PyMOLVisualizeMacromolecules.py
     1736
     1737 Copyright:
     1738     Copyright (C) 2018 Manish Sud. All rights reserved.
     1739
     1740     The functionality available in this script is implemented using PyMOL, a
     1741     molecular visualization system on an open source foundation originally
     1742     developed by Warren DeLano.
     1743
     1744     This file is part of MayaChemTools.
     1745
     1746     MayaChemTools is free software; you can redistribute it and/or modify it under
     1747     the terms of the GNU Lesser General Public License as published by the Free
     1748     Software Foundation; either version 3 of the License, or (at your option) any
     1749     later version.
     1750
     1751 """
     1752
     1753 if __name__ == "__main__":
     1754     main()