MayaChemTools

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