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