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