1 #!/bin/env python
2 #
3 # File: PyMOLVisualizeCavities.py
4 # Author: Manish Sud <msud@san.rr.com>
5 #
6 # Copyright (C) 2026 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 import os
33 import sys
34 import time
35 import re
36
37 # PyMOL imports...
38 try:
39 import pymol
40
41 # Finish launching PyMOL in a command line mode for batch processing (-c)
42 # along with the following options: disable loading of pymolrc and plugins (-k);
43 # suppress start up messages (-q)
44 pymol.finish_launching(["pymol", "-ckq"])
45 except ImportError as ErrMsg:
46 sys.stderr.write("\nFailed to import PyMOL module/package: %s\n" % ErrMsg)
47 sys.stderr.write("Check/update your PyMOL environment and try again.\n\n")
48 sys.exit(1)
49
50 # MayaChemTools imports...
51 sys.path.insert(0, os.path.join(os.path.dirname(sys.argv[0]), "..", "lib", "Python"))
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
66 def main():
67 """Start execution of the script."""
68
69 MiscUtil.PrintInfo(
70 "\n%s (PyMOL v%s; MayaChemTools v%s; %s): Starting...\n"
71 % (ScriptName, pymol.cmd.get_version()[0], MiscUtil.GetMayaChemToolsVersion(), time.asctime())
72 )
73
74 (WallClockTime, ProcessorTime) = MiscUtil.GetWallClockAndProcessorTime()
75
76 # Retrieve command line arguments and options...
77 RetrieveOptions()
78
79 # Process and validate command line arguments and options...
80 ProcessOptions()
81
82 # Perform actions required by the script...
83 GenerateCavitiesVisualization()
84
85 MiscUtil.PrintInfo("\n%s: Done...\n" % ScriptName)
86 MiscUtil.PrintInfo("Total time: %s" % MiscUtil.GetFormattedElapsedTime(WallClockTime, ProcessorTime))
87
88
89 def GenerateCavitiesVisualization():
90 """Generate visualization for cavities."""
91
92 Outfile = OptionsInfo["PMLOutfile"]
93 OutFH = open(Outfile, "w")
94 if OutFH is None:
95 MiscUtil.PrintError("Failed to open output fie %s " % Outfile)
96
97 MiscUtil.PrintInfo("\nGenerating file %s..." % Outfile)
98
99 # Setup header...
100 WritePMLHeader(OutFH, ScriptName)
101 WritePyMOLParameters(OutFH)
102
103 # Load reffile for alignment..
104 if OptionsInfo["Align"]:
105 WriteAlignReference(OutFH)
106
107 # Setup view for each input file...
108 FirstComplex = True
109 FirstComplexFirstChainName = None
110 for FileIndex in range(0, len(OptionsInfo["InfilesInfo"]["InfilesNames"])):
111 # Setup PyMOL object names...
112 PyMOLObjectNames = SetupPyMOLObjectNames(FileIndex)
113
114 # Setup complex view...
115 WriteComplexView(OutFH, FileIndex, PyMOLObjectNames, FirstComplex)
116
117 SpecifiedChainsAndLigandsInfo = OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"][FileIndex]
118 FirstChain = True
119 for ChainID in SpecifiedChainsAndLigandsInfo["ChainIDs"]:
120 if FirstComplex and FirstChain:
121 FirstComplexFirstChainName = PyMOLObjectNames["Chains"][ChainID]["ChainAlone"]
122
123 WriteChainView(OutFH, FileIndex, PyMOLObjectNames, ChainID)
124
125 # Setup ligand views...
126 FirstLigand = True
127 for LigandID in SpecifiedChainsAndLigandsInfo["LigandIDs"][ChainID]:
128 WriteChainLigandView(OutFH, FileIndex, PyMOLObjectNames, ChainID, LigandID)
129
130 # Set up ligand level group...
131 Enable, Action = [False, "close"]
132 if FirstLigand:
133 FirstLigand = False
134 Enable, Action = [True, "open"]
135 GenerateAndWritePMLForGroup(
136 OutFH,
137 PyMOLObjectNames["Ligands"][ChainID][LigandID]["ChainLigandGroup"],
138 PyMOLObjectNames["Ligands"][ChainID][LigandID]["ChainLigandGroupMembers"],
139 Enable,
140 Action,
141 )
142
143 # Setup Chain level group...
144 Enable, Action = [False, "close"]
145 if FirstChain:
146 FirstChain = False
147 Enable, Action = [True, "open"]
148 GenerateAndWritePMLForGroup(
149 OutFH,
150 PyMOLObjectNames["Chains"][ChainID]["ChainGroup"],
151 PyMOLObjectNames["Chains"][ChainID]["ChainGroupMembers"],
152 Enable,
153 Action,
154 )
155
156 # Set up complex level group...
157 Enable, Action = [False, "close"]
158 if FirstComplex:
159 FirstComplex = False
160 Enable, Action = [True, "open"]
161 GenerateAndWritePMLForGroup(
162 OutFH, PyMOLObjectNames["PDBGroup"], PyMOLObjectNames["PDBGroupMembers"], Enable, Action
163 )
164
165 # Delete empty PyMOL objects...
166 DeleteEmptyPyMOLObjects(OutFH, FileIndex, PyMOLObjectNames)
167
168 if OptionsInfo["Align"]:
169 DeleteAlignReference(OutFH)
170
171 if FirstComplexFirstChainName is not None:
172 OutFH.write("""\ncmd.orient("%s", animate = -1)\n""" % FirstComplexFirstChainName)
173 else:
174 OutFH.write("""\ncmd.orient("visible", animate = -1)\n""")
175
176 OutFH.close()
177
178 # Generate PSE file as needed...
179 if OptionsInfo["PSEOut"]:
180 GeneratePyMOLSessionFile()
181
182
183 def WritePMLHeader(OutFH, ScriptName):
184 """Write out PML setting up complex view."""
185
186 HeaderInfo = PyMOLUtil.SetupPMLHeaderInfo(ScriptName)
187 OutFH.write("%s\n" % HeaderInfo)
188
189
190 def WritePyMOLParameters(OutFH):
191 """Write out PyMOL global parameters."""
192
193 PMLCmds = []
194 PMLCmds.append("""cmd.set("transparency", %.2f, "", 0)""" % (OptionsInfo["SurfaceTransparency"]))
195 PMLCmds.append("""cmd.set("label_font_id", %s)""" % (OptionsInfo["LabelFontID"]))
196
197 PMLCmds.append("""cmd.set("cavity_cull", %.1f, "", 0)""" % (OptionsInfo["CavityCullSize"]))
198 PMLCmds.append("""cmd.set("surface_cavity_radius", -%.1f, "", 0)""" % (OptionsInfo["CavityRadius"]))
199 PMLCmds.append("""cmd.set("surface_cavity_cutoff", -%.1f, "", 0)""" % (OptionsInfo["CavityCutoff"]))
200
201 PML = "\n".join(PMLCmds)
202
203 OutFH.write("""\n""\n"Setting up PyMOL gobal parameters..."\n""\n""")
204 OutFH.write("%s\n" % PML)
205
206
207 def WriteAlignReference(OutFH):
208 """Setup object for alignment reference."""
209
210 RefFileInfo = OptionsInfo["RefFileInfo"]
211 RefFile = RefFileInfo["RefFileName"]
212 RefName = RefFileInfo["PyMOLObjectName"]
213
214 PMLCmds = []
215 PMLCmds.append("""cmd.load("%s", "%s")""" % (RefFile, RefName))
216 PMLCmds.append("""cmd.hide("everything", "%s")""" % (RefName))
217 PMLCmds.append("""cmd.disable("%s")""" % (RefName))
218 PML = "\n".join(PMLCmds)
219
220 OutFH.write("""\n""\n"Loading %s and setting up view for align reference..."\n""\n""" % RefFile)
221 OutFH.write("%s\n" % PML)
222
223
224 def WriteAlignComplex(OutFH, FileIndex, PyMOLObjectNames):
225 """Setup alignment of complex to reference."""
226
227 RefFileInfo = OptionsInfo["RefFileInfo"]
228 RefName = RefFileInfo["PyMOLObjectName"]
229
230 ComplexName = PyMOLObjectNames["Complex"]
231
232 if re.match("^FirstChain$", OptionsInfo["AlignMode"], re.I):
233 RefFirstChainID = RefFileInfo["ChainsAndLigandsInfo"]["ChainIDs"][0]
234 RefAlignSelection = "%s and chain %s" % (RefName, RefFirstChainID)
235
236 ComplexFirstChainID = RetrieveFirstChainID(FileIndex)
237 ComplexAlignSelection = "%s and chain %s" % (ComplexName, ComplexFirstChainID)
238 else:
239 RefAlignSelection = RefName
240 ComplexAlignSelection = ComplexName
241
242 PML = PyMOLUtil.SetupPMLForAlignment(OptionsInfo["AlignMethod"], RefAlignSelection, ComplexAlignSelection)
243 OutFH.write("""\n""\n"Aligning %s against reference %s ..."\n""\n""" % (ComplexAlignSelection, RefAlignSelection))
244 OutFH.write("%s\n" % PML)
245
246
247 def DeleteAlignReference(OutFH):
248 """Delete alignment reference object."""
249
250 RefName = OptionsInfo["RefFileInfo"]["PyMOLObjectName"]
251 OutFH.write("""\n""\n"Deleting alignment reference object %s..."\n""\n""" % RefName)
252 OutFH.write("""cmd.delete("%s")\n""" % RefName)
253
254
255 def WriteComplexView(OutFH, FileIndex, PyMOLObjectNames, FirstComplex):
256 """Write out PML for viewing polymer complex."""
257
258 # Setup complex...
259 Infile = OptionsInfo["InfilesInfo"]["InfilesNames"][FileIndex]
260 PML = PyMOLUtil.SetupPMLForPolymerComplexView(PyMOLObjectNames["Complex"], Infile, True)
261 OutFH.write("""\n""\n"Loading %s and setting up view for complex..."\n""\n""" % Infile)
262 OutFH.write("%s\n" % PML)
263
264 if OptionsInfo["Align"]:
265 # No need to align complex on to itself...
266 if not (re.match("^FirstInputFile$", OptionsInfo["AlignRefFile"], re.I) and FirstComplex):
267 WriteAlignComplex(OutFH, FileIndex, PyMOLObjectNames)
268
269 if OptionsInfo["SurfaceComplex"]:
270 # Setup hydrophobic surface...
271 PML = PyMOLUtil.SetupPMLForHydrophobicSurfaceView(
272 PyMOLObjectNames["ComplexHydrophobicSurface"],
273 PyMOLObjectNames["Complex"],
274 ColorPalette=OptionsInfo["SurfaceColorPalette"],
275 Enable=False,
276 )
277 OutFH.write("\n%s\n" % PML)
278
279 # Setup complex group...
280 GenerateAndWritePMLForGroup(
281 OutFH, PyMOLObjectNames["ComplexGroup"], PyMOLObjectNames["ComplexGroupMembers"], False, "close"
282 )
283
284
285 def WriteChainView(OutFH, FileIndex, PyMOLObjectNames, ChainID):
286 """Write out PML for viewing chain."""
287
288 OutFH.write("""\n""\n"Setting up views for chain %s..."\n""\n""" % ChainID)
289
290 ChainComplexName = PyMOLObjectNames["Chains"][ChainID]["ChainComplex"]
291
292 # Setup chain complex group view...
293 WriteChainComplexViews(OutFH, FileIndex, PyMOLObjectNames, ChainID)
294
295 # Setup chain view...
296 WriteChainAloneViews(OutFH, FileIndex, PyMOLObjectNames, ChainID)
297
298 # Setup chain solvent view...
299 PML = PyMOLUtil.SetupPMLForSolventView(PyMOLObjectNames["Chains"][ChainID]["Solvent"], ChainComplexName, False)
300 OutFH.write("\n%s\n" % PML)
301
302 # Setup chain inorganic view...
303 PML = PyMOLUtil.SetupPMLForInorganicView(PyMOLObjectNames["Chains"][ChainID]["Inorganic"], ChainComplexName, False)
304 OutFH.write("\n%s\n" % PML)
305
306
307 def WriteChainComplexViews(OutFH, FileIndex, PyMOLObjectNames, ChainID):
308 """Write chain complex views."""
309
310 # Setup chain complex...
311 ChainComplexName = PyMOLObjectNames["Chains"][ChainID]["ChainComplex"]
312 PML = PyMOLUtil.SetupPMLForPolymerChainComplexView(ChainComplexName, PyMOLObjectNames["Complex"], ChainID, True)
313 OutFH.write("%s\n" % PML)
314
315 if OptionsInfo["SurfaceChainComplex"]:
316 # Setup hydrophobic surface...
317 PML = PyMOLUtil.SetupPMLForHydrophobicSurfaceView(
318 PyMOLObjectNames["Chains"][ChainID]["ChainComplexHydrophobicSurface"],
319 ChainComplexName,
320 ColorPalette=OptionsInfo["SurfaceColorPalette"],
321 Enable=False,
322 )
323 OutFH.write("\n%s\n" % PML)
324
325 # Setup chain complex group...
326 GenerateAndWritePMLForGroup(
327 OutFH,
328 PyMOLObjectNames["Chains"][ChainID]["ChainComplexGroup"],
329 PyMOLObjectNames["Chains"][ChainID]["ChainComplexGroupMembers"],
330 False,
331 "close",
332 )
333
334
335 def WriteChainAloneViews(OutFH, FileIndex, PyMOLObjectNames, ChainID):
336 """Write individual chain views."""
337
338 ChainComplexName = PyMOLObjectNames["Chains"][ChainID]["ChainComplex"]
339
340 # Setup chain view...
341 ChainName = PyMOLObjectNames["Chains"][ChainID]["ChainAlone"]
342 PML = PyMOLUtil.SetupPMLForPolymerChainView(ChainName, ChainComplexName, True)
343 OutFH.write("\n%s\n" % PML)
344
345 WriteChainAloneResidueTypesView(OutFH, FileIndex, PyMOLObjectNames, ChainID)
346 WriteChainAloneCavitiesAndSurfacesView(OutFH, FileIndex, PyMOLObjectNames, ChainID)
347
348 # Setup chain group...
349 GenerateAndWritePMLForGroup(
350 OutFH,
351 PyMOLObjectNames["Chains"][ChainID]["ChainAloneGroup"],
352 PyMOLObjectNames["Chains"][ChainID]["ChainAloneGroupMembers"],
353 True,
354 "open",
355 )
356
357
358 def WriteChainLigandView(OutFH, FileIndex, PyMOLObjectNames, ChainID, LigandID):
359 """Write out PML for viewing ligand in a chain."""
360
361 GroupID = "Ligand"
362 ComplexName = PyMOLObjectNames["Chains"][ChainID]["ChainComplex"]
363
364 # Setup main object...
365 GroupTypeObjectID = "%s" % (GroupID)
366 GroupTypeObjectName = PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupTypeObjectID]
367
368 OutFH.write("""\n""\n"Setting up views for ligand %s in chain %s..."\n""\n""" % (LigandID, ChainID))
369 PML = PyMOLUtil.SetupPMLForLigandView(
370 GroupTypeObjectName, ComplexName, LigandID, Enable=True, IgnoreHydrogens=OptionsInfo["IgnoreHydrogens"]
371 )
372 OutFH.write("%s\n" % PML)
373
374 # Setup ball and stick view...
375 BallAndStickNameID = "%sBallAndStick" % (GroupID)
376 BallAndStickName = PyMOLObjectNames["Ligands"][ChainID][LigandID][BallAndStickNameID]
377 PML = PyMOLUtil.SetupPMLForBallAndStickView(BallAndStickName, GroupTypeObjectName, Enable=False)
378 OutFH.write("\n%s\n" % PML)
379
380 # Setup group....
381 GroupNameID = "%sGroup" % (GroupID)
382 GroupMembersID = "%sGroupMembers" % (GroupID)
383 GroupName = PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupNameID]
384 GroupMembers = PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupMembersID]
385
386 Action = "close"
387 Enable = True
388 GenerateAndWritePMLForGroup(OutFH, GroupName, GroupMembers, Enable, Action)
389
390
391 def WriteChainAloneCavitiesAndSurfacesView(OutFH, FileIndex, PyMOLObjectNames, ChainID):
392 """Write out PML for viewing cavities and pockets in chains."""
393
394 if not GetChainAloneContainsSurfacesStatus(FileIndex, ChainID):
395 return
396
397 ChainName = PyMOLObjectNames["Chains"][ChainID]["ChainAlone"]
398
399 for SubGroupType in ["Cavities", "Surface"]:
400 SubGroupID = "ChainAlone%sGroup" % (SubGroupType)
401 SubGroupMembersID = "%sMembers" % (SubGroupID)
402
403 ProcessingCavities = True if re.match("^Cavities$", SubGroupType, re.I) else False
404
405 # Turn off lines display for cavity surfaces...
406 DisplayStyle = None if ProcessingCavities else "cartoon"
407
408 # Setup a generic color surface...
409 SurfaceID = "%sSurface" % (SubGroupID)
410 SurfaceName = PyMOLObjectNames["Chains"][ChainID][SurfaceID]
411 ColorName = OptionsInfo["SurfaceCavityColor"] if ProcessingCavities else OptionsInfo["SurfaceColor"]
412 EnableStatus = True if ProcessingCavities else False
413 PML = PyMOLUtil.SetupPMLForSurfaceView(SurfaceName, ChainName, Enable=EnableStatus, Color=ColorName)
414 OutFH.write("\n%s\n" % PML)
415
416 if ProcessingCavities:
417 OutFH.write(
418 """cmd.set("surface_cavity_mode", %d, "%s")\n""" % (OptionsInfo["SurfaceCavityMode"], SurfaceName)
419 )
420
421 if GetChainAloneSurfaceChainStatus(FileIndex, ChainID):
422 # Setup surface colored by hydrophobicity...
423 HydrophobicSurfaceID = "%sHydrophobicSurface" % (SubGroupID)
424 HydrophobicSurfaceName = PyMOLObjectNames["Chains"][ChainID][HydrophobicSurfaceID]
425 PML = PyMOLUtil.SetupPMLForHydrophobicSurfaceView(
426 HydrophobicSurfaceName, ChainName, ColorPalette=OptionsInfo["SurfaceColorPalette"], Enable=False
427 )
428 OutFH.write("\n%s\n" % PML)
429
430 if ProcessingCavities:
431 OutFH.write(
432 """cmd.set("surface_cavity_mode", %d, "%s")\n"""
433 % (OptionsInfo["SurfaceCavityMode"], HydrophobicSurfaceName)
434 )
435
436 # Setup surface colored by hyrdophobicity and charge...
437 HydrophobicChargeSurfaceID = "%sHydrophobicChargeSurface" % (SubGroupID)
438 HydrophobicChargeSurfaceName = PyMOLObjectNames["Chains"][ChainID][HydrophobicChargeSurfaceID]
439 PML = PyMOLUtil.SetupPMLForHydrophobicAndChargeSurfaceView(
440 HydrophobicChargeSurfaceName,
441 ChainName,
442 OptionsInfo["AtomTypesColorNames"]["HydrophobicAtomsColor"],
443 OptionsInfo["AtomTypesColorNames"]["NegativelyChargedAtomsColor"],
444 OptionsInfo["AtomTypesColorNames"]["PositivelyChargedAtomsColor"],
445 OptionsInfo["AtomTypesColorNames"]["OtherAtomsColor"],
446 Enable=False,
447 DisplayAs=None,
448 )
449 OutFH.write("\n%s\n" % PML)
450
451 if ProcessingCavities:
452 OutFH.write(
453 """cmd.set("surface_cavity_mode", %d, "%s")\n"""
454 % (OptionsInfo["SurfaceCavityMode"], HydrophobicChargeSurfaceName)
455 )
456
457 if GetChainAloneSurfaceChainElectrostaticsStatus(FileIndex, ChainID):
458 # Setup electrostatics surface...
459 ElectrostaticsGroupID = "%sElectrostaticsGroup" % (SubGroupID)
460 ElectrostaticsGroupMembersID = "%sElectrostaticsGroupMembers" % (SubGroupID)
461 ElectrostaticsGroupName = PyMOLObjectNames["Chains"][ChainID][ElectrostaticsGroupID]
462 ElectrostaticsGroupMembers = PyMOLObjectNames["Chains"][ChainID][ElectrostaticsGroupMembersID]
463 WriteSurfaceElectrostaticsView(
464 SubGroupType,
465 OutFH,
466 ChainName,
467 ElectrostaticsGroupName,
468 ElectrostaticsGroupMembers,
469 DisplayAs=DisplayStyle,
470 SurfaceCavityMode=OptionsInfo["SurfaceCavityMode"],
471 )
472
473 # Setup surface group...
474 GenerateAndWritePMLForGroup(
475 OutFH,
476 PyMOLObjectNames["Chains"][ChainID][SubGroupID],
477 PyMOLObjectNames["Chains"][ChainID][SubGroupMembersID],
478 True,
479 "open",
480 )
481
482
483 def WriteChainAloneResidueTypesView(OutFH, FileIndex, PyMOLObjectNames, ChainID):
484 """Write out PML for viewing residue types for a chain."""
485
486 if not GetChainAloneResidueTypesStatus(FileIndex, ChainID):
487 return
488
489 ChainName = PyMOLObjectNames["Chains"][ChainID]["ChainAlone"]
490
491 # Setup residue types objects...
492 ResiduesGroupIDPrefix = "ChainAloneResidues"
493 for SubGroupType in ["Aromatic", "Hydrophobic", "Polar", "Positively_Charged", "Negatively_Charged", "Other"]:
494 SubGroupID = re.sub("_", "", SubGroupType)
495
496 ResiduesObjectID = "%s%sResidues" % (ResiduesGroupIDPrefix, SubGroupID)
497 ResiduesObjectName = PyMOLObjectNames["Chains"][ChainID][ResiduesObjectID]
498
499 ResiduesSurfaceObjectID = "%s%sSurface" % (ResiduesGroupIDPrefix, SubGroupID)
500 ResiduesSurfaceObjectName = PyMOLObjectNames["Chains"][ChainID][ResiduesSurfaceObjectID]
501
502 ResiduesColor = OptionsInfo["ResidueTypesParams"][SubGroupType]["Color"]
503 ResiduesNames = OptionsInfo["ResidueTypesParams"][SubGroupType]["Residues"]
504
505 NegateResidueNames = True if re.match("^Other$", SubGroupType, re.I) else False
506 WriteResidueTypesResiduesAndSurfaceView(
507 OutFH,
508 ChainName,
509 ResiduesObjectName,
510 ResiduesSurfaceObjectName,
511 ResiduesColor,
512 ResiduesNames,
513 NegateResidueNames,
514 )
515
516 # Setup sub groups for residue types..
517 ResiduesSubGroupID = "%s%sGroup" % (ResiduesGroupIDPrefix, SubGroupID)
518 ResiduesSubGroupMembersID = "%s%sGroupMembers" % (ResiduesGroupIDPrefix, SubGroupID)
519
520 # Setup residue type sub groups...
521 GenerateAndWritePMLForGroup(
522 OutFH,
523 PyMOLObjectNames["Chains"][ChainID][ResiduesSubGroupID],
524 PyMOLObjectNames["Chains"][ChainID][ResiduesSubGroupMembersID],
525 True,
526 "close",
527 )
528
529 # Setup residue types group...
530 GenerateAndWritePMLForGroup(
531 OutFH,
532 PyMOLObjectNames["Chains"][ChainID]["ChainAloneResiduesGroup"],
533 PyMOLObjectNames["Chains"][ChainID]["ChainAloneResiduesGroupMembers"],
534 False,
535 "close",
536 )
537
538
539 def WriteResidueTypesResiduesAndSurfaceView(
540 OutFH, SelectionObjectName, Name, SurfaceName, ResiduesColor, ResiduesNames, NegateResidueNames
541 ):
542 """Write residue types residues and surface view."""
543
544 ResidueNamesSelection = "+".join(ResiduesNames)
545 if NegateResidueNames:
546 Selection = "%s and (not resn %s)" % (SelectionObjectName, ResidueNamesSelection)
547 else:
548 Selection = "%s and (resn %s)" % (SelectionObjectName, ResidueNamesSelection)
549
550 # Setup residues...
551 PML = PyMOLUtil.SetupPMLForSelectionDisplayView(Name, Selection, "lines", ResiduesColor, True)
552 OutFH.write("\n%s\n" % PML)
553
554 # Setup surface...
555 PML = PyMOLUtil.SetupPMLForSelectionDisplayView(SurfaceName, Selection, "surface", ResiduesColor, True)
556 OutFH.write("\n%s\n" % PML)
557
558
559 def WriteSurfaceElectrostaticsView(
560 Mode,
561 OutFH,
562 SelectionObjectName,
563 ElectrostaticsGroupName,
564 ElectrostaticsGroupMembers,
565 DisplayAs=None,
566 SurfaceCavityMode=2,
567 ):
568 """Write out PML for viewing surface electrostatics."""
569
570 if len(ElectrostaticsGroupMembers) == 5:
571 Name, ContactPotentialName, MapName, LegendName, VolumeName = ElectrostaticsGroupMembers
572 else:
573 Name, ContactPotentialName, MapName, LegendName = ElectrostaticsGroupMembers
574 VolumeName = None
575
576 PMLCmds = []
577
578 # Setup chain...
579 PMLCmds.append("""cmd.create("%s", "(%s)")""" % (Name, SelectionObjectName))
580
581 # Setup vacuum electrostatics surface along with associated objects...
582 PMLCmds.append("""util.protein_vacuum_esp("%s", mode=2, quiet=0, _self=cmd)""" % (Name))
583 PMLCmds.append("""cmd.set_name("%s_e_chg", "%s")""" % (Name, ContactPotentialName))
584
585 if DisplayAs is not None:
586 PMLCmds.append("""cmd.show("%s", "(%s)")""" % (DisplayAs, ContactPotentialName))
587
588 if re.match("^Cavities$", Mode, re.I):
589 if SurfaceCavityMode is not None:
590 PMLCmds.append("""cmd.set("surface_cavity_mode", %d, "%s")\n""" % (SurfaceCavityMode, ContactPotentialName))
591
592 PMLCmds.append(PyMOLUtil.SetupPMLForEnableDisable(ContactPotentialName, Enable=True))
593
594 PMLCmds.append("""cmd.set_name("%s_e_map", "%s")""" % (Name, MapName))
595 PMLCmds.append(PyMOLUtil.SetupPMLForEnableDisable(MapName, Enable=False))
596
597 PMLCmds.append("""cmd.set_name("%s_e_pot", "%s")""" % (Name, LegendName))
598 PMLCmds.append(PyMOLUtil.SetupPMLForEnableDisable(LegendName, Enable=False))
599
600 if VolumeName is not None:
601 PMLCmds.append("""cmd.volume("%s", "%s", "%s", "(%s)")""" % (VolumeName, MapName, "esp", Name))
602 PMLCmds.append(PyMOLUtil.SetupPMLForEnableDisable(VolumeName, Enable=False))
603
604 # Delete name and take it out from the group membership. It is
605 # is already part of ContactPotential object.
606 PMLCmds.append("""cmd.delete("%s")""" % (Name))
607 ElectrostaticsGroupMembers.pop(0)
608
609 PML = "\n".join(PMLCmds)
610
611 OutFH.write("\n%s\n" % PML)
612
613 # Setup group...
614 GenerateAndWritePMLForGroup(OutFH, ElectrostaticsGroupName, ElectrostaticsGroupMembers, False, "close")
615
616
617 def GenerateAndWritePMLForGroup(OutFH, GroupName, GroupMembers, Enable=False, Action="close"):
618 """Generate and write PML for group."""
619
620 PML = PyMOLUtil.SetupPMLForGroup(GroupName, GroupMembers, Enable, Action)
621 OutFH.write("""\n""\n"Setting up group %s..."\n""\n""" % GroupName)
622 OutFH.write("%s\n" % PML)
623
624
625 def GeneratePyMOLSessionFile():
626 """Generate PME file from PML file."""
627
628 PSEOutfile = OptionsInfo["PSEOutfile"]
629 PMLOutfile = OptionsInfo["PMLOutfile"]
630
631 MiscUtil.PrintInfo("\nGenerating file %s..." % PSEOutfile)
632
633 PyMOLUtil.ConvertPMLFileToPSEFile(PMLOutfile, PSEOutfile)
634
635 if not os.path.exists(PSEOutfile):
636 MiscUtil.PrintWarning("Failed to generate PSE file, %s..." % (PSEOutfile))
637
638 if not OptionsInfo["PMLOut"]:
639 MiscUtil.PrintInfo("Deleting file %s..." % PMLOutfile)
640 os.remove(PMLOutfile)
641
642
643 def DeleteEmptyPyMOLObjects(OutFH, FileIndex, PyMOLObjectNames):
644 """Delete empty PyMOL objects."""
645
646 if OptionsInfo["AllowEmptyObjects"]:
647 return
648
649 SpecifiedChainsAndLigandsInfo = OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"][FileIndex]
650 for ChainID in SpecifiedChainsAndLigandsInfo["ChainIDs"]:
651 OutFH.write("""\n""\n"Checking and deleting empty objects for chain %s..."\n""\n""" % (ChainID))
652
653 # Delete any chain level objects...
654 WritePMLToCheckAndDeleteEmptyObjects(OutFH, PyMOLObjectNames["Chains"][ChainID]["Solvent"])
655 WritePMLToCheckAndDeleteEmptyObjects(OutFH, PyMOLObjectNames["Chains"][ChainID]["Inorganic"])
656
657 # Delete residue type objects...
658 DeleteEmptyChainResidueTypesObjects(OutFH, FileIndex, PyMOLObjectNames, ChainID)
659
660
661 def DeleteEmptyChainResidueTypesObjects(OutFH, FileIndex, PyMOLObjectNames, ChainID):
662 """Delete empty chain residue objects."""
663
664 if not GetChainAloneResidueTypesStatus(FileIndex, ChainID):
665 return
666
667 ResiduesGroupIDPrefix = "ChainAloneResidues"
668 for GroupType in ["Aromatic", "Hydrophobic", "Polar", "Positively_Charged", "Negatively_Charged", "Other"]:
669 GroupID = re.sub("_", "", GroupType)
670
671 ResiduesGroupID = "%s%sGroup" % (ResiduesGroupIDPrefix, GroupID)
672 GroupName = PyMOLObjectNames["Chains"][ChainID][ResiduesGroupID]
673
674 GroupObjectNamesList = []
675
676 ResiduesObjectID = "%s%sResidues" % (ResiduesGroupIDPrefix, GroupID)
677 ResiduesObjectName = PyMOLObjectNames["Chains"][ChainID][ResiduesObjectID]
678 GroupObjectNamesList.append(ResiduesObjectName)
679
680 ResiduesSurfaceObjectID = "%s%sSurface" % (ResiduesGroupIDPrefix, GroupID)
681 ResiduesSurfaceObjectName = PyMOLObjectNames["Chains"][ChainID][ResiduesSurfaceObjectID]
682 GroupObjectNamesList.append(ResiduesSurfaceObjectName)
683
684 GroupObjectNames = ",".join(GroupObjectNamesList)
685 WritePMLToCheckAndDeleteEmptyObjects(OutFH, GroupObjectNames, GroupName)
686
687
688 def WritePMLToCheckAndDeleteEmptyObjects(OutFH, ObjectName, ParentObjectName=None):
689 """Write PML to check and delete empty PyMOL objects."""
690
691 if ParentObjectName is None:
692 PML = """CheckAndDeleteEmptyObjects("%s")""" % (ObjectName)
693 else:
694 PML = """CheckAndDeleteEmptyObjects("%s", "%s")""" % (ObjectName, ParentObjectName)
695
696 OutFH.write("%s\n" % PML)
697
698
699 def SetupPyMOLObjectNames(FileIndex):
700 """Setup hierarchy of PyMOL groups and objects for ligand centric views of
701 chains and ligands present in input file.
702 """
703
704 PyMOLObjectNames = {}
705 PyMOLObjectNames["Chains"] = {}
706 PyMOLObjectNames["Ligands"] = {}
707
708 # Setup groups and objects for complex...
709 SetupPyMOLObjectNamesForComplex(FileIndex, PyMOLObjectNames)
710
711 # Setup groups and objects for chain...
712 SpecifiedChainsAndLigandsInfo = OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"][FileIndex]
713 for ChainID in SpecifiedChainsAndLigandsInfo["ChainIDs"]:
714 SetupPyMOLObjectNamesForChain(FileIndex, PyMOLObjectNames, ChainID)
715
716 # Setup groups and objects for ligand...
717 for LigandID in SpecifiedChainsAndLigandsInfo["LigandIDs"][ChainID]:
718 SetupPyMOLObjectNamesForLigand(FileIndex, PyMOLObjectNames, ChainID, LigandID)
719
720 return PyMOLObjectNames
721
722
723 def SetupPyMOLObjectNamesForComplex(FileIndex, PyMOLObjectNames):
724 """Setup groups and objects for complex."""
725
726 PDBFileRoot = OptionsInfo["InfilesInfo"]["InfilesRoots"][FileIndex]
727
728 PDBGroupName = "%s" % PDBFileRoot
729 PyMOLObjectNames["PDBGroup"] = PDBGroupName
730 PyMOLObjectNames["PDBGroupMembers"] = []
731
732 ComplexGroupName = "%s.Complex" % PyMOLObjectNames["PDBGroup"]
733 PyMOLObjectNames["ComplexGroup"] = ComplexGroupName
734 PyMOLObjectNames["PDBGroupMembers"].append(ComplexGroupName)
735
736 PyMOLObjectNames["Complex"] = "%s.Complex" % ComplexGroupName
737 if OptionsInfo["SurfaceComplex"]:
738 PyMOLObjectNames["ComplexHydrophobicSurface"] = "%s.Surface" % ComplexGroupName
739
740 PyMOLObjectNames["ComplexGroupMembers"] = []
741 PyMOLObjectNames["ComplexGroupMembers"].append(PyMOLObjectNames["Complex"])
742 if OptionsInfo["SurfaceComplex"]:
743 PyMOLObjectNames["ComplexGroupMembers"].append(PyMOLObjectNames["ComplexHydrophobicSurface"])
744
745
746 def SetupPyMOLObjectNamesForChain(FileIndex, PyMOLObjectNames, ChainID):
747 """Setup groups and objects for chain."""
748
749 PDBGroupName = PyMOLObjectNames["PDBGroup"]
750
751 PyMOLObjectNames["Chains"][ChainID] = {}
752 PyMOLObjectNames["Ligands"][ChainID] = {}
753
754 # Set up chain group and chain objects...
755 ChainGroupName = "%s.Chain%s" % (PDBGroupName, ChainID)
756 PyMOLObjectNames["Chains"][ChainID]["ChainGroup"] = ChainGroupName
757 PyMOLObjectNames["PDBGroupMembers"].append(ChainGroupName)
758 PyMOLObjectNames["Chains"][ChainID]["ChainGroupMembers"] = []
759
760 # Setup chain complex group and objects...
761 ChainComplexGroupName = "%s.Complex" % (ChainGroupName)
762 PyMOLObjectNames["Chains"][ChainID]["ChainComplexGroup"] = ChainComplexGroupName
763 PyMOLObjectNames["Chains"][ChainID]["ChainGroupMembers"].append(ChainComplexGroupName)
764
765 PyMOLObjectNames["Chains"][ChainID]["ChainComplexGroupMembers"] = []
766
767 Name = "%s.Complex" % (ChainComplexGroupName)
768 PyMOLObjectNames["Chains"][ChainID]["ChainComplex"] = Name
769 PyMOLObjectNames["Chains"][ChainID]["ChainComplexGroupMembers"].append(Name)
770
771 if OptionsInfo["SurfaceChainComplex"]:
772 Name = "%s.Surface" % (ChainComplexGroupName)
773 PyMOLObjectNames["Chains"][ChainID]["ChainComplexHydrophobicSurface"] = Name
774 PyMOLObjectNames["Chains"][ChainID]["ChainComplexGroupMembers"].append(Name)
775
776 # Setup up a group for individual chains...
777 ChainAloneGroupName = "%s.Chain" % (ChainGroupName)
778 PyMOLObjectNames["Chains"][ChainID]["ChainAloneGroup"] = ChainAloneGroupName
779 PyMOLObjectNames["Chains"][ChainID]["ChainGroupMembers"].append(ChainAloneGroupName)
780
781 PyMOLObjectNames["Chains"][ChainID]["ChainAloneGroupMembers"] = []
782
783 Name = "%s.Chain" % (ChainAloneGroupName)
784 PyMOLObjectNames["Chains"][ChainID]["ChainAlone"] = Name
785 PyMOLObjectNames["Chains"][ChainID]["ChainAloneGroupMembers"].append(Name)
786
787 if GetChainAloneResidueTypesStatus(FileIndex, ChainID):
788 # Setup residue type group and its subgroups...
789 ResiduesGroupName = "%s.Residues" % (ChainAloneGroupName)
790
791 ResiduesGroupIDPrefix = "ChainAloneResidues"
792 ResiduesGroupID = "%sGroup" % ResiduesGroupIDPrefix
793
794 # Add residue group to chain alone group...
795 PyMOLObjectNames["Chains"][ChainID][ResiduesGroupID] = ResiduesGroupName
796 PyMOLObjectNames["Chains"][ChainID]["ChainAloneGroupMembers"].append(ResiduesGroupName)
797
798 # Initialize residue group members...
799 ResiduesGroupMembersID = "%sGroupMembers" % ResiduesGroupIDPrefix
800 PyMOLObjectNames["Chains"][ChainID][ResiduesGroupMembersID] = []
801
802 # Setup residues sub groups and its members...
803 for SubGroupType in ["Aromatic", "Hydrophobic", "Polar", "Positively_Charged", "Negatively_Charged", "Other"]:
804 SubGroupID = re.sub("_", "", SubGroupType)
805
806 ResiduesSubGroupName = "%s.%s" % (ResiduesGroupName, SubGroupType)
807 ResiduesSubGroupID = "%s%sGroup" % (ResiduesGroupIDPrefix, SubGroupID)
808
809 # Add sub group to residues group...
810 PyMOLObjectNames["Chains"][ChainID][ResiduesSubGroupID] = ResiduesSubGroupName
811 PyMOLObjectNames["Chains"][ChainID][ResiduesGroupMembersID].append(ResiduesSubGroupName)
812
813 # Initialize sub group members...
814 ResiduesSubGroupMembersID = "%s%sGroupMembers" % (ResiduesGroupIDPrefix, SubGroupID)
815 PyMOLObjectNames["Chains"][ChainID][ResiduesSubGroupMembersID] = []
816
817 # Add sub group members to subgroup...
818 for MemberType in ["Residues", "Surface"]:
819 MemberID = re.sub("_", "", MemberType)
820
821 SubGroupMemberName = "%s.%s" % (ResiduesSubGroupName, MemberType)
822 SubGroupMemberID = "%s%s%s" % (ResiduesGroupIDPrefix, SubGroupID, MemberID)
823
824 PyMOLObjectNames["Chains"][ChainID][SubGroupMemberID] = SubGroupMemberName
825 PyMOLObjectNames["Chains"][ChainID][ResiduesSubGroupMembersID].append(SubGroupMemberName)
826
827 if GetChainAloneContainsSurfacesStatus(FileIndex, ChainID):
828 # Setup cavity and surface groups...
829 for SubGroupType in ["Cavities", "Surface"]:
830 SubGroupName = "%s.%s" % (ChainAloneGroupName, SubGroupType)
831 SubGroupID = "ChainAlone%sGroup" % (SubGroupType)
832 SubGroupMembersID = "%sMembers" % (SubGroupID)
833
834 PyMOLObjectNames["Chains"][ChainID][SubGroupID] = SubGroupName
835 PyMOLObjectNames["Chains"][ChainID]["ChainAloneGroupMembers"].append(SubGroupName)
836
837 PyMOLObjectNames["Chains"][ChainID][SubGroupMembersID] = []
838
839 # Setup a generic color surface...
840 SurfaceName = "%s.Surface" % (SubGroupName)
841 SurfaceID = "%sSurface" % (SubGroupID)
842 PyMOLObjectNames["Chains"][ChainID][SurfaceID] = SurfaceName
843 PyMOLObjectNames["Chains"][ChainID][SubGroupMembersID].append(SurfaceName)
844
845 if GetChainAloneSurfaceChainStatus(FileIndex, ChainID):
846 # Setup hydrophobicity surface...
847 HydrophobicSurfaceName = "%s.Hydrophobicity" % (SubGroupName)
848 HydrophobicSurfaceID = "%sHydrophobicSurface" % (SubGroupID)
849 PyMOLObjectNames["Chains"][ChainID][HydrophobicSurfaceID] = HydrophobicSurfaceName
850 PyMOLObjectNames["Chains"][ChainID][SubGroupMembersID].append(HydrophobicSurfaceName)
851
852 # Setup hydrophobicity and charge surface...
853 HydrophobicChargeSurfaceName = "%s.Hydrophobicity_Charge" % (SubGroupName)
854 HydrophobicChargeSurfaceID = "%sHydrophobicChargeSurface" % (SubGroupID)
855 PyMOLObjectNames["Chains"][ChainID][HydrophobicChargeSurfaceID] = HydrophobicChargeSurfaceName
856 PyMOLObjectNames["Chains"][ChainID][SubGroupMembersID].append(HydrophobicChargeSurfaceName)
857
858 if GetChainAloneSurfaceChainElectrostaticsStatus(FileIndex, ChainID):
859 # Setup electrostatics group...
860 ElectrostaticsGroupName = "%s.Vacuum_Electrostatics" % (SubGroupName)
861 ElectrostaticsGroupID = "%sElectrostaticsGroup" % (SubGroupID)
862 ElectrostaticsGroupMembersID = "%sElectrostaticsGroupMembers" % (SubGroupID)
863
864 PyMOLObjectNames["Chains"][ChainID][ElectrostaticsGroupID] = ElectrostaticsGroupName
865 PyMOLObjectNames["Chains"][ChainID][SubGroupMembersID].append(ElectrostaticsGroupName)
866
867 # Setup electrostatics group members...
868 PyMOLObjectNames["Chains"][ChainID][ElectrostaticsGroupMembersID] = []
869
870 for MemberType in ["Chain", "Contact_Potential", "Map", "Legend"]:
871 MemberID = re.sub("_", "", MemberType)
872
873 Name = "%s.%s" % (ElectrostaticsGroupName, MemberType)
874 NameID = "%s%s" % (ElectrostaticsGroupID, MemberID)
875
876 PyMOLObjectNames["Chains"][ChainID][NameID] = Name
877 PyMOLObjectNames["Chains"][ChainID][ElectrostaticsGroupMembersID].append(Name)
878
879 # Setup solvent and inorganic objects for chain...
880 for NameID in ["Solvent", "Inorganic"]:
881 Name = "%s.%s" % (ChainGroupName, NameID)
882 PyMOLObjectNames["Chains"][ChainID][NameID] = Name
883 PyMOLObjectNames["Chains"][ChainID]["ChainGroupMembers"].append(Name)
884
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 ligand group and its members...
901 GroupName = "%s.Ligand" % (ChainLigandGroupName)
902 GroupNameID = "LigandGroup"
903 GroupMembersID = "LigandGroupMembers"
904
905 PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupNameID] = GroupName
906 PyMOLObjectNames["Ligands"][ChainID][LigandID]["ChainLigandGroupMembers"].append(GroupName)
907
908 LigandName = "%s.Ligand" % (GroupName)
909 LigandNameID = "Ligand"
910 PyMOLObjectNames["Ligands"][ChainID][LigandID][LigandNameID] = LigandName
911
912 PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupMembersID] = []
913 PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupMembersID].append(LigandName)
914
915 # Add ball and stick...
916 BallAndStickName = "%s.BallAndStick" % (GroupName)
917 BallAndStickID = "LigandBallAndStick"
918 PyMOLObjectNames["Ligands"][ChainID][LigandID][BallAndStickID] = BallAndStickName
919 PyMOLObjectNames["Ligands"][ChainID][LigandID][GroupMembersID].append(BallAndStickName)
920
921
922 def RetrieveInfilesInfo():
923 """Retrieve information for input files."""
924
925 InfilesInfo = {}
926
927 InfilesInfo["InfilesNames"] = []
928 InfilesInfo["InfilesRoots"] = []
929 InfilesInfo["ChainsAndLigandsInfo"] = []
930
931 for Infile in OptionsInfo["InfilesNames"]:
932 FileDir, FileName, FileExt = MiscUtil.ParseFileName(Infile)
933 InfileRoot = FileName
934
935 ChainsAndLigandInfo = PyMOLUtil.GetChainsAndLigandsInfo(Infile, InfileRoot)
936
937 InfilesInfo["InfilesNames"].append(Infile)
938 InfilesInfo["InfilesRoots"].append(InfileRoot)
939 InfilesInfo["ChainsAndLigandsInfo"].append(ChainsAndLigandInfo)
940
941 OptionsInfo["InfilesInfo"] = InfilesInfo
942
943
944 def RetrieveRefFileInfo():
945 """Retrieve information for ref file."""
946
947 RefFileInfo = {}
948 if not OptionsInfo["Align"]:
949 OptionsInfo["RefFileInfo"] = RefFileInfo
950 return
951
952 RefFile = OptionsInfo["RefFileName"]
953
954 FileDir, FileName, FileExt = MiscUtil.ParseFileName(RefFile)
955 RefFileRoot = FileName
956
957 if re.match("^FirstInputFile$", OptionsInfo["AlignRefFile"], re.I):
958 ChainsAndLigandInfo = OptionsInfo["InfilesInfo"]["ChainsAndLigandsInfo"][0]
959 else:
960 MiscUtil.PrintInfo("\nRetrieving chain and ligand information for alignment reference file %s..." % RefFile)
961 ChainsAndLigandInfo = PyMOLUtil.GetChainsAndLigandsInfo(RefFile, RefFileRoot)
962
963 RefFileInfo["RefFileName"] = RefFile
964 RefFileInfo["RefFileRoot"] = RefFileRoot
965 RefFileInfo["PyMOLObjectName"] = "AlignRef_%s" % RefFileRoot
966 RefFileInfo["ChainsAndLigandsInfo"] = ChainsAndLigandInfo
967
968 OptionsInfo["RefFileInfo"] = RefFileInfo
969
970
971 def ProcessChainAndLigandIDs():
972 """Process specified chain and ligand IDs for infiles."""
973
974 OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"] = []
975
976 for FileIndex in range(0, len(OptionsInfo["InfilesInfo"]["InfilesNames"])):
977 MiscUtil.PrintInfo(
978 "\nProcessing specified chain and ligand IDs for input file %s..."
979 % OptionsInfo["InfilesInfo"]["InfilesNames"][FileIndex]
980 )
981
982 ChainsAndLigandsInfo = OptionsInfo["InfilesInfo"]["ChainsAndLigandsInfo"][FileIndex]
983 SpecifiedChainsAndLigandsInfo = PyMOLUtil.ProcessChainsAndLigandsOptionsInfo(
984 ChainsAndLigandsInfo, "-c, --chainIDs", OptionsInfo["ChainIDs"], "-l, --ligandIDs", OptionsInfo["LigandIDs"]
985 )
986 ProcessResidueTypesAndSurfaceOptions(FileIndex, SpecifiedChainsAndLigandsInfo)
987 OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"].append(SpecifiedChainsAndLigandsInfo)
988
989 CheckPresenceOfValidLigandIDs(ChainsAndLigandsInfo, SpecifiedChainsAndLigandsInfo)
990
991
992 def ProcessResidueTypesAndSurfaceOptions(FileIndex, SpecifiedChainsAndLigandsInfo):
993 """Process residue types and surface options for chains."""
994
995 SpecifiedChainsAndLigandsInfo["ChainSurfaces"] = {}
996 SpecifiedChainsAndLigandsInfo["SurfaceChain"] = {}
997 SpecifiedChainsAndLigandsInfo["SurfaceChainElectrostatics"] = {}
998
999 SpecifiedChainsAndLigandsInfo["ResidueTypesChain"] = {}
1000
1001 # Load infile...
1002 Infile = OptionsInfo["InfilesInfo"]["InfilesNames"][FileIndex]
1003 MolName = OptionsInfo["InfilesInfo"]["InfilesRoots"][FileIndex]
1004 pymol.cmd.load(Infile, MolName)
1005
1006 for ChainID in SpecifiedChainsAndLigandsInfo["ChainIDs"]:
1007 AminoAcidsPresent = PyMOLUtil.AreAminoAcidResiduesPresent(MolName, ChainID)
1008
1009 # Process surfaces for chains...
1010 if re.match("^auto$", OptionsInfo["SurfaceChain"], re.I):
1011 SurfaceChain = True if AminoAcidsPresent else False
1012 else:
1013 SurfaceChain = True if re.match("^yes$", OptionsInfo["SurfaceChain"], re.I) else False
1014 SpecifiedChainsAndLigandsInfo["SurfaceChain"][ChainID] = SurfaceChain
1015
1016 if re.match("^auto$", OptionsInfo["SurfaceChainElectrostatics"], re.I):
1017 SurfaceChainElectrostatics = True if AminoAcidsPresent else False
1018 else:
1019 SurfaceChainElectrostatics = (
1020 True if re.match("^yes$", OptionsInfo["SurfaceChainElectrostatics"], re.I) else False
1021 )
1022 SpecifiedChainsAndLigandsInfo["SurfaceChainElectrostatics"][ChainID] = SurfaceChainElectrostatics
1023
1024 # A generic color surface is always created...
1025 ChainSurfaces = True
1026 SpecifiedChainsAndLigandsInfo["ChainSurfaces"][ChainID] = ChainSurfaces
1027
1028 # Process residue types for chains...
1029 if re.match("^auto$", OptionsInfo["ResidueTypesChain"], re.I):
1030 ResidueTypesChain = True if AminoAcidsPresent else False
1031 else:
1032 ResidueTypesChain = True if re.match("^yes$", OptionsInfo["ResidueTypesChain"], re.I) else False
1033 SpecifiedChainsAndLigandsInfo["ResidueTypesChain"][ChainID] = ResidueTypesChain
1034
1035 # Delete loaded object...
1036 pymol.cmd.delete(MolName)
1037
1038
1039 def GetChainAloneResidueTypesStatus(FileIndex, ChainID):
1040 """Get status of residue types for chain alone object."""
1041
1042 Status = (
1043 True
1044 if OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"][FileIndex]["ResidueTypesChain"][ChainID]
1045 else False
1046 )
1047
1048 return Status
1049
1050
1051 def GetChainAloneContainsSurfacesStatus(FileIndex, ChainID):
1052 """Get status of surfaces present in chain alone object."""
1053
1054 return OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"][FileIndex]["ChainSurfaces"][ChainID]
1055
1056
1057 def GetChainAloneSurfaceChainStatus(FileIndex, ChainID):
1058 """Get status of hydrophobic surfaces for chain alone object."""
1059
1060 return OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"][FileIndex]["SurfaceChain"][ChainID]
1061
1062
1063 def GetChainAloneSurfaceChainElectrostaticsStatus(FileIndex, ChainID):
1064 """Get status of electrostatics surfaces for chain alone object."""
1065
1066 return OptionsInfo["InfilesInfo"]["SpecifiedChainsAndLigandsInfo"][FileIndex]["SurfaceChainElectrostatics"][ChainID]
1067
1068
1069 def CheckPresenceOfValidLigandIDs(ChainsAndLigandsInfo, SpecifiedChainsAndLigandsInfo):
1070 """Check presence of valid ligand IDs."""
1071
1072 MiscUtil.PrintInfo("\nSpecified chain IDs: %s" % (", ".join(SpecifiedChainsAndLigandsInfo["ChainIDs"])))
1073
1074 for ChainID in SpecifiedChainsAndLigandsInfo["ChainIDs"]:
1075 if len(SpecifiedChainsAndLigandsInfo["LigandIDs"][ChainID]):
1076 MiscUtil.PrintInfo(
1077 "Chain ID: %s; Specified LigandIDs: %s"
1078 % (ChainID, ", ".join(SpecifiedChainsAndLigandsInfo["LigandIDs"][ChainID]))
1079 )
1080 else:
1081 MiscUtil.PrintInfo("Chain IDs: %s; Specified LigandIDs: None" % (ChainID))
1082 MiscUtil.PrintWarning(
1083 "No valid ligand IDs found for chain ID, %s. PyMOL groups and objects related to ligand and binding pockect won't be created."
1084 % (ChainID)
1085 )
1086
1087
1088 def RetrieveFirstChainID(FileIndex):
1089 """Get first chain ID."""
1090
1091 ChainsAndLigandsInfo = OptionsInfo["InfilesInfo"]["ChainsAndLigandsInfo"][FileIndex]
1092
1093 FirstChainID = None
1094 if len(ChainsAndLigandsInfo["ChainIDs"]):
1095 FirstChainID = ChainsAndLigandsInfo["ChainIDs"][0]
1096
1097 return FirstChainID
1098
1099
1100 def ProcessResidueTypes():
1101 """Process residue types."""
1102
1103 ResidueTypesNamesInfo, ResidueTypesParamsInfo = PyMOLUtil.ProcessResidueTypesOptionsInfo(
1104 "-r, --residueTypes", OptionsInfo["ResidueTypes"]
1105 )
1106 OptionsInfo["ResidueTypesNames"] = ResidueTypesNamesInfo
1107 OptionsInfo["ResidueTypesParams"] = ResidueTypesParamsInfo
1108
1109
1110 def ProcessSurfaceAtomTypesColors():
1111 """Process surface atom types colors."""
1112
1113 AtomTypesColorNamesInfo = PyMOLUtil.ProcessSurfaceAtomTypesColorsOptionsInfo(
1114 "--surfaceAtomTypesColors", OptionsInfo["SurfaceAtomTypesColors"]
1115 )
1116 OptionsInfo["AtomTypesColorNames"] = AtomTypesColorNamesInfo
1117
1118
1119 def ProcessOptions():
1120 """Process and validate command line arguments and options."""
1121
1122 MiscUtil.PrintInfo("Processing options...")
1123
1124 # Validate options...
1125 ValidateOptions()
1126
1127 OptionsInfo["Align"] = True if re.match("^Yes$", Options["--align"], re.I) else False
1128 OptionsInfo["AlignMethod"] = Options["--alignMethod"].lower()
1129 OptionsInfo["AlignMode"] = Options["--alignMode"]
1130
1131 OptionsInfo["AllowEmptyObjects"] = True if re.match("^Yes$", Options["--allowEmptyObjects"], re.I) else False
1132
1133 OptionsInfo["CavityCulled"] = True if re.match("^Yes$", Options["--cavityCulled"], re.I) else False
1134 OptionsInfo["SurfaceCavityMode"] = 2 if OptionsInfo["CavityCulled"] else 1
1135
1136 OptionsInfo["CavityCullSize"] = float(Options["--cavityCullSize"])
1137 OptionsInfo["CavityCutoff"] = float(Options["--cavityCutoff"])
1138 OptionsInfo["CavityRadius"] = float(Options["--cavityRadius"])
1139
1140 OptionsInfo["Infiles"] = Options["--infiles"]
1141 OptionsInfo["InfilesNames"] = Options["--infileNames"]
1142
1143 OptionsInfo["AlignRefFile"] = Options["--alignRefFile"]
1144 if re.match("^FirstInputFile$", Options["--alignRefFile"], re.I):
1145 OptionsInfo["RefFileName"] = OptionsInfo["InfilesNames"][0]
1146 else:
1147 OptionsInfo["RefFileName"] = Options["--alignRefFile"]
1148
1149 OptionsInfo["IgnoreHydrogens"] = True if re.match("^Yes$", Options["--ignoreHydrogens"], re.I) else False
1150
1151 OptionsInfo["Overwrite"] = Options["--overwrite"]
1152 OptionsInfo["PMLOut"] = True if re.match("^Yes$", Options["--PMLOut"], re.I) else False
1153
1154 OptionsInfo["Outfile"] = Options["--outfile"]
1155 FileDir, FileName, FileExt = MiscUtil.ParseFileName(OptionsInfo["Outfile"])
1156 OptionsInfo["PSEOut"] = False
1157 if re.match("^pml$", FileExt, re.I):
1158 OptionsInfo["PMLOutfile"] = OptionsInfo["Outfile"]
1159 OptionsInfo["PMEOutfile"] = re.sub(".pml$", ".pme", OptionsInfo["Outfile"])
1160 elif re.match("^pse$", FileExt, re.I):
1161 OptionsInfo["PSEOut"] = True
1162 OptionsInfo["PSEOutfile"] = OptionsInfo["Outfile"]
1163 OptionsInfo["PMLOutfile"] = re.sub(".pse$", ".pml", OptionsInfo["Outfile"])
1164 if os.path.exists(OptionsInfo["PMLOutfile"]) and (not OptionsInfo["Overwrite"]):
1165 MiscUtil.PrintError(
1166 'The intermediate output file to be generated, %s, already exist. Use option "--ov" or "--overwrite" and try again.'
1167 % OptionsInfo["PMLOutfile"]
1168 )
1169
1170 OptionsInfo["LabelFontID"] = int(Options["--labelFontID"])
1171
1172 OptionsInfo["ResidueTypesChain"] = Options["--residueTypesChain"]
1173 OptionsInfo["ResidueTypes"] = Options["--residueTypes"]
1174 ProcessResidueTypes()
1175
1176 OptionsInfo["SurfaceChain"] = Options["--surfaceChain"]
1177 OptionsInfo["SurfaceChainElectrostatics"] = Options["--surfaceChainElectrostatics"]
1178
1179 OptionsInfo["SurfaceChainComplex"] = True if re.match("^Yes$", Options["--surfaceChainComplex"], re.I) else False
1180 OptionsInfo["SurfaceComplex"] = True if re.match("^Yes$", Options["--surfaceComplex"], re.I) else False
1181
1182 # Retrieve surface colors for generic surfaces..
1183 SurfaceColors = re.sub(" ", "", Options["--surfaceColors"])
1184 SurfaceColorsWords = SurfaceColors.split(",")
1185 if len(SurfaceColorsWords) != 2:
1186 MiscUtil.PrintError(
1187 'The number of comma delinited color names, %d, specified using "--surfaceColors" option, "%s", must be a 2.'
1188 % (len(SurfaceColorsWords), Options["--surfaceColors"])
1189 )
1190 OptionsInfo["SurfaceColors"] = SurfaceColors
1191 OptionsInfo["SurfaceCavityColor"] = SurfaceColorsWords[0]
1192 OptionsInfo["SurfaceColor"] = SurfaceColorsWords[1]
1193
1194 OptionsInfo["SurfaceColorPalette"] = Options["--surfaceColorPalette"]
1195 OptionsInfo["SurfaceAtomTypesColors"] = Options["--surfaceAtomTypesColors"]
1196 ProcessSurfaceAtomTypesColors()
1197
1198 OptionsInfo["SurfaceTransparency"] = float(Options["--surfaceTransparency"])
1199
1200 RetrieveInfilesInfo()
1201 RetrieveRefFileInfo()
1202
1203 OptionsInfo["ChainIDs"] = Options["--chainIDs"]
1204 OptionsInfo["LigandIDs"] = Options["--ligandIDs"]
1205
1206 ProcessChainAndLigandIDs()
1207
1208
1209 def RetrieveOptions():
1210 """Retrieve command line arguments and options."""
1211
1212 # Get options...
1213 global Options
1214 Options = docopt(_docoptUsage_)
1215
1216 # Set current working directory to the specified directory...
1217 WorkingDir = Options["--workingdir"]
1218 if WorkingDir:
1219 os.chdir(WorkingDir)
1220
1221 # Handle examples option...
1222 if "--examples" in Options and Options["--examples"]:
1223 MiscUtil.PrintInfo(MiscUtil.GetExamplesTextFromDocOptText(_docoptUsage_))
1224 sys.exit(0)
1225
1226
1227 def ValidateOptions():
1228 """Validate option values."""
1229
1230 MiscUtil.ValidateOptionTextValue("--align", Options["--align"], "yes no")
1231 MiscUtil.ValidateOptionTextValue("--alignMethod", Options["--alignMethod"], "align cealign super")
1232 MiscUtil.ValidateOptionTextValue("--alignMode", Options["--alignMode"], "FirstChain Complex")
1233
1234 MiscUtil.ValidateOptionTextValue("--allowEmptyObjects", Options["--allowEmptyObjects"], "yes no")
1235
1236 MiscUtil.ValidateOptionTextValue("--cavityCulled", Options["--cavityCulled"], "yes no")
1237 MiscUtil.ValidateOptionFloatValue("--cavityCullSize", Options["--cavityCullSize"], {">": 0.0})
1238 MiscUtil.ValidateOptionFloatValue("--cavityCutoff", Options["--cavityCutoff"], {">": 0.0})
1239 MiscUtil.ValidateOptionFloatValue("--cavityRadius", Options["--cavityRadius"], {">": 0.0})
1240
1241 # Expand infiles to handle presence of multiple input files...
1242 InfileNames = MiscUtil.ExpandFileNames(Options["--infiles"], ",")
1243 if not len(InfileNames):
1244 MiscUtil.PrintError('No input files specified for "-i, --infiles" option')
1245
1246 # Validate file extensions...
1247 for Infile in InfileNames:
1248 MiscUtil.ValidateOptionFilePath("-i, --infiles", Infile)
1249 MiscUtil.ValidateOptionFileExt("-i, --infiles", Infile, "pdb cif")
1250 MiscUtil.ValidateOptionsDistinctFileNames("-i, --infiles", Infile, "-o, --outfile", Options["--outfile"])
1251 Options["--infileNames"] = InfileNames
1252
1253 MiscUtil.ValidateOptionFileExt("-o, --outfile", Options["--outfile"], "pml pse")
1254 MiscUtil.ValidateOptionsOutputFileOverwrite(
1255 "-o, --outfile", Options["--outfile"], "--overwrite", Options["--overwrite"]
1256 )
1257
1258 if re.match("^yes$", Options["--align"], re.I):
1259 if not re.match("^FirstInputFile$", Options["--alignRefFile"], re.I):
1260 AlignRefFile = Options["--alignRefFile"]
1261 MiscUtil.ValidateOptionFilePath("--alignRefFile", AlignRefFile)
1262 MiscUtil.ValidateOptionFileExt("--alignRefFile", AlignRefFile, "pdb cif")
1263 MiscUtil.ValidateOptionsDistinctFileNames(
1264 "--AlignRefFile", AlignRefFile, "-o, --outfile", Options["--outfile"]
1265 )
1266
1267 MiscUtil.ValidateOptionTextValue("--ignoreHydrogens", Options["--ignoreHydrogens"], "yes no")
1268
1269 MiscUtil.ValidateOptionTextValue("--PMLOut", Options["--PMLOut"], "yes no")
1270 MiscUtil.ValidateOptionIntegerValue("--labelFontID", Options["--labelFontID"], {})
1271
1272 MiscUtil.ValidateOptionTextValue("--residueTypesChain", Options["--residueTypesChain"], "yes no auto")
1273
1274 MiscUtil.ValidateOptionTextValue("--surfaceChain", Options["--surfaceChain"], "yes no auto")
1275 MiscUtil.ValidateOptionTextValue("--surfaceComplex", Options["--surfaceComplex"], "yes no")
1276 MiscUtil.ValidateOptionTextValue("--surfaceChainComplex", Options["--surfaceChainComplex"], "yes no")
1277 MiscUtil.ValidateOptionTextValue(
1278 "--surfaceChainElectrostatics", Options["--surfaceChainElectrostatics"], "yes no auto"
1279 )
1280
1281 MiscUtil.ValidateOptionTextValue(
1282 "--surfaceColorPalette", Options["--surfaceColorPalette"], "RedToWhite WhiteToGreen"
1283 )
1284 MiscUtil.ValidateOptionFloatValue("--surfaceTransparency", Options["--surfaceTransparency"], {">=": 0.0, "<=": 1.0})
1285
1286
1287 # Setup a usage string for docopt...
1288 _docoptUsage_ = """
1289 PyMOLVisualizeCavities.py - Visualize cavities and pockets in macromolecules
1290
1291 Usage:
1292 PyMOLVisualizeCavities.py [--align <yes or no>] [--alignMethod <align, cealign, super>]
1293 [--alignMode <FirstChain or Complex>] [--alignRefFile <filename>]
1294 [--allowEmptyObjects <yes or no>] [--cavityCulled <Yes or No>]
1295 [--cavityCullSize <number>] [--cavityCutoff <number>] [--cavityRadius <number>]
1296 [--chainIDs <First, All or ID1,ID2...>] [--labelFontID <number>]
1297 [--ignoreHydrogens <yes or no>] [--ligandIDs <Largest, All or ID1,ID2...> ] [--PMLOut <yes or no>]
1298 [--residueTypes <Type,Color,ResNames,...>] [--residueTypesChain <yes or no>]
1299 [--surfaceChain <yes or no>] [--surfaceChainElectrostatics <yes or no>]
1300 [--surfaceChainComplex <yes or no>] [--surfaceComplex <yes or no>]
1301 [--surfaceAtomTypesColors <ColorType,ColorSpec,...>]
1302 [--surfaceColors <ColorName1,ColorName2>] [--surfaceColorPalette <RedToWhite or WhiteToGreen>]
1303 [--surfaceTransparency <number>] [--overwrite] [-w <dir>] -i <infile1,infile2,infile3...> -o <outfile>
1304 PyMOLVisualizeCavities.py -h | --help | -e | --examples
1305
1306 Description:
1307 Generate PyMOL visualization files for viewing cavities and pockets in
1308 macromolecules including proteins and nucleic acids.
1309
1310 The supported input file format are: PDB (.pdb), CIF (.cif)
1311
1312 The supported output file formats are: PyMOL script file (.pml), PyMOL session
1313 file (.pse)
1314
1315 A variety of PyMOL groups and objects may be created for visualization of
1316 cavities and pockets in macromolecules. These groups and objects correspond
1317 to complexes, surfaces, chains, ligands, inorganics, cavities, and pockets.
1318 A complete hierarchy of all possible PyMOL groups and objects is shown below:
1319
1320 <PDBFileRoot>
1321 .Complex
1322 .Complex
1323 .Surface
1324 .Chain<ID>
1325 .Complex
1326 .Complex
1327 .Surface
1328 .Chain
1329 .Chain
1330 .Residues
1331 .Aromatic
1332 .Residues
1333 .Surface
1334 .Hydrophobic
1335 .Residues
1336 .Surface
1337 .Polar
1338 .Residues
1339 .Surface
1340 .Positively_Charged
1341 .Residues
1342 .Surface
1343 .Negatively_Charged
1344 .Residues
1345 .Surface
1346 .Other
1347 .Residues
1348 .Surface
1349 .Cavities
1350 .Surface
1351 .Hydrophobicity
1352 .Hydrophobicity_Charge
1353 .Vacuum_Electrostatics
1354 .Contact_Potentials
1355 .Map
1356 .Legend
1357 .Surface
1358 .Surface
1359 .Hydrophobicity
1360 .Hydrophobicity_Charge
1361 .Vacuum_Electrostatics
1362 .Contact_Potentials
1363 .Map
1364 .Legend
1365 .Solvent
1366 .Inorganic
1367 .Ligand<ID>
1368 .Ligand
1369 .Ligand
1370 .BallAndStick
1371 .Ligand<ID>
1372 .Ligand
1373 ... ... ...
1374 .Chain<ID>
1375 ... ... ...
1376 .Ligand<ID>
1377 ... ... ...
1378 .Ligand<ID>
1379 ... ... ...
1380 .Chain<ID>
1381 ... ... ...
1382 <PDBFileRoot>
1383 .Complex
1384 ... ... ...
1385 .Chain<ID>
1386 ... ... ...
1387 .Ligand<ID>
1388 ... ... ...
1389 .Ligand<ID>
1390 ... ... ...
1391 .Chain<ID>
1392 ... ... ...
1393
1394 The hydrophobic and electrostatic surfaces are not created for complete complex
1395 and chain complex in input file(s) by default. A word to the wise: The creation of
1396 surface objects may slow down loading of PML file and generation of PSE file, based
1397 on the size of input complexes. The generation of PSE file may also fail.
1398
1399 Options:
1400 -a, --align <yes or no> [default: no]
1401 Align input files to a reference file before visualization.
1402 --alignMethod <align, cealign, super> [default: super]
1403 Alignment methodology to use for aligning input files to a
1404 reference file.
1405 --alignMode <FirstChain or Complex> [default: FirstChain]
1406 Portion of input and reference files to use for spatial alignment of
1407 input files against reference file. Possible values: FirstChain or
1408 Complex.
1409
1410 The FirstChain mode allows alignment of the first chain in each input
1411 file to the first chain in the reference file along with moving the rest
1412 of the complex to coordinate space of the reference file. The complete
1413 complex in each input file is aligned to the complete complex in reference
1414 file for the Complex mode.
1415 --alignRefFile <filename> [default: FirstInputFile]
1416 Reference input file name. The default is to use the first input file
1417 name specified using '-i, --infiles' option.
1418 --allowEmptyObjects <yes or no> [default: no]
1419 Allow creation of empty PyMOL objects corresponding to solvent and
1420 inorganic atom selections across chains and ligands in input file(s). By
1421 default, the empty objects are marked for deletion.
1422 --cavityCulled <Yes or No> [default: Yes]
1423 Cull cavities and pockets. The cavities and pockets are culled by default.
1424 This value is used to set of PyMOL parameter surface_cavity_mode as
1425 shown below:
1426
1427 No: 1 (Cavities and Pockets Only)
1428 Yes: 2 (Cavities and Pockets Culled)
1429
1430 --cavityCullSize <number> [default: 2.0]
1431 Approximate dimension of the cavity in Angstroms for detecting cavities and
1432 pockets in the interior of a macromolecule. The higher value makes PyMOL less
1433 sensitive to detection of smaller cavities.
1434 --cavityCutoff <number> [default: 3.0]
1435 Cavity cutoff in terms of number of solvent radii for detecting cavities
1436 and pockets. This value is used to set value of PyMOL parameter
1437 surface_cavity_cutoff.
1438 --cavityRadius <number> [default: 5.0]
1439 Cavity detection radius in terms of number of solvent radii for detecting
1440 cavities and pockets. The detection of larger pockets is ignored for lower
1441 value for the cavity radius. This value is used to set of PyMOL parameter
1442 surface_cavity_radius.
1443 -c, --chainIDs <First, All or ID1,ID2...> [default: First]
1444 List of chain IDs to use for visualizing macromolecules. Possible values:
1445 First, All, or a comma delimited list of chain IDs. The default is to use the
1446 chain ID for the first chain in each input file.
1447 -e, --examples
1448 Print examples.
1449 -h, --help
1450 Print this help message.
1451 -i, --infiles <infile1,infile2,infile3...>
1452 Input file names.
1453 --ignoreHydrogens <yes or no> [default: yes]
1454 Ignore hydrogens for ligand views.
1455 --labelFontID <number> [default: 7]
1456 Font ID for drawing labels. Default: 7 (Sans Bold). Valid values: 5 to 16.
1457 The specified value must be a valid PyMOL font ID. No validation is
1458 performed. The complete lists of valid font IDs is available at:
1459 pymolwiki.org/index.php/Label_font_id. Examples: 5 - Sans;
1460 7 - Sans Bold; 9 - Serif; 10 - Serif Bold.
1461 -l, --ligandIDs <Largest, All or ID1,ID2...> [default: All]
1462 List of ligand IDs to show in chains during visualizing of cavities in
1463 macromolecules. Possible values: Largest, All, or a comma delimited
1464 list of ligand IDs. The default is to show all ligands present in all or
1465 specified chains in each input file.
1466
1467 Ligands are identified using organic selection operator available in PyMOL.
1468 It'll also identify buffer molecules as ligands. The largest ligand contains
1469 the highest number of heavy atoms.
1470 -o, --outfile <outfile>
1471 Output file name.
1472 -p, --PMLOut <yes or no> [default: yes]
1473 Save PML file during generation of PSE file.
1474 -r, --residueTypes <Type,Color,ResNames,...> [default: auto]
1475 Residue types, colors, and names to generate for residue groups during
1476 '--residueTypesChain' option. It is only valid for amino acids.
1477
1478 It is a triplet of comma delimited list of amino acid residues type, residues
1479 color, and a space delimited list three letter residue names.
1480
1481 The default values for residue type, color, and name triplets are shown
1482 below:
1483
1484 Aromatic,brightorange,HIS PHE TRP TYR,
1485 Hydrophobic,orange,ALA GLY VAL LEU ILE PRO MET,
1486 Polar,palegreen,ASN GLN SER THR CYS,
1487 Positively_Charged,marine,ARG LYS,
1488 Negatively_Charged,red,ASP GLU
1489
1490 The color name must be a valid PyMOL name. No validation is performed.
1491 An amino acid name may appear across multiple residue types. All other
1492 residues are grouped under 'Other'.
1493 --residueTypesChain <yes or no> [default: auto]
1494 Chain residue types. The residue groups are generated using residue types,
1495 colors, and names specified by '--residueTypes' option. It is only valid for
1496 amino acids. By default, the residue type groups are automatically created
1497 for chains containing amino acids and skipped for chains only containing
1498 nucleic acids.
1499 --surfaceChain <yes or no> [default: auto]
1500 Surfaces around individual chain colored by hydrophobicity alone and
1501 both hydrophobicity and charge. The hydrophobicity surface is colored
1502 at residue level using Eisenberg hydrophobicity scale for residues and color
1503 gradient specified by '--surfaceColorPalette' option. The hydrophobicity and
1504 charge surface is colored [ Ref 140 ] at atom level using colors specified for
1505 groups of atoms by '--surfaceAtomTypesColors' option. This scheme allows
1506 simultaneous mapping of hyrophobicity and charge values on the surfaces.
1507
1508 This option is only valid for amino acids. By default, both surfaces are
1509 automatically created for chains containing amino acids and skipped for
1510 chains containing only nucleic acids.
1511
1512 In addition, generic surfaces colored by '--surfaceColor' are always created
1513 for chain residues containing amino acids and nucleic acids.
1514 --surfaceChainElectrostatics <yes or no> [default: no]
1515 Vacuum electrostatics contact potential surface around individual
1516 chain. A word to the wise from PyMOL documentation: The computed protein
1517 contact potentials are only qualitatively useful, due to short cutoffs,
1518 truncation, and lack of solvent "screening".
1519
1520 This option is only valid for amino acids. By default, the electrostatics surface
1521 is automatically created for chains containing amino acids and
1522 skipped for chains containing only nucleic acids.
1523 --surfaceChainComplex <yes or no> [default: no]
1524 Hydrophobic surface around chain complex. The surface is colored by
1525 hydrophobicity. It is only valid for amino acids.
1526 --surfaceComplex <yes or no> [default: no]
1527 Hydrophobic surface around complete complex. The surface is colored by
1528 hydrophobicity. It is only valid for amino acids.
1529 --surfaceAtomTypesColors <ColorType,ColorSpec,...> [default: auto]
1530 Atom colors for generating surfaces colored by hyrophobicity and charge
1531 around chains and pockets in proteins. It's a pairwise comma delimited list
1532 of atom color type and color specification for goups of atoms.
1533
1534 The default values for color types [ Ref 140 ] along wth color specifications
1535 are shown below:
1536
1537 HydrophobicAtomsColor, yellow,
1538 NegativelyChargedAtomsColor, red,
1539 PositivelyChargedAtomsColor, blue,
1540 OtherAtomsColor, gray90
1541
1542 The color names must be valid PyMOL names.
1543
1544 The color values may also be specified as space delimited RGB triplets:
1545
1546 HydrophobicAtomsColor, 0.95 0.78 0.0,
1547 NegativelyChargedAtomsColor, 1.0 0.4 0.4,
1548 PositivelyChargedAtomsColor, 0.2 0.5 0.8,
1549 OtherAtomsColor, 0.95 0.95 0.95
1550
1551 --surfaceColors <ColorName1,ColorName2> [default: salmon,lightblue]
1552 Color names for surfaces around cavities and chains. These colors are not
1553 used for surfaces and cavities colored by hydrophobicity and charge. The
1554 color names must be valid PyMOL names.
1555 --surfaceColorPalette <RedToWhite or WhiteToGreen> [default: RedToWhite]
1556 Color palette for hydrophobic surfaces around chains and pockets in proteins.
1557 Possible values: RedToWhite or WhiteToGreen from most hydrophobic amino
1558 acid to least hydrophobic. The colors values for amino acids are taken from
1559 color_h script available as part of the Script Library at PyMOL Wiki.
1560 --surfaceTransparency <number> [default: 0.25]
1561 Surface transparency for molecular surfaces.
1562 --overwrite
1563 Overwrite existing files.
1564 -w, --workingdir <dir>
1565 Location of working directory which defaults to the current directory.
1566
1567 Examples:
1568 To visualize cavities in the first chain along with the largest ligand in the
1569 first chain, solvents, and inorganics, in a PDB file, and generate a PML
1570 file, type:
1571
1572 % PyMOLVisualizeCavities.py -i Sample4.pdb -o Sample4.pml
1573
1574 To visualize cavities in all chain along with all ligands, solvents,
1575 and inorganics, in a PDB file, and generate a PML file, type:
1576
1577 % PyMOLVisualizeCavities.py -c All -l All -i Sample4.pdb
1578 -o Sample4.pml
1579
1580 To visualize cavities in the first chain at a specific cavity radius and cutoff
1581 using specifc colors for surfaces corresponding to cavities and non-cavities,
1582 and generate a PML file, type:
1583
1584 % PyMOLVisualizeCavities.py --cavityRadius 3 --cavityCutoff 5
1585 --surfaceColors "red,blue" -i Sample4.pdb -o Sample4.pml
1586
1587 To visualize cavities in the first chain along with the largest ligand in the
1588 first chain, solvents, and inorganics, in PDB files, along with aligning first
1589 chain in each input file to the first chain inand generate a PML file, type:
1590
1591 % PyMOLVisualizeCavities.py --align yes
1592 -i "Sample5.pdb,Sample6.pdb,Sample7.pdb"
1593 -o SampleOut.pml
1594
1595 Author:
1596 Manish Sud(msud@san.rr.com)
1597
1598 See also:
1599 DownloadPDBFiles.pl, PyMOLVisualizeCryoEMDensity.py,
1600 PyMOLVisualizeElectronDensity.py, PyMOLVisualizeInterfaces.py
1601 PyMOLVisualizeMacromolecules.py, PyMOLVisualizeSurfaceAndBuriedResidues.py
1602
1603 Copyright:
1604 Copyright (C) 2026 Manish Sud. All rights reserved.
1605
1606 The functionality available in this script is implemented using PyMOL, a
1607 molecular visualization system on an open source foundation originally
1608 developed by Warren DeLano.
1609
1610 This file is part of MayaChemTools.
1611
1612 MayaChemTools is free software; you can redistribute it and/or modify it under
1613 the terms of the GNU Lesser General Public License as published by the Free
1614 Software Foundation; either version 3 of the License, or (at your option) any
1615 later version.
1616
1617 """
1618
1619 if __name__ == "__main__":
1620 main()