1 #!/bin/env python
2 #
3 # File: PyMOLVisualizeFpockets.py
4 # Author: Manish Sud <msud@san.rr.com>
5 #
6 # Author: Manish Sud
7 #
8 # Collaborators: Joann Prescott-Roy and Pat Walters
9 #
10 # Copyright (C) 2026 Manish Sud. All rights reserved.
11 #
12 # The functionality available in this script is implemented using PyMOL, a
13 # molecular visualization system on an open source foundation originally
14 # developed by Warren DeLano.
15 #
16 # This file is part of MayaChemTools.
17 #
18 # MayaChemTools is free software; you can redistribute it and/or modify it under
19 # the terms of the GNU Lesser General Public License as published by the Free
20 # Software Foundation; either version 3 of the License, or (at your option) any
21 # later version.
22 #
23 # MayaChemTools is distributed in the hope that it will be useful, but without
24 # any warranty; without even the implied warranty of merchantability of fitness
25 # for a particular purpose. See the GNU Lesser General Public License for more
26 # details.
27 #
28 # You should have received a copy of the GNU Lesser General Public License
29 # along with MayaChemTools; if not, see <http://www.gnu.org/licenses/> or
30 # write to the Free Software Foundation Inc., 59 Temple Place, Suite 330,
31 # Boston, MA, 02111-1307, USA.
32 #
33 #
34
35 from __future__ import print_function
36
37 import os
38 import sys
39 import time
40 import re
41 import glob
42 import shutil
43
44 # PyMOL imports...
45 try:
46 import pymol
47
48 # Finish launching PyMOL in a command line mode for batch processing (-c)
49 # along with the following options: disable loading of pymolrc and plugins (-k);
50 # suppress start up messages (-q)
51 pymol.finish_launching(["pymol", "-ckq"])
52 except ImportError as ErrMsg:
53 sys.stderr.write("\nFailed to import PyMOL module/package: %s\n" % ErrMsg)
54 sys.stderr.write("Check/update your PyMOL environment and try again.\n\n")
55 sys.exit(1)
56
57 # MayaChemTools imports...
58 sys.path.insert(0, os.path.join(os.path.dirname(sys.argv[0]), "..", "lib", "Python"))
59 try:
60 from docopt import docopt
61 import MiscUtil
62 import PyMOLUtil
63 except ImportError as ErrMsg:
64 sys.stderr.write("\nFailed to import MayaChemTools module/package: %s\n" % ErrMsg)
65 sys.stderr.write("Check/update your MayaChemTools environment and try again.\n\n")
66 sys.exit(1)
67
68 ScriptName = os.path.basename(sys.argv[0])
69 Options = {}
70 OptionsInfo = {}
71
72
73 def main():
74 """Start execution of the script"""
75
76 MiscUtil.PrintInfo(
77 "\n%s (PyMOL v%s; MayaChemTools v%s; %s): Starting...\n"
78 % (ScriptName, pymol.cmd.get_version()[0], MiscUtil.GetMayaChemToolsVersion(), time.asctime())
79 )
80
81 (WallClockTime, ProcessorTime) = MiscUtil.GetWallClockAndProcessorTime()
82
83 # Retrieve command line arguments and options...
84 RetrieveOptions()
85
86 # Process and validate command line arguments and options...
87 ProcessOptions()
88
89 # Perform actions required by the script...
90 GenerateFpocketsVisualization()
91
92 MiscUtil.PrintInfo("\n%s: Done...\n" % ScriptName)
93 MiscUtil.PrintInfo("Total time: %s" % MiscUtil.GetFormattedElapsedTime(WallClockTime, ProcessorTime))
94
95
96 def GenerateFpocketsVisualization():
97 """Generate fpockets visualization."""
98
99 Outfile = OptionsInfo["PMLOutfilePath"]
100 OutFH = open(Outfile, "w")
101 if OutFH is None:
102 MiscUtil.PrintError("Failed to open output fie %s " % Outfile)
103
104 MiscUtil.PrintInfo("\nGenerating file %s..." % Outfile)
105
106 # Setup header...
107 WritePMLHeader(OutFH, ScriptName)
108 WritePyMOLParameters(OutFH)
109
110 if OptionsInfo["Align"]:
111 WriteAlignReference(OutFH)
112
113 # Setup view for each input file...
114 FirstComplex = True
115 FirstComplexFirstChainName = None
116 for FileIndex in range(0, len(OptionsInfo["InfilesInfo"]["InfilesNames"])):
117 # Setup PyMOL object names...
118 PyMOLObjectNames = SetupPyMOLObjectNames(FileIndex)
119
120 # Setup complex view...
121 WriteComplexView(OutFH, FileIndex, PyMOLObjectNames, FirstComplex)
122
123 # Setup chain and pocket views...
124 SpecifiedChainsAndPocketsInfo = OptionsInfo["FpocketInfilesInfo"]["SpecifiedChainsAndPocketsInfo"][FileIndex]
125 FirstChain = True
126 for ChainID in SpecifiedChainsAndPocketsInfo["ChainIDs"]:
127 if FirstComplex and FirstChain:
128 FirstComplexFirstChainName = PyMOLObjectNames["Chains"][ChainID]["ChainAlone"]
129
130 WriteChainView(OutFH, FileIndex, PyMOLObjectNames, ChainID)
131
132 # Setup fpocket views...
133 FirstPocket = True
134 PocketNum = 0
135 for PocketID in SpecifiedChainsAndPocketsInfo["PocketIDs"][ChainID]:
136 PocketNum += 1
137 WriteChainPocketView(OutFH, FileIndex, PyMOLObjectNames, ChainID, PocketID, PocketNum)
138
139 # Set up pocket level group...
140 Enable, Action = [False, "close"]
141 if FirstPocket:
142 FirstPocket = False
143 Enable, Action = [True, "open"]
144 GenerateAndWritePMLForGroup(
145 OutFH,
146 PyMOLObjectNames["Pockets"][ChainID][PocketID]["ChainPocketGroup"],
147 PyMOLObjectNames["Pockets"][ChainID][PocketID]["ChainPocketGroupMembers"],
148 Enable,
149 Action,
150 )
151
152 # Setup Chain level group...
153 Enable, Action = [False, "close"]
154 if FirstChain:
155 FirstChain = False
156 Enable, Action = [True, "open"]
157 GenerateAndWritePMLForGroup(
158 OutFH,
159 PyMOLObjectNames["Chains"][ChainID]["ChainGroup"],
160 PyMOLObjectNames["Chains"][ChainID]["ChainGroupMembers"],
161 Enable,
162 Action,
163 )
164
165 # Set up complex level group...
166 Enable, Action = [False, "close"]
167 if FirstComplex:
168 FirstComplex = False
169 Enable, Action = [True, "open"]
170 GenerateAndWritePMLForGroup(
171 OutFH, PyMOLObjectNames["PDBGroup"], PyMOLObjectNames["PDBGroupMembers"], Enable, Action
172 )
173
174 if OptionsInfo["Align"]:
175 DeleteAlignReference(OutFH)
176
177 if FirstComplexFirstChainName is not None:
178 OutFH.write("""\ncmd.orient("%s", animate = -1)\n""" % FirstComplexFirstChainName)
179 else:
180 OutFH.write("""\ncmd.orient("visible", animate = -1)\n""")
181
182 OutFH.close()
183
184 CopyPDBFilesForPML()
185
186
187 def WritePMLHeader(OutFH, ScriptName):
188 """Write out PML header."""
189
190 HeaderInfo = PyMOLUtil.SetupPMLHeaderInfo(ScriptName)
191 OutFH.write("%s\n" % HeaderInfo)
192
193
194 def WritePyMOLParameters(OutFH):
195 """Write out PyMOL global parameters."""
196
197 PMLCmds = []
198 PMLCmds.append("""cmd.set("transparency", %.2f, "", 0)""" % (OptionsInfo["SurfaceTransparency"]))
199 PMLCmds.append("""cmd.set("label_font_id", %s)""" % (OptionsInfo["LabelFontID"]))
200 PML = "\n".join(PMLCmds)
201
202 OutFH.write("""\n""\n"Setting up PyMOL gobal parameters..."\n""\n""")
203 OutFH.write("%s\n" % PML)
204
205
206 def WriteAlignReference(OutFH):
207 """Setup object for alignment reference"""
208
209 RefFileInfo = OptionsInfo["RefFileInfo"]
210 RefFile = RefFileInfo["RefFileName"]
211 RefName = RefFileInfo["PyMOLObjectName"]
212
213 PMLCmds = []
214 PMLCmds.append("""cmd.load("%s", "%s")""" % (RefFile, RefName))
215 PMLCmds.append("""cmd.hide("everything", "%s")""" % (RefName))
216 PMLCmds.append("""cmd.disable("%s")""" % (RefName))
217 PML = "\n".join(PMLCmds)
218
219 OutFH.write("""\n""\n"Loading %s and setting up view for align reference..."\n""\n""" % RefFile)
220 OutFH.write("%s\n" % PML)
221
222
223 def WriteAlignComplex(OutFH, FileIndex, FpocketComplexMode, PyMOLObjectNames):
224 """Setup alignment of complex to reference"""
225
226 RefFileInfo = OptionsInfo["RefFileInfo"]
227 RefName = RefFileInfo["PyMOLObjectName"]
228
229 if FpocketComplexMode:
230 ComplexName = PyMOLObjectNames["FpocketComplex"]
231 else:
232 ComplexName = PyMOLObjectNames["InitialComplex"]
233
234 if re.match("^FirstChain$", OptionsInfo["AlignMode"], re.I):
235 RefFirstChainID = RefFileInfo["ChainsAndLigandsInfo"]["ChainIDs"][0]
236 RefAlignSelection = "%s and chain %s" % (RefName, RefFirstChainID)
237
238 ComplexFirstChainID = RetrieveFirstChainID(FileIndex, FpocketComplexMode)
239 ComplexAlignSelection = "%s and chain %s" % (ComplexName, ComplexFirstChainID)
240 else:
241 RefAlignSelection = RefName
242 ComplexAlignSelection = ComplexName
243
244 PML = PyMOLUtil.SetupPMLForAlignment(OptionsInfo["AlignMethod"], RefAlignSelection, ComplexAlignSelection)
245 OutFH.write("""\n""\n"Aligning %s against reference %s ..."\n""\n""" % (ComplexAlignSelection, RefAlignSelection))
246 OutFH.write("%s\n" % PML)
247
248
249 def DeleteAlignReference(OutFH):
250 """Delete alignment reference object."""
251
252 RefName = OptionsInfo["RefFileInfo"]["PyMOLObjectName"]
253 OutFH.write("""\n""\n"Deleting alignment reference object %s..."\n""\n""" % RefName)
254 OutFH.write("""cmd.delete("%s")\n""" % RefName)
255
256
257 def WriteComplexView(OutFH, FileIndex, PyMOLObjectNames, FirstComplex):
258 """Write out PML for viewing polymer complex."""
259
260 # Setup initial complex...
261 Infile = OptionsInfo["InfilesInfo"]["InfilesNames"][FileIndex]
262 PML = PyMOLUtil.SetupPMLForPolymerComplexView(PyMOLObjectNames["InitialComplex"], Infile, True)
263 OutFH.write("""\n""\n"Loading %s and setting up view for complex..."\n""\n""" % Infile)
264 OutFH.write("%s\n" % PML)
265
266 if OptionsInfo["Align"]:
267 # No need to align initial complex on to itself...
268 FpocketComplexMode = False
269 if not (re.match("^FirstInputFile$", OptionsInfo["AlignRefFile"], re.I) and FirstComplex):
270 WriteAlignComplex(OutFH, FileIndex, FpocketComplexMode, PyMOLObjectNames)
271
272 # Setup fpocket complex...
273 Infile = OptionsInfo["FpocketInfilesInfo"]["InfilesNames"][FileIndex]
274 PML = PyMOLUtil.SetupPMLForPolymerComplexView(PyMOLObjectNames["FpocketComplex"], Infile, True)
275
276 # Modify default complex view for fpocket complex...
277 PMLModify = SetupPMLModifyDefaultPolymerComplexView(PyMOLObjectNames["FpocketComplex"])
278
279 OutFH.write("""\n""\n"Loading %s and setting up view for complex..."\n""\n""" % Infile)
280 OutFH.write("%s\n%s\n" % (PML, PMLModify))
281
282 if OptionsInfo["Align"]:
283 # No need to align initial complex on to itself...
284 FpocketComplexMode = True
285 if not (re.match("^FirstInputFile$", OptionsInfo["AlignRefFile"], re.I) and FirstComplex):
286 WriteAlignComplex(OutFH, FileIndex, FpocketComplexMode, PyMOLObjectNames)
287
288 # Setup complex group...
289 GenerateAndWritePMLForGroup(
290 OutFH, PyMOLObjectNames["ComplexGroup"], PyMOLObjectNames["ComplexGroupMembers"], False, "close"
291 )
292
293
294 def WriteChainView(OutFH, FileIndex, PyMOLObjectNames, ChainID):
295 """Write out PML for viewing chain."""
296
297 OutFH.write("""\n""\n"Setting up views for chain %s..."\n""\n""" % ChainID)
298
299 # Setup chain complex group view...
300 WriteChainComplexViews(OutFH, FileIndex, PyMOLObjectNames, ChainID)
301
302 # Setup chain view...
303 WriteChainAloneViews(OutFH, FileIndex, PyMOLObjectNames, ChainID)
304
305
306 def WriteChainComplexViews(OutFH, FileIndex, PyMOLObjectNames, ChainID):
307 """Write chain complex views."""
308
309 # Setup chain complex...
310 ChainComplexName = PyMOLObjectNames["Chains"][ChainID]["ChainComplex"]
311 PML = SetupPMLForFpocketChainComplexView(
312 FileIndex, ChainComplexName, PyMOLObjectNames["FpocketComplex"], ChainID, True
313 )
314
315 # Modify default complex view for fpocket chain complex...
316 PMLModify = SetupPMLModifyDefaultPolymerComplexView(ChainComplexName)
317 OutFH.write("%s\n%s\n" % (PML, PMLModify))
318
319 # Setup chain complex group...
320 GenerateAndWritePMLForGroup(
321 OutFH,
322 PyMOLObjectNames["Chains"][ChainID]["ChainComplexGroup"],
323 PyMOLObjectNames["Chains"][ChainID]["ChainComplexGroupMembers"],
324 False,
325 "close",
326 )
327
328
329 def WriteChainAloneViews(OutFH, FileIndex, PyMOLObjectNames, ChainID):
330 """Write individual chain views."""
331
332 ChainComplexName = PyMOLObjectNames["Chains"][ChainID]["ChainComplex"]
333
334 # Setup chain view...
335 ChainName = PyMOLObjectNames["Chains"][ChainID]["ChainAlone"]
336 PML = PyMOLUtil.SetupPMLForPolymerChainView(ChainName, ChainComplexName, True)
337 OutFH.write("\n%s\n" % PML)
338
339 if GetChainAloneContainsSurfacesStatus(FileIndex, ChainID):
340 # Setup a generic color surface...
341 PML = PyMOLUtil.SetupPMLForSurfaceView(
342 PyMOLObjectNames["Chains"][ChainID]["ChainAloneSurface"],
343 ChainName,
344 Enable=False,
345 Color=OptionsInfo["SurfaceColor"],
346 )
347 OutFH.write("\n%s\n" % PML)
348
349 if GetChainAloneSurfaceChainStatus(FileIndex, ChainID):
350 # Setup surface colored by hydrophobicity...
351 PML = PyMOLUtil.SetupPMLForHydrophobicSurfaceView(
352 PyMOLObjectNames["Chains"][ChainID]["ChainAloneHydrophobicSurface"],
353 ChainName,
354 ColorPalette=OptionsInfo["SurfaceColorPalette"],
355 Enable=False,
356 )
357 OutFH.write("\n%s\n" % PML)
358
359 # Setup surface colored by hyrdophobicity and charge...
360 PML = PyMOLUtil.SetupPMLForHydrophobicAndChargeSurfaceView(
361 PyMOLObjectNames["Chains"][ChainID]["ChainAloneHydrophobicChargeSurface"],
362 ChainName,
363 OptionsInfo["AtomTypesColorNames"]["HydrophobicAtomsColor"],
364 OptionsInfo["AtomTypesColorNames"]["NegativelyChargedAtomsColor"],
365 OptionsInfo["AtomTypesColorNames"]["PositivelyChargedAtomsColor"],
366 OptionsInfo["AtomTypesColorNames"]["OtherAtomsColor"],
367 Enable=False,
368 DisplayAs=None,
369 )
370 OutFH.write("\n%s\n" % PML)
371
372 # Setup surface group...
373 GenerateAndWritePMLForGroup(
374 OutFH,
375 PyMOLObjectNames["Chains"][ChainID]["ChainAloneSurfaceGroup"],
376 PyMOLObjectNames["Chains"][ChainID]["ChainAloneSurfaceGroupMembers"],
377 True,
378 "open",
379 )
380
381 # Setup chain group...
382 GenerateAndWritePMLForGroup(
383 OutFH,
384 PyMOLObjectNames["Chains"][ChainID]["ChainAloneGroup"],
385 PyMOLObjectNames["Chains"][ChainID]["ChainAloneGroupMembers"],
386 True,
387 "close",
388 )
389
390
391 def WriteChainPocketView(OutFH, FileIndex, PyMOLObjectNames, ChainID, PocketID, PocketNum):
392 """Write out PML for viewing pocket in a chain."""
393
394 OutFH.write("""\n""\n"Setting up views for pocket %s in chain %s..."\n""\n""" % (PocketID, ChainID))
395
396 FpocketComplexName = PyMOLObjectNames["FpocketComplex"]
397
398 # Setup pocket...
399 PML = SetupPMLForFPocketView(
400 PyMOLObjectNames["Pockets"][ChainID][PocketID]["Pocket"], FpocketComplexName, ChainID, PocketID, PocketNum, True
401 )
402 OutFH.write("%s\n" % PML)
403
404 # Setup pocket residues...
405 ChainsAndPocketsInfo = OptionsInfo["FpocketInfilesInfo"]["ChainsAndPocketsInfo"][FileIndex]
406 PocketResNums = ChainsAndPocketsInfo["PocketResNums"][ChainID][PocketID]
407 PocketResiduesName = PyMOLObjectNames["Pockets"][ChainID][PocketID]["PocketResidues"]
408 PML = SetupPMLForFPocketResiduesView(
409 PocketResiduesName, FpocketComplexName, ChainID, PocketID, PocketNum, PocketResNums, True
410 )
411 OutFH.write("%s\n" % PML)
412
413 # Setup pocket surfaces and group...
414 if GetPocketContainsSurfaceStatus(FileIndex, ChainID, PocketID):
415 # Setup a generic color surface...
416 PML = PyMOLUtil.SetupPMLForSurfaceView(
417 PyMOLObjectNames["Pockets"][ChainID][PocketID]["PocketSurface"],
418 PocketResiduesName,
419 Enable=False,
420 Color=OptionsInfo["SurfaceColor"],
421 )
422 OutFH.write("\n%s\n" % PML)
423
424 if GetPocketSurfaceChainStatus(FileIndex, ChainID, PocketID):
425 # Setup surface colored by hydrophobicity...
426 PML = PyMOLUtil.SetupPMLForHydrophobicSurfaceView(
427 PyMOLObjectNames["Pockets"][ChainID][PocketID]["PocketHydrophobicitySurface"],
428 PocketResiduesName,
429 ColorPalette=OptionsInfo["SurfaceColorPalette"],
430 Enable=False,
431 )
432 OutFH.write("\n%s\n" % PML)
433
434 # Setup surface colored by hyrdophobicity and charge...
435 PML = PyMOLUtil.SetupPMLForHydrophobicAndChargeSurfaceView(
436 PyMOLObjectNames["Pockets"][ChainID][PocketID]["PocketHydrophobicityChargeSurface"],
437 PocketResiduesName,
438 OptionsInfo["AtomTypesColorNames"]["HydrophobicAtomsColor"],
439 OptionsInfo["AtomTypesColorNames"]["NegativelyChargedAtomsColor"],
440 OptionsInfo["AtomTypesColorNames"]["PositivelyChargedAtomsColor"],
441 OptionsInfo["AtomTypesColorNames"]["OtherAtomsColor"],
442 Enable=False,
443 DisplayAs=None,
444 )
445 OutFH.write("\n%s\n" % PML)
446
447 # Setup surface group...
448 GenerateAndWritePMLForGroup(
449 OutFH,
450 PyMOLObjectNames["Pockets"][ChainID][PocketID]["PocketSurfaceGroup"],
451 PyMOLObjectNames["Pockets"][ChainID][PocketID]["PocketSurfaceGroupMembers"],
452 True,
453 "open",
454 )
455
456 # Setup pocket group...
457 GenerateAndWritePMLForGroup(
458 OutFH,
459 PyMOLObjectNames["Pockets"][ChainID][PocketID]["ChainPocketGroup"],
460 PyMOLObjectNames["Pockets"][ChainID][PocketID]["ChainPocketGroupMembers"],
461 True,
462 "open",
463 )
464
465
466 def SetupPMLForFpocketChainComplexView(FileIndex, Name, Selection, ChainName, Enable=True):
467 """Setup PML commands for creating a polymer chain complex view
468 including fockets for the chain."""
469
470 PMLCmds = []
471
472 # Include fpockets as spheres for the chain complex view...
473 ChainsAndPocketsInfo = OptionsInfo["FpocketInfilesInfo"]["ChainsAndPocketsInfo"][FileIndex]
474 PocketIDs = ChainsAndPocketsInfo["PocketIDs"][ChainName]
475
476 PMLCmds.append(
477 """cmd.create("%s", "((%s and chain %s) or (%s and (resn STP and resi %s)))")"""
478 % (Name, Selection, ChainName, Selection, "+".join(PocketIDs))
479 )
480 PMLCmds.append("""cmd.hide("everything", "%s")""" % (Name))
481 PMLCmds.append("""cmd.show("cartoon", "%s")""" % (Name))
482 PMLCmds.append("""util.cba(33, "%s", _self = cmd)""" % (Name))
483 PMLCmds.append("""cmd.show("sticks", "(organic and (%s))")""" % (Name))
484
485 PMLCmds.append("""cmd.show("nonbonded", "(solvent and (%s))")""" % (Name))
486 PMLCmds.append("""cmd.show("nonbonded", "(inorganic and (%s))")""" % (Name))
487
488 PMLCmds.append("""cmd.show("lines", "%s")""" % (Name))
489
490 PMLCmds.append("""cmd.set_bond("valence", "1", "%s", quiet = 1)""" % (Name))
491 PMLCmds.append(PyMOLUtil.SetupPMLForEnableDisable(Name, Enable))
492
493 PML = "\n".join(PMLCmds)
494
495 return PML
496
497
498 def SetupPMLModifyDefaultPolymerComplexView(Name):
499 """Setup PML to modify default polymer complex view for fpocket."""
500
501 PMLCmds = []
502 PMLCmds.append("""cmd.hide("lines", "%s")""" % (Name))
503 PMLCmds.append("""cmd.show("lines", "(polymer and (%s))")""" % (Name))
504 PMLCmds.append("""cmd.show("lines", "(solvent and (%s))")""" % (Name))
505 PMLCmds.append("""cmd.show("spheres", "(inorganic and (%s))")""" % (Name))
506 PMLCmds.append("""cmd.set("sphere_scale", "%s", "(inorganic and (%s))")""" % (OptionsInfo["SphereScale"], Name))
507 PMLCmds.append(
508 """cmd.set("sphere_transparency", "%s", "(inorganic and (%s))")""" % (OptionsInfo["SphereTransparency"], Name)
509 )
510
511 PML = "\n".join(PMLCmds)
512
513 return PML
514
515
516 def SetupPMLForFPocketView(FpocketName, FpocketComplexName, ChainID, PocketID, PocketNum, Enable=True):
517 """Setup PML to visualize fpocket spheres using fpocket complex."""
518
519 PMLCmds = []
520 PMLCmds.append(
521 """cmd.create("%s", "(%s and (resn STP and resi %s))")""" % (FpocketName, FpocketComplexName, PocketID)
522 )
523 if PocketNum == 1:
524 # Skip color index of 1: It is set to black. Use pocket one color name...
525 PMLCmds.append("""cmd.color(%s, "%s")""" % (OptionsInfo["PocketNumOneColor"], FpocketName))
526 else:
527 PMLCmds.append("""cmd.color(%s, "%s")""" % (PocketNum, FpocketName))
528 PMLCmds.append("""cmd.show("spheres", "%s")""" % (FpocketName))
529 PMLCmds.append("""cmd.set("sphere_scale", "%s", "%s")""" % (OptionsInfo["SphereScale"], FpocketName))
530 PMLCmds.append("""cmd.set("sphere_transparency", "%s", "%s")""" % (OptionsInfo["SphereTransparency"], FpocketName))
531
532 PMLCmds.append(PyMOLUtil.SetupPMLForEnableDisable(FpocketName, Enable))
533
534 PML = "\n".join(PMLCmds)
535 return PML
536
537
538 def SetupPMLForFPocketResiduesView(Name, FpocketComplexName, ChainID, PocketID, PocketNum, PocketResNums, Enable=True):
539 """Setup PML to visualize fpocket residues."""
540
541 PMLCmds = []
542
543 PMLCmds.append(
544 """cmd.create("%s", "(%s and (chain %s) and (resi %s))")"""
545 % (Name, FpocketComplexName, ChainID, "+".join(PocketResNums))
546 )
547 PMLCmds.append("""cmd.hide("everything", "%s")""" % (Name))
548
549 # Setup pocket residue labels...
550 if OptionsInfo["PocketLabel"]:
551 if OptionsInfo["ThreeLetterPocketLabelType"]:
552 LabelFormat = """"%s-%s"%(resn,resi)"""
553 PMLCmds.append("""cmd.label("(name CA+C1*+C1' and (byres(%s)))", \'\'\'%s\'\'\')""" % (Name, LabelFormat))
554 else:
555 PMLCmds.append("""cmd.label("byca(%s)", "oneletter+resi")""" % (Name))
556
557 PocketColor = OptionsInfo["PocketNumOneColor"] if PocketNum == 1 else PocketNum
558
559 if OptionsInfo["PocketColorByPocketNum"]:
560 # Setup color of pocket residues...
561 PMLCmds.append(PyMOLUtil.SetupPMLForDeepColoring(Name, PocketColor))
562
563 # Setup color of pocket residue labels...
564 PMLCmds.append("""cmd.set("label_color", %s, "%s")""" % (PocketColor, Name))
565 else:
566 PMLCmds.append("""util.cbag("%s", _self = cmd)""" % (Name))
567
568 PMLCmds.append("""cmd.show("lines", "%s")""" % (Name))
569
570 PMLCmds.append(PyMOLUtil.SetupPMLForEnableDisable(Name, Enable))
571
572 PML = "\n".join(PMLCmds)
573 return PML
574
575
576 def GenerateAndWritePMLForGroup(OutFH, GroupName, GroupMembers, Enable=False, Action="close"):
577 """Generate and write PML for group."""
578
579 PML = PyMOLUtil.SetupPMLForGroup(GroupName, GroupMembers, Enable, Action)
580 OutFH.write("""\n""\n"Setting up group %s..."\n""\n""" % GroupName)
581 OutFH.write("%s\n" % PML)
582
583
584 def WritePMLToCheckAndDeleteEmptyObjects(OutFH, ObjectName, ParentObjectName=None):
585 """Write PML to check and delete empty PyMOL objects."""
586
587 if ParentObjectName is None:
588 PML = """CheckAndDeleteEmptyObjects("%s")""" % (ObjectName)
589 else:
590 PML = """CheckAndDeleteEmptyObjects("%s", "%s")""" % (ObjectName, ParentObjectName)
591
592 OutFH.write("%s\n" % PML)
593
594
595 def SetupPyMOLObjectNames(FileIndex):
596 """Setup hierarchy of PyMOL groups and objects for pocket centric views of
597 chains and pockets present in input file.
598 """
599
600 PyMOLObjectNames = {}
601 PyMOLObjectNames["Chains"] = {}
602 PyMOLObjectNames["Pockets"] = {}
603
604 # Setup groups and objects for complex...
605 SetupPyMOLObjectNamesForComplex(FileIndex, PyMOLObjectNames)
606
607 # Setup groups and objects for chains using fpockets info...
608 SpecifiedChainsAndPocketsInfo = OptionsInfo["FpocketInfilesInfo"]["SpecifiedChainsAndPocketsInfo"][FileIndex]
609 for ChainID in SpecifiedChainsAndPocketsInfo["ChainIDs"]:
610 SetupPyMOLObjectNamesForChain(FileIndex, PyMOLObjectNames, ChainID)
611
612 # Setup groups and objects for pocket...
613 for PocketID in SpecifiedChainsAndPocketsInfo["PocketIDs"][ChainID]:
614 SetupPyMOLObjectNamesForPocket(FileIndex, PyMOLObjectNames, ChainID, PocketID)
615
616 return PyMOLObjectNames
617
618
619 def SetupPyMOLObjectNamesForComplex(FileIndex, PyMOLObjectNames):
620 """Setup groups and objects for complex."""
621
622 PDBFileRoot = OptionsInfo["InfilesInfo"]["InfilesRoots"][FileIndex]
623
624 PDBGroupName = "%s" % PDBFileRoot
625 PyMOLObjectNames["PDBGroup"] = PDBGroupName
626 PyMOLObjectNames["PDBGroupMembers"] = []
627
628 ComplexGroupName = "%s.Complex" % PyMOLObjectNames["PDBGroup"]
629 PyMOLObjectNames["ComplexGroup"] = ComplexGroupName
630 PyMOLObjectNames["ComplexGroupMembers"] = []
631
632 PyMOLObjectNames["PDBGroupMembers"].append(ComplexGroupName)
633
634 PyMOLObjectNames["InitialComplex"] = "%s.Initial_Complex" % ComplexGroupName
635 PyMOLObjectNames["FpocketComplex"] = "%s.Fpocket_Complex" % ComplexGroupName
636
637 PyMOLObjectNames["ComplexGroupMembers"].append(PyMOLObjectNames["InitialComplex"])
638 PyMOLObjectNames["ComplexGroupMembers"].append(PyMOLObjectNames["FpocketComplex"])
639
640
641 def SetupPyMOLObjectNamesForChain(FileIndex, PyMOLObjectNames, ChainID):
642 """Setup groups and objects for chain."""
643
644 PDBGroupName = PyMOLObjectNames["PDBGroup"]
645
646 PyMOLObjectNames["Chains"][ChainID] = {}
647 PyMOLObjectNames["Pockets"][ChainID] = {}
648
649 # Set up chain group and chain objects...
650 ChainGroupName = "%s.Chain%s" % (PDBGroupName, ChainID)
651 PyMOLObjectNames["Chains"][ChainID]["ChainGroup"] = ChainGroupName
652 PyMOLObjectNames["PDBGroupMembers"].append(ChainGroupName)
653 PyMOLObjectNames["Chains"][ChainID]["ChainGroupMembers"] = []
654
655 # Setup chain complex group and objects...
656 ChainComplexGroupName = "%s.Complex" % (ChainGroupName)
657 PyMOLObjectNames["Chains"][ChainID]["ChainComplexGroup"] = ChainComplexGroupName
658 PyMOLObjectNames["Chains"][ChainID]["ChainGroupMembers"].append(ChainComplexGroupName)
659
660 PyMOLObjectNames["Chains"][ChainID]["ChainComplexGroupMembers"] = []
661
662 Name = "%s.Complex" % (ChainComplexGroupName)
663 PyMOLObjectNames["Chains"][ChainID]["ChainComplex"] = Name
664 PyMOLObjectNames["Chains"][ChainID]["ChainComplexGroupMembers"].append(Name)
665
666 # Setup up a group for individual chains...
667 ChainAloneGroupName = "%s.Chain" % (ChainGroupName)
668 PyMOLObjectNames["Chains"][ChainID]["ChainAloneGroup"] = ChainAloneGroupName
669 PyMOLObjectNames["Chains"][ChainID]["ChainGroupMembers"].append(ChainAloneGroupName)
670
671 PyMOLObjectNames["Chains"][ChainID]["ChainAloneGroupMembers"] = []
672
673 Name = "%s.Chain" % (ChainAloneGroupName)
674 PyMOLObjectNames["Chains"][ChainID]["ChainAlone"] = Name
675 PyMOLObjectNames["Chains"][ChainID]["ChainAloneGroupMembers"].append(Name)
676
677 if GetChainAloneContainsSurfacesStatus(FileIndex, ChainID):
678 # Setup a surface group and add it to chain alone group...
679 SurfaceGroupName = "%s.Surface" % (ChainAloneGroupName)
680 PyMOLObjectNames["Chains"][ChainID]["ChainAloneSurfaceGroup"] = SurfaceGroupName
681 PyMOLObjectNames["Chains"][ChainID]["ChainAloneGroupMembers"].append(SurfaceGroupName)
682
683 PyMOLObjectNames["Chains"][ChainID]["ChainAloneSurfaceGroupMembers"] = []
684
685 # Setup a generic color surface...
686 Name = "%s.Surface" % (SurfaceGroupName)
687 PyMOLObjectNames["Chains"][ChainID]["ChainAloneSurface"] = Name
688 PyMOLObjectNames["Chains"][ChainID]["ChainAloneSurfaceGroupMembers"].append(Name)
689
690 if GetChainAloneSurfaceChainStatus(FileIndex, ChainID):
691 # Setup hydrophobicity surface...
692 Name = "%s.Hydrophobicity" % (SurfaceGroupName)
693 PyMOLObjectNames["Chains"][ChainID]["ChainAloneHydrophobicSurface"] = Name
694 PyMOLObjectNames["Chains"][ChainID]["ChainAloneSurfaceGroupMembers"].append(Name)
695
696 # Setup hydrophobicity and charge surface...
697 Name = "%s.Hydrophobicity_Charge" % (SurfaceGroupName)
698 PyMOLObjectNames["Chains"][ChainID]["ChainAloneHydrophobicChargeSurface"] = Name
699 PyMOLObjectNames["Chains"][ChainID]["ChainAloneSurfaceGroupMembers"].append(Name)
700
701
702 def SetupPyMOLObjectNamesForPocket(FileIndex, PyMOLObjectNames, ChainID, PocketID):
703 """Stetup groups and objects for pocket."""
704
705 PyMOLObjectNames["Pockets"][ChainID][PocketID] = {}
706
707 ChainGroupName = PyMOLObjectNames["Chains"][ChainID]["ChainGroup"]
708
709 # Setup a chain level pocket group...
710 ChainPocketGroupName = SetupChainPocketGroupName(FileIndex, ChainGroupName, ChainID, PocketID)
711
712 PyMOLObjectNames["Pockets"][ChainID][PocketID]["ChainPocketGroup"] = ChainPocketGroupName
713 PyMOLObjectNames["Chains"][ChainID]["ChainGroupMembers"].append(ChainPocketGroupName)
714
715 PyMOLObjectNames["Pockets"][ChainID][PocketID]["ChainPocketGroupMembers"] = []
716
717 # Setup fpocket...
718 Name = "%s.Fpocket" % (ChainPocketGroupName)
719 PyMOLObjectNames["Pockets"][ChainID][PocketID]["Pocket"] = Name
720 PyMOLObjectNames["Pockets"][ChainID][PocketID]["ChainPocketGroupMembers"].append(Name)
721
722 # Setup fpocket residues...
723 Name = "%s.Residues" % (ChainPocketGroupName)
724 PyMOLObjectNames["Pockets"][ChainID][PocketID]["PocketResidues"] = Name
725 PyMOLObjectNames["Pockets"][ChainID][PocketID]["ChainPocketGroupMembers"].append(Name)
726
727 if GetPocketContainsSurfaceStatus(FileIndex, ChainID, PocketID):
728 # Setup a pocket surface group and add it to chain pocket group
729 SurfaceGroupName = "%s.Surface" % (ChainPocketGroupName)
730 PyMOLObjectNames["Pockets"][ChainID][PocketID]["PocketSurfaceGroup"] = SurfaceGroupName
731 PyMOLObjectNames["Pockets"][ChainID][PocketID]["ChainPocketGroupMembers"].append(SurfaceGroupName)
732
733 PyMOLObjectNames["Pockets"][ChainID][PocketID]["PocketSurfaceGroupMembers"] = []
734
735 # Setup a generic color surface...
736 Name = "%s.Surface" % (SurfaceGroupName)
737 PyMOLObjectNames["Pockets"][ChainID][PocketID]["PocketSurface"] = Name
738 PyMOLObjectNames["Pockets"][ChainID][PocketID]["PocketSurfaceGroupMembers"].append(Name)
739
740 if GetPocketSurfaceChainStatus(FileIndex, ChainID, PocketID):
741 # Surface colored by hydrophobicity...
742 Name = "%s.Hydrophobicity" % (SurfaceGroupName)
743 PyMOLObjectNames["Pockets"][ChainID][PocketID]["PocketHydrophobicitySurface"] = Name
744 PyMOLObjectNames["Pockets"][ChainID][PocketID]["PocketSurfaceGroupMembers"].append(Name)
745
746 # Surface colored by hydrophobicity and charge...
747 Name = "%s.Hydrophobicity_Charge" % (SurfaceGroupName)
748 PyMOLObjectNames["Pockets"][ChainID][PocketID]["PocketHydrophobicityChargeSurface"] = Name
749 PyMOLObjectNames["Pockets"][ChainID][PocketID]["PocketSurfaceGroupMembers"].append(Name)
750
751
752 def SetupChainPocketGroupName(FileIndex, ChainGroupName, ChainID, PocketID):
753 """Setup pocket group PyMOL object name."""
754
755 ChainPocketGroupName = "%s.Fpocket%s" % (ChainGroupName, PocketID)
756
757 if not OptionsInfo["FpocketPropertiesAppend"]:
758 return ChainPocketGroupName
759
760 PocketPropertiesName = SetupFpocketPropertiesForGroupName(FileIndex, ChainGroupName, ChainID, PocketID)
761
762 ChainPocketGroupName = "%s_%s" % (ChainPocketGroupName, PocketPropertiesName)
763
764 return ChainPocketGroupName
765
766
767 def SetupFpocketPropertiesForGroupName(FileIndex, ChainGroupName, ChainID, PocketID):
768 """Setup fpocket properties for PyMOL group name."""
769
770 ChainsAndPocketsInfo = OptionsInfo["FpocketInfilesInfo"]["ChainsAndPocketsInfo"][FileIndex]
771
772 PocketScore = FormatFpocketPropertyForGroupName(ChainsAndPocketsInfo["PocketScore"][ChainID][PocketID])
773 DrugScore = FormatFpocketPropertyForGroupName(ChainsAndPocketsInfo["DrugScore"][ChainID][PocketID])
774 HydrophobicityScore = FormatFpocketPropertyForGroupName(
775 ChainsAndPocketsInfo["HydrophobicityScore"][ChainID][PocketID]
776 )
777 PolarityScore = FormatFpocketPropertyForGroupName(ChainsAndPocketsInfo["PolarityScore"][ChainID][PocketID])
778 PocketVolume = FormatFpocketPropertyForGroupName(ChainsAndPocketsInfo["PocketVolume"][ChainID][PocketID])
779
780 PocketProperties = "S%s_D%s_V%s_H%s_P%s" % (
781 PocketScore,
782 DrugScore,
783 PocketVolume,
784 HydrophobicityScore,
785 PolarityScore,
786 )
787
788 return PocketProperties
789
790
791 def FormatFpocketPropertyForGroupName(PocketProperty):
792 """Format fpocket property for PyMOL group name."""
793
794 if PocketProperty is None:
795 PocketProperty = "NA"
796 else:
797 PocketProperty = "%.2f" % float(PocketProperty)
798 PocketProperty = re.sub(r"\.", "p", PocketProperty)
799 PocketProperty = re.sub("^-", "neg", PocketProperty)
800
801 return PocketProperty
802
803
804 def GetChainAloneContainsSurfacesStatus(FileIndex, ChainID):
805 """Get status of surfaces present in chain alone object."""
806
807 # Always set up generic color surfaces...
808 return True
809
810
811 def GetChainAloneSurfaceChainStatus(FileIndex, ChainID):
812 """Get status of surfaces for chain alone object."""
813
814 return OptionsInfo["SurfaceChain"]
815
816
817 def GetPocketContainsSurfaceStatus(FileIndex, ChainID, PocketID):
818 """Get status of surfaces present in a pocket object."""
819
820 # Always set up generic color surfaces...
821 return True
822
823
824 def GetPocketSurfaceChainStatus(FileIndex, ChainID, PocketID):
825 """Get status of surfaces for pocket object."""
826
827 return OptionsInfo["PocketSurface"]
828
829
830 def CopyPDBFilesForPML():
831 """Copy appropriate PDB files for PyMOL to OutfilesDir"""
832
833 OutfilesDir = OptionsInfo["OutfilesDir"]
834
835 MiscUtil.PrintInfo("\nCopying appropriate PDB files to directory %s..." % OutfilesDir)
836
837 # Copy input PDB files...
838 for FileIndex in range(0, len(OptionsInfo["InfilesInfo"]["InfilesNames"])):
839 Infile = OptionsInfo["InfilesInfo"]["InfilesNames"][FileIndex]
840 NewInfilePath = os.path.join(OutfilesDir, Infile)
841
842 shutil.copyfile(Infile, NewInfilePath)
843
844 # Copy fpocket output PDB files...
845 for FileIndex in range(0, len(OptionsInfo["FpocketInfilesInfo"]["InfilesNames"])):
846 Infile = OptionsInfo["FpocketInfilesInfo"]["InfilesNames"][FileIndex]
847 InfilePath = OptionsInfo["FpocketInfilesInfo"]["InfilesPaths"][FileIndex]
848 NewInfilePath = os.path.join(OutfilesDir, Infile)
849
850 shutil.copyfile(InfilePath, NewInfilePath)
851
852
853 def RetrieveInfilesInfo():
854 """Retrieve information for input files."""
855
856 InfilesInfo = {}
857
858 InfilesInfo["InfilesNames"] = []
859 InfilesInfo["InfilesRoots"] = []
860 InfilesInfo["ChainsAndLigandsInfo"] = []
861
862 for Infile in OptionsInfo["InfilesNames"]:
863 FileDir, FileName, FileExt = MiscUtil.ParseFileName(Infile)
864 InfileRoot = FileName
865
866 ChainsAndLigandInfo = PyMOLUtil.GetChainsAndLigandsInfo(Infile, InfileRoot)
867
868 InfilesInfo["InfilesNames"].append(Infile)
869 InfilesInfo["InfilesRoots"].append(InfileRoot)
870 InfilesInfo["ChainsAndLigandsInfo"].append(ChainsAndLigandInfo)
871
872 OptionsInfo["InfilesInfo"] = InfilesInfo
873
874
875 def RetrieveRefFileInfo():
876 """Retrieve information for ref file."""
877
878 RefFileInfo = {}
879 if not OptionsInfo["Align"]:
880 OptionsInfo["RefFileInfo"] = RefFileInfo
881 return
882
883 RefFile = OptionsInfo["RefFileName"]
884
885 FileDir, FileName, FileExt = MiscUtil.ParseFileName(RefFile)
886 RefFileRoot = FileName
887
888 if re.match("^FirstInputFile$", OptionsInfo["AlignRefFile"], re.I):
889 ChainsAndLigandInfo = OptionsInfo["InfilesInfo"]["ChainsAndLigandsInfo"][0]
890 else:
891 MiscUtil.PrintInfo("\nRetrieving chain and ligand information for alignment reference file %s..." % RefFile)
892 ChainsAndLigandInfo = PyMOLUtil.GetChainsAndLigandsInfo(RefFile, RefFileRoot)
893
894 RefFileInfo["RefFileName"] = RefFile
895 RefFileInfo["RefFileRoot"] = RefFileRoot
896 RefFileInfo["PyMOLObjectName"] = "AlignRef_%s" % RefFileRoot
897 RefFileInfo["ChainsAndLigandsInfo"] = ChainsAndLigandInfo
898
899 OptionsInfo["RefFileInfo"] = RefFileInfo
900
901
902 def RetrieveFpocketResultFilesInfo():
903 """Check and retrieve information for Fpocket result files."""
904
905 FpocketInfilesInfo = {}
906
907 FpocketInfilesInfo["InfilesNames"] = []
908 FpocketInfilesInfo["InfilesRoots"] = []
909 FpocketInfilesInfo["InfilesPaths"] = []
910 FpocketInfilesInfo["InfilesDirs"] = []
911
912 FpocketInfilesInfo["InfilesPocketsDirs"] = []
913 FpocketInfilesInfo["InfilesPocketsPDBFilesCount"] = []
914
915 FpocketInfilesInfo["ChainsAndPocketsInfo"] = []
916
917 for Infile in OptionsInfo["InfilesNames"]:
918 MiscUtil.PrintInfo("\nRetrieving Fpocket result file information for input file %s..." % Infile)
919
920 FileDir, FileName, FileExt = MiscUtil.ParseFileName(Infile)
921 InfileRoot = FileName
922
923 FpocketInfileDir = "%s_out" % InfileRoot
924 FpocketInfileRoot = "%s_out" % InfileRoot
925 FpocketInfileName = "%s.pdb" % FpocketInfileRoot
926 FpocketInfilePath = os.path.join(FpocketInfileDir, FpocketInfileName)
927
928 FpocketInfilePocketsDir = os.path.join(FpocketInfileDir, "pockets")
929
930 if not os.path.isdir(FpocketInfileDir):
931 MiscUtil.PrintError(
932 "Fpocket result file directory, %s, is missing for input PDB file, %s." % (FpocketInfileDir, Infile)
933 )
934
935 if not os.path.isfile(FpocketInfilePath):
936 MiscUtil.PrintError(
937 "Fpocket result PDB file, %s, is missing for input PDB file, %s." % (FpocketInfilePath, Infile)
938 )
939
940 if not os.path.isdir(FpocketInfilePocketsDir):
941 MiscUtil.PrintError(
942 "Fpocket pockets result file directory, %s, is missing for input PDB file, %s."
943 % (FpocketInfilePocketsDir, Infile)
944 )
945
946 PocketsPDBFiles = glob.glob(os.path.join(FpocketInfilePocketsDir, "pocket*_atm.pdb"))
947 PocketsPDBFilesCount = len(PocketsPDBFiles)
948 if PocketsPDBFilesCount == 0:
949 MiscUtil.PrintError(
950 "Fpocket pockets result files missing in directory, %s, for input PDB file, %s."
951 % (FpocketInfilePocketsDir, Infile)
952 )
953
954 # Retrieve chains and pockets...
955 ChainsAndPocketsInfo = GetFpocketChainsAndPocketsInfo(
956 FpocketInfileRoot, FpocketInfilePath, FpocketInfileDir, FpocketInfilePocketsDir
957 )
958
959 FpocketInfilesInfo["InfilesNames"].append(FpocketInfileName)
960 FpocketInfilesInfo["InfilesRoots"].append(FpocketInfileRoot)
961 FpocketInfilesInfo["InfilesPaths"].append(FpocketInfilePath)
962 FpocketInfilesInfo["InfilesDirs"].append(FpocketInfileDir)
963
964 FpocketInfilesInfo["InfilesPocketsDirs"].append(FpocketInfilePocketsDir)
965 FpocketInfilesInfo["InfilesPocketsPDBFilesCount"].append(PocketsPDBFilesCount)
966
967 FpocketInfilesInfo["ChainsAndPocketsInfo"].append(ChainsAndPocketsInfo)
968
969 MiscUtil.PrintInfo("PDB result file: %s..." % FpocketInfileName)
970 MiscUtil.PrintInfo("Total number of pockets: %s..." % ChainsAndPocketsInfo["NumOfPockets"])
971
972 MiscUtil.PrintInfo("Pocket Chain IDs: %s" % " ".join(ChainsAndPocketsInfo["ChainIDs"]))
973 for ChainID in ChainsAndPocketsInfo["ChainIDs"]:
974 MiscUtil.PrintInfo(
975 "Pocket Chain ID: %s; NumOfPockets: %s; PocketIDs: %s"
976 % (
977 ChainID,
978 len(ChainsAndPocketsInfo["PocketIDs"][ChainID]),
979 " ".join(ChainsAndPocketsInfo["PocketIDs"][ChainID]),
980 )
981 )
982
983 OptionsInfo["FpocketInfilesInfo"] = FpocketInfilesInfo
984
985
986 def GetFpocketChainsAndPocketsInfo(FpocketInfileRoot, FpocketInfilePath, FpocketInfileDir, FpocketInfilePocketsDir):
987 """Get chains and pockets information for Fpocket result files."""
988
989 ChainsAndPocketsInfo = {}
990 ChainsAndPocketsInfo["ChainIDs"] = []
991 ChainsAndPocketsInfo["PocketIDs"] = {}
992 ChainsAndPocketsInfo["PocketResNums"] = {}
993
994 ChainsAndPocketsInfo["DrugScore"] = {}
995 ChainsAndPocketsInfo["PocketScore"] = {}
996 ChainsAndPocketsInfo["HydrophobicityScore"] = {}
997 ChainsAndPocketsInfo["PolarityScore"] = {}
998 ChainsAndPocketsInfo["PocketVolume"] = {}
999
1000 ChainsAndPocketsInfo["NumOfPockets"] = 0
1001
1002 # Retrieve number of pockets and pocket IDs...
1003 PocketIDs = GetPocketIDs(FpocketInfilePath, FpocketInfileRoot)
1004 ChainsAndPocketsInfo["NumOfPockets"] = len(PocketIDs)
1005
1006 # Retrieve residue numbers for fpockets across the chains...
1007 for PocketID in PocketIDs:
1008 PocketAtomFile = os.path.join(FpocketInfilePocketsDir, "pocket%s_atm.pdb" % PocketID)
1009
1010 if not os.path.isfile(PocketAtomFile):
1011 MiscUtil.PrintError(
1012 "Fpocket result PDB file, %s, is missing for pocket ID, %s." % (PocketAtomFile, PocketID)
1013 )
1014
1015 # Retrieve pocket properites for a pocket across chains...
1016 PocketScore, DrugScore, HydrophobicityScore, PolarityScore, PocketVolume = GetPocketProperties(PocketAtomFile)
1017
1018 MolName = "pocket%s_atm" % PocketID
1019 pymol.cmd.load(PocketAtomFile, MolName)
1020 SelectionCmd = "(%s)" % MolName
1021
1022 pymol.stored.FpocketInfo = []
1023 pymol.cmd.iterate(SelectionCmd, "pymol.stored.FpocketInfo.append([chain, resi, resn])")
1024 pymol.cmd.delete(MolName)
1025
1026 for ChainID, ResNum, ResName in pymol.stored.FpocketInfo:
1027 if ChainID not in ChainsAndPocketsInfo["ChainIDs"]:
1028 ChainsAndPocketsInfo["PocketIDs"][ChainID] = []
1029 ChainsAndPocketsInfo["PocketResNums"][ChainID] = {}
1030
1031 ChainsAndPocketsInfo["DrugScore"][ChainID] = {}
1032 ChainsAndPocketsInfo["PocketScore"][ChainID] = {}
1033 ChainsAndPocketsInfo["HydrophobicityScore"][ChainID] = {}
1034 ChainsAndPocketsInfo["PolarityScore"][ChainID] = {}
1035 ChainsAndPocketsInfo["PocketVolume"][ChainID] = {}
1036
1037 ChainsAndPocketsInfo["ChainIDs"].append(ChainID)
1038
1039 if PocketID not in ChainsAndPocketsInfo["PocketIDs"][ChainID]:
1040 ChainsAndPocketsInfo["PocketResNums"][ChainID][PocketID] = []
1041 ChainsAndPocketsInfo["PocketIDs"][ChainID].append(PocketID)
1042
1043 # Track pocket and drug score across chains...
1044 ChainsAndPocketsInfo["DrugScore"][ChainID][PocketID] = DrugScore
1045 ChainsAndPocketsInfo["PocketScore"][ChainID][PocketID] = PocketScore
1046 ChainsAndPocketsInfo["HydrophobicityScore"][ChainID][PocketID] = HydrophobicityScore
1047 ChainsAndPocketsInfo["PolarityScore"][ChainID][PocketID] = PolarityScore
1048 ChainsAndPocketsInfo["PocketVolume"][ChainID][PocketID] = PocketVolume
1049
1050 if ResNum not in ChainsAndPocketsInfo["PocketResNums"][ChainID][PocketID]:
1051 ChainsAndPocketsInfo["PocketResNums"][ChainID][PocketID].append(ResNum)
1052
1053 ChainsAndPocketsInfo["ChainIDs"] = sorted(ChainsAndPocketsInfo["ChainIDs"])
1054
1055 return ChainsAndPocketsInfo
1056
1057
1058 def GetPolymerChainIDs(Infile, MolName):
1059 """Get chain IDs for main chain excluding hetero atoms."""
1060
1061 pymol.cmd.load(Infile, MolName)
1062 ChainIDs = PyMOLUtil.GetChains(MolName)
1063
1064 # Retrieve polymer chains...
1065 SelectedChainIDs = []
1066 for ChainID in ChainIDs:
1067 AtomsCount = pymol.cmd.count_atoms("(%s and (chain %s) and (polymer) and (not hetatm))" % (MolName, ChainID))
1068 if AtomsCount > 0:
1069 SelectedChainIDs.append(ChainID)
1070
1071 pymol.cmd.delete(MolName)
1072
1073 return SelectedChainIDs
1074
1075
1076 def GetPocketIDs(Infile, MolName):
1077 """Get pocket IDs."""
1078
1079 # Fpockets are annonated in PDB file as STP residue name and unique residue
1080 # numbers...
1081 pymol.cmd.load(Infile, MolName)
1082 SelectionCmd = "(%s and (resn STP) and hetatm)" % MolName
1083
1084 pymol.stored.FpocketIDsInfo = []
1085 pymol.cmd.iterate(SelectionCmd, "pymol.stored.FpocketIDsInfo.append(resi)")
1086 pymol.cmd.delete(MolName)
1087
1088 PocketIDs = []
1089 for PocketID in pymol.stored.FpocketIDsInfo:
1090 if PocketID not in PocketIDs:
1091 PocketIDs.append(PocketID)
1092
1093 return PocketIDs
1094
1095
1096 def ProcessChainAndPocketIDs():
1097 """Process specified chain and pocket IDs for infiles."""
1098
1099 OptionsInfo["FpocketInfilesInfo"]["SpecifiedChainsAndPocketsInfo"] = []
1100
1101 for FileIndex in range(0, len(OptionsInfo["InfilesInfo"]["InfilesNames"])):
1102 MiscUtil.PrintInfo(
1103 "\nProcessing specified chain and Pocket IDs for input file %s..."
1104 % OptionsInfo["FpocketInfilesInfo"]["InfilesNames"][FileIndex]
1105 )
1106
1107 ChainsAndPocketsInfo = OptionsInfo["FpocketInfilesInfo"]["ChainsAndPocketsInfo"][FileIndex]
1108
1109 SpecifiedChainsAndPocketsInfo = ProcessChainsAndPocketsOptionsInfo(ChainsAndPocketsInfo)
1110 OptionsInfo["FpocketInfilesInfo"]["SpecifiedChainsAndPocketsInfo"].append(SpecifiedChainsAndPocketsInfo)
1111
1112 CheckPresenceOfValidPocketIDs(ChainsAndPocketsInfo, SpecifiedChainsAndPocketsInfo)
1113
1114
1115 def GetPocketProperties(PocketAtomFile):
1116 """Get pocket properites from the pocket PDB file."""
1117
1118 PocketScore, DrugScore, HydrophobicityScore, PolarityScore, PocketVolume = [None] * 5
1119
1120 PocketAtomFH = open(PocketAtomFile, "r")
1121 if PocketAtomFH is None:
1122 return (PocketScore, DrugScore, HydrophobicityScore, PolarityScore, PocketVolume)
1123
1124 for Line in PocketAtomFH:
1125 Line = Line.rstrip()
1126 if re.search("Pocket Score", Line, re.I):
1127 LineWords = Line.split()
1128 PocketScore = LineWords[-1]
1129 elif re.search("Drug Score", Line, re.I):
1130 LineWords = Line.split()
1131 DrugScore = LineWords[-1]
1132 elif re.search("Hydrophobicity Score", Line, re.I):
1133 LineWords = Line.split()
1134 HydrophobicityScore = LineWords[-1]
1135 elif re.search("Polarity Score", Line, re.I):
1136 LineWords = Line.split()
1137 PolarityScore = LineWords[-1]
1138 elif re.search(r"Pocket volume \(Monte Carlo\)", Line, re.I):
1139 LineWords = Line.split()
1140 PocketVolume = LineWords[-1]
1141
1142 if not re.match("^HEADER", Line, re.I):
1143 break
1144
1145 PocketAtomFH.close()
1146
1147 return (PocketScore, DrugScore, HydrophobicityScore, PolarityScore, PocketVolume)
1148
1149
1150 def ProcessChainsAndPocketsOptionsInfo(ChainsAndPocketsInfo):
1151 """Process specified chain and pocket IDs using command line options."""
1152
1153 SpecifiedChainsAndPocketsInfo = {}
1154 SpecifiedChainsAndPocketsInfo["ChainIDs"] = []
1155 SpecifiedChainsAndPocketsInfo["PocketIDs"] = {}
1156
1157 ProcessChainsOptionInfo(ChainsAndPocketsInfo, SpecifiedChainsAndPocketsInfo)
1158 ProcessPocketsOptionInfo(ChainsAndPocketsInfo, SpecifiedChainsAndPocketsInfo)
1159
1160 return SpecifiedChainsAndPocketsInfo
1161
1162
1163 def ProcessChainsOptionInfo(ChainsAndPocketsInfo, SpecifiedChainsAndPocketsInfo):
1164 """Process chain IDs"""
1165
1166 MiscUtil.PrintInfo("Processing chain IDs...")
1167
1168 ChainsOptionName = "-c, --chainIDs"
1169 ChainsOptionValue = OptionsInfo["ChainIDs"]
1170
1171 if re.match("^All$", ChainsOptionValue, re.I):
1172 SpecifiedChainsAndPocketsInfo["ChainIDs"] = ChainsAndPocketsInfo["ChainIDs"]
1173 return
1174 elif re.match("^(First|Auto)$", ChainsOptionValue, re.I):
1175 FirstChainID = ChainsAndPocketsInfo["ChainIDs"][0] if (len(ChainsAndPocketsInfo["ChainIDs"])) else None
1176 if FirstChainID is not None:
1177 SpecifiedChainsAndPocketsInfo["ChainIDs"].append(FirstChainID)
1178 return
1179
1180 ChainIDs = re.sub(" ", "", ChainsOptionValue)
1181 if not ChainIDs:
1182 MiscUtil.PrintError('No valid value specified using "%s" option.' % ChainsOptionName)
1183
1184 ChainIDsList = ChainsAndPocketsInfo["ChainIDs"]
1185 SpecifiedChainIDsList = []
1186
1187 ChainIDsWords = ChainIDs.split(",")
1188 for ChainID in ChainIDsWords:
1189 if ChainID not in ChainIDsList:
1190 MiscUtil.PrintWarning(
1191 'The chain ID, %s, specified using "%s" option is not valid. It\'ll be ignored. Valid chain IDs: %s'
1192 % (ChainID, ChainsOptionName, ", ".join(ChainIDsList))
1193 )
1194 continue
1195 if ChainID in SpecifiedChainIDsList:
1196 MiscUtil.PrintWarning(
1197 'The chain ID, %s, has already been specified using "%s" option. It\'ll be ignored.'
1198 % (ChainID, ChainsOptionName)
1199 )
1200 continue
1201 SpecifiedChainIDsList.append(ChainID)
1202
1203 if not len(SpecifiedChainIDsList):
1204 MiscUtil.PrintError(
1205 'No valid chain IDs "%s" specified using "%s" option.' % (ChainsOptionValue, ChainsOptionName)
1206 )
1207
1208 SpecifiedChainsAndPocketsInfo["ChainIDs"] = SpecifiedChainIDsList
1209
1210
1211 def ProcessPocketsOptionInfo(ChainsAndPocketsInfo, SpecifiedChainsAndPocketsInfo):
1212 """Process pocket IDs"""
1213
1214 MiscUtil.PrintInfo("Processing pocket IDs...")
1215
1216 PocketsModeOptionValue = OptionsInfo["FpocketMode"]
1217
1218 PocketsIDsOptionName = "--fpocketIDs"
1219 PocketsIDsOptionValue = OptionsInfo["FpocketIDs"]
1220
1221 # Intialize pocketIDs...
1222 for ChainID in SpecifiedChainsAndPocketsInfo["ChainIDs"]:
1223 SpecifiedChainsAndPocketsInfo["PocketIDs"][ChainID] = []
1224
1225 if re.match("^All$", PocketsModeOptionValue, re.I):
1226 for ChainID in SpecifiedChainsAndPocketsInfo["ChainIDs"]:
1227 SpecifiedChainsAndPocketsInfo["PocketIDs"][ChainID] = ChainsAndPocketsInfo["PocketIDs"][ChainID]
1228 return
1229 elif re.match("^TopN$", PocketsModeOptionValue, re.I):
1230 # Setup TopN pocket IDs for each chain...
1231 TopNPocketsCount = int(PocketsIDsOptionValue[0])
1232 for ChainID in SpecifiedChainsAndPocketsInfo["ChainIDs"]:
1233 TopNPocketsIDs = []
1234 NumOfPockets = len(ChainsAndPocketsInfo["PocketIDs"][ChainID])
1235
1236 if NumOfPockets:
1237 if TopNPocketsCount > NumOfPockets:
1238 TopNPocketsIDs = ChainsAndPocketsInfo["PocketIDs"][ChainID]
1239 else:
1240 TopNPocketsIDs = ChainsAndPocketsInfo["PocketIDs"][ChainID][0:TopNPocketsCount]
1241
1242 SpecifiedChainsAndPocketsInfo["PocketIDs"][ChainID] = TopNPocketsIDs
1243 return
1244
1245 # Process explicitly specified pocket IDs...
1246 PocketIDsWords = PocketsIDsOptionValue
1247 if not len(PocketIDsWords):
1248 MiscUtil.PrintError('No valid value specified using "%s" option.' % PocketsIDsOptionName)
1249
1250 for ChainID in SpecifiedChainsAndPocketsInfo["ChainIDs"]:
1251 PocketIDsList = ChainsAndPocketsInfo["PocketIDs"][ChainID]
1252 SpecifiedPocketIDsList = []
1253
1254 for PocketID in PocketIDsWords:
1255 if PocketID not in PocketIDsList:
1256 MiscUtil.PrintWarning(
1257 'The pocket ID, %s, specified using "%s" option is not valid for chain, %s. It\'ll be ignored. Valid pocket IDs are listed earlier.'
1258 % (PocketID, PocketsIDsOptionName, ChainID)
1259 )
1260 continue
1261
1262 if PocketID in SpecifiedPocketIDsList:
1263 MiscUtil.PrintWarning(
1264 'The pocket ID, %s, has already been specified using "%s" option. It\'ll be ignored.'
1265 % (PocketID, PocketsIDsOptionName)
1266 )
1267 continue
1268
1269 SpecifiedPocketIDsList.append(PocketID)
1270
1271 if not len(SpecifiedPocketIDsList):
1272 MiscUtil.PrintWarning(
1273 'No valid pocket IDs "%s" specified using "%s" option for chain ID, %s.'
1274 % (PocketsIDsOptionValue, PocketsIDsOptionName, ChainID)
1275 )
1276
1277 SpecifiedChainsAndPocketsInfo["PocketIDs"][ChainID] = SpecifiedPocketIDsList
1278
1279
1280 def CheckPresenceOfValidPocketIDs(ChainsAndPocketsInfo, SpecifiedChainsAndPocketsInfo):
1281 """Check presence of valid pocket IDs."""
1282
1283 MiscUtil.PrintInfo("\nSpecified chain IDs: %s" % (", ".join(SpecifiedChainsAndPocketsInfo["ChainIDs"])))
1284
1285 for ChainID in SpecifiedChainsAndPocketsInfo["ChainIDs"]:
1286 if len(SpecifiedChainsAndPocketsInfo["PocketIDs"][ChainID]):
1287 MiscUtil.PrintInfo(
1288 "Chain ID: %s; Specified PocketIDs: %s"
1289 % (ChainID, ", ".join(SpecifiedChainsAndPocketsInfo["PocketIDs"][ChainID]))
1290 )
1291 else:
1292 MiscUtil.PrintInfo("Chain IDs: %s; Specified PocketIDs: None" % (ChainID))
1293 MiscUtil.PrintWarning(
1294 "No valid pocket IDs found for chain ID, %s. PyMOL groups and objects related to fpockets won't be created."
1295 % (ChainID)
1296 )
1297
1298
1299 def RetrieveFirstChainID(FileIndex, FpocketComplexMode):
1300 """Get first chain ID."""
1301
1302 FirstChainID = None
1303 if FpocketComplexMode:
1304 ChainsAndPocketsInfo = OptionsInfo["FpocketInfilesInfo"]["ChainsAndPocketsInfo"][FileIndex]
1305 if len(ChainsAndPocketsInfo["ChainIDs"]):
1306 FirstChainID = ChainsAndPocketsInfo["ChainIDs"][0]
1307 else:
1308 ChainsAndLigandsInfo = OptionsInfo["InfilesInfo"]["ChainsAndLigandsInfo"][FileIndex]
1309 if len(ChainsAndLigandsInfo["ChainIDs"]):
1310 FirstChainID = ChainsAndLigandsInfo["ChainIDs"][0]
1311
1312 return FirstChainID
1313
1314
1315 def ProcessSurfaceAtomTypesColors():
1316 """Process surface atom types colors."""
1317
1318 AtomTypesColorNamesInfo = PyMOLUtil.ProcessSurfaceAtomTypesColorsOptionsInfo(
1319 "--surfaceAtomTypesColors", OptionsInfo["SurfaceAtomTypesColors"]
1320 )
1321 OptionsInfo["AtomTypesColorNames"] = AtomTypesColorNamesInfo
1322
1323
1324 def CheckAndSetupOutfilesDir():
1325 """Check and setup a directory for output files used by PyMOL."""
1326
1327 Outfile = Options["--outfile"]
1328 OutfilesDir = Options["--outfilesDir"]
1329
1330 FileDir, FileName, FileExt = MiscUtil.ParseFileName(Outfile)
1331 if re.match("^auto$", OutfilesDir, re.I):
1332 OutfilesDir = "%s_out_PyMOL" % FileName
1333
1334 if os.path.isdir(OutfilesDir):
1335 if not OptionsInfo["Overwrite"]:
1336 MiscUtil.PrintError(
1337 'The output directory, %s, already exists. Use option "--ov" or "--overwrite" and try again.'
1338 % OutfilesDir
1339 )
1340 MiscUtil.PrintInfo("Using existing outout dir %s..." % OutfilesDir)
1341 else:
1342 MiscUtil.PrintInfo("Creating new output dir %s..." % OutfilesDir)
1343 os.mkdir(OutfilesDir)
1344
1345 OptionsInfo["Outfile"] = Outfile
1346 OptionsInfo["OutfilesDir"] = OutfilesDir
1347
1348 OptionsInfo["PMLOutfile"] = Outfile
1349 OptionsInfo["PMLOutfilePath"] = os.path.join(OutfilesDir, Outfile)
1350
1351
1352 def ProcessOptions():
1353 """Process and validate command line arguments and options"""
1354
1355 MiscUtil.PrintInfo("Processing options...")
1356
1357 # Validate options...
1358 ValidateOptions()
1359
1360 OptionsInfo["Align"] = True if re.match("^Yes$", Options["--align"], re.I) else False
1361 OptionsInfo["AlignMethod"] = Options["--alignMethod"].lower()
1362 OptionsInfo["AlignMode"] = Options["--alignMode"]
1363
1364 OptionsInfo["FpocketPropertiesAppend"] = (
1365 True if re.match("^Yes$", Options["--fpocketPropertiesAppend"], re.I) else False
1366 )
1367
1368 OptionsInfo["Infiles"] = Options["--infiles"]
1369 OptionsInfo["InfilesNames"] = Options["--infileNames"]
1370
1371 OptionsInfo["AlignRefFile"] = Options["--alignRefFile"]
1372 if re.match("^FirstInputFile$", Options["--alignRefFile"], re.I):
1373 OptionsInfo["RefFileName"] = OptionsInfo["InfilesNames"][0]
1374 else:
1375 OptionsInfo["RefFileName"] = Options["--alignRefFile"]
1376
1377 OptionsInfo["ChainIDs"] = Options["--chainIDs"]
1378
1379 OptionsInfo["FpocketMode"] = Options["--fpocketMode"]
1380 OptionsInfo["FpocketIDs"] = Options["--fpocketIDsList"]
1381
1382 OptionsInfo["Overwrite"] = Options["--overwrite"]
1383
1384 OptionsInfo["LabelFontID"] = int(Options["--labelFontID"])
1385
1386 OptionsInfo["PocketColorByPocketNum"] = (
1387 True if re.match("^Yes$", Options["--pocketColorByPocketNum"], re.I) else False
1388 )
1389 OptionsInfo["PocketLabel"] = True if re.match("^Yes$", Options["--pocketLabel"], re.I) else False
1390 OptionsInfo["PocketLabelType"] = Options["--pocketLabelType"]
1391 OptionsInfo["ThreeLetterPocketLabelType"] = (
1392 True if re.match("^ThreeLetter$", Options["--pocketLabelType"], re.I) else False
1393 )
1394
1395 OptionsInfo["PocketNumOneColor"] = "gray80"
1396
1397 OptionsInfo["PocketSurface"] = True if re.match("^Yes$", Options["--pocketSurface"], re.I) else False
1398 OptionsInfo["SurfaceChain"] = True if re.match("^Yes$", Options["--surfaceChain"], re.I) else False
1399
1400 OptionsInfo["SurfaceColor"] = Options["--surfaceColor"]
1401 OptionsInfo["SurfaceColorPalette"] = Options["--surfaceColorPalette"]
1402 OptionsInfo["SurfaceAtomTypesColors"] = Options["--surfaceAtomTypesColors"]
1403 ProcessSurfaceAtomTypesColors()
1404
1405 OptionsInfo["SphereScale"] = float(Options["--sphereScale"])
1406 OptionsInfo["SphereTransparency"] = float(Options["--sphereTransparency"])
1407
1408 OptionsInfo["SurfaceTransparency"] = float(Options["--surfaceTransparency"])
1409
1410 # Check and setup outfile dir before processing input files...
1411 CheckAndSetupOutfilesDir()
1412
1413 RetrieveInfilesInfo()
1414 RetrieveRefFileInfo()
1415 RetrieveFpocketResultFilesInfo()
1416
1417 # Process specified chain and pocket IDs..
1418 ProcessChainAndPocketIDs()
1419
1420
1421 def RetrieveOptions():
1422 """Retrieve command line arguments and options"""
1423
1424 # Get options...
1425 global Options
1426 Options = docopt(_docoptUsage_)
1427
1428 # Set current working directory to the specified directory...
1429 WorkingDir = Options["--workingdir"]
1430 if WorkingDir:
1431 os.chdir(WorkingDir)
1432
1433 # Handle examples option...
1434 if "--examples" in Options and Options["--examples"]:
1435 MiscUtil.PrintInfo(MiscUtil.GetExamplesTextFromDocOptText(__doc__))
1436 sys.exit(0)
1437
1438
1439 def ValidateOptions():
1440 """Validate option values"""
1441
1442 MiscUtil.ValidateOptionTextValue("--align", Options["--align"], "yes no")
1443 MiscUtil.ValidateOptionTextValue("--alignMethod", Options["--alignMethod"], "align cealign super")
1444 MiscUtil.ValidateOptionTextValue("--alignMode", Options["--alignMode"], "FirstChain Complex")
1445
1446 MiscUtil.ValidateOptionTextValue("--fpocketPropertiesAppend", Options["--fpocketPropertiesAppend"], "yes no")
1447
1448 # Expand infiles to handle presence of multiple input files...
1449 InfileNames = MiscUtil.ExpandFileNames(Options["--infiles"], ",")
1450 if not len(InfileNames):
1451 MiscUtil.PrintError('No input files specified for "-i, --infiles" option')
1452
1453 # Validate file extensions...
1454 for Infile in InfileNames:
1455 MiscUtil.ValidateOptionFilePath("-i, --infiles", Infile)
1456 MiscUtil.ValidateOptionFileExt("-i, --infiles", Infile, "pdb")
1457 MiscUtil.ValidateOptionsDistinctFileNames("-i, --infiles", Infile, "-o, --outfile", Options["--outfile"])
1458 Options["--infileNames"] = InfileNames
1459
1460 MiscUtil.ValidateOptionFileExt("-o, --outfile", Options["--outfile"], "pml")
1461
1462 if re.match("^yes$", Options["--align"], re.I):
1463 if not re.match("^FirstInputFile$", Options["--alignRefFile"], re.I):
1464 AlignRefFile = Options["--alignRefFile"]
1465 MiscUtil.ValidateOptionFilePath("--alignRefFile", AlignRefFile)
1466 MiscUtil.ValidateOptionFileExt("--alignRefFile", AlignRefFile, "pdb")
1467 MiscUtil.ValidateOptionsDistinctFileNames(
1468 "--AlignRefFile", AlignRefFile, "-o, --outfile", Options["--outfile"]
1469 )
1470
1471 MiscUtil.ValidateOptionTextValue("--fpocketMode", Options["--fpocketMode"], "All TopN Specify")
1472
1473 FpocketIDsList = []
1474 if re.match("^(TopN|Specify)$", Options["--fpocketMode"], re.I):
1475 if Options["--fpocketIDs"] is None:
1476 MiscUtil.PrintError(
1477 'No value specified for "--fpocketIDs" during "%s" of "-f, --fpocketMode" option.'
1478 % (Options["--fpocketMode"])
1479 )
1480
1481 FpocketIDs = re.sub(" ", "", Options["--fpocketIDs"])
1482 if not FpocketIDs:
1483 MiscUtil.PrintError(
1484 'No valid value specified for "--fpocketIDs" during "%s" of "-f, --fpocketMode" option.'
1485 % (Options["--fpocketMode"])
1486 )
1487 FpocketIDsWords = FpocketIDs.split(",")
1488 if len(FpocketIDsWords) == 0:
1489 MiscUtil.PrintError(
1490 'No valid value specified for "--fpocketIDs" during "%s" of "-f, --fpocketMode" option.'
1491 % (Options["--fpocketMode"])
1492 )
1493
1494 if re.match("^TopN$", Options["--fpocketMode"], re.I):
1495 if len(FpocketIDsWords) > 1:
1496 MiscUtil.PrintError(
1497 'Number of values specified for "--fpocketIDs" must be 1 during "TopN" of "-f, --fpocketMode" option.'
1498 )
1499
1500 for FpocketID in FpocketIDsWords:
1501 MiscUtil.ValidateOptionIntegerValue("--fpocketIDs", FpocketID, {">": 0})
1502 FpocketIDsList.append(FpocketID)
1503
1504 Options["--fpocketIDsList"] = FpocketIDsList
1505
1506 MiscUtil.ValidateOptionIntegerValue("--labelFontID", Options["--labelFontID"], {})
1507
1508 MiscUtil.ValidateOptionTextValue("--pocketColorByPocketNum", Options["--pocketColorByPocketNum"], "yes no")
1509 MiscUtil.ValidateOptionTextValue("--pocketLabel", Options["--pocketLabel"], "yes no")
1510 MiscUtil.ValidateOptionTextValue("--pocketLabelType", Options["--pocketLabelType"], "OneLetter ThreeLetter")
1511
1512 MiscUtil.ValidateOptionTextValue("--pocketSurface", Options["--pocketSurface"], "yes no")
1513 MiscUtil.ValidateOptionTextValue("--surfaceChain", Options["--surfaceChain"], "yes no")
1514
1515 MiscUtil.ValidateOptionFloatValue("--sphereScale", Options["--sphereScale"], {">": 0.0})
1516 MiscUtil.ValidateOptionFloatValue("--sphereTransparency", Options["--sphereTransparency"], {">=": 0.0, "<=": 1.0})
1517
1518 MiscUtil.ValidateOptionTextValue(
1519 "--surfaceColorPalette", Options["--surfaceColorPalette"], "RedToWhite WhiteToGreen"
1520 )
1521 MiscUtil.ValidateOptionFloatValue("--surfaceTransparency", Options["--surfaceTransparency"], {">=": 0.0, "<=": 1.0})
1522
1523
1524 # Setup a usage string for docopt...
1525 _docoptUsage_ = """
1526 PyMOLVisualizeFpockets.py - Visualize fpockets for macromolecules.
1527
1528 Usage:
1529 PyMOLVisualizeFpockets.py [--align <yes or no>] [--alignMethod <align, cealign, super>]
1530 [--alignMode <FirstChain or Complex>] [--alignRefFile <filename>]
1531 [--chainIDs <First, All or ID1,ID2...>] [--fpocketMode <All, TopN, or Specify>]
1532 [--fpocketIDs <Value or Value1,Value2...>] [--fpocketPropertiesAppend <yes or no>]
1533 [--labelFontID <number>] [--outfilesDir <outfilesDir>] [--pocketColorByPocketNum <yes or no>]
1534 [--pocketLabel <yes or no>] [--pocketLabelType <OneLetter or ThreeLetter>]
1535 [--pocketSurface <yes or no>] [--sphereScale <number>] [--sphereTransparency <number>]
1536 [--surfaceChain <yes or no>] [--surfaceAtomTypesColors <ColorType,ColorSpec,...>]
1537 [--surfaceColor <ColorName>] [--surfaceColorPalette <RedToWhite or WhiteToGreen>]
1538 [--surfaceTransparency <number>] [--overwrite] [-w <dir>] -i <infile1,infile2,infile3...> -o <outfile>
1539 PyMOLVisualizeFpockets.py -h | --help | -e | --examples
1540
1541 Description:
1542 Generate a PyMOL visualization file for visualizing pockets in macromolecules
1543 detected by an open source package named Fpocket [ Ref 166 ].
1544
1545 The results of Fpocket calculations must be available in the current directory
1546 for all input files. A complete set of expected results is shown below:
1547
1548 Dir: <PDBFileRoot>_out
1549 <PDBFileRoot>_out.pdb
1550 ... .. ...
1551 Dir: pockets
1552 <PDBFileRoot><PocketID>_atm.pdb
1553 ... .. ...
1554
1555 The supported input file format is: PDB (.pdb)
1556
1557 The supported output file formats is: PyMOL script file (.pml)
1558
1559 The following directory and files are created for the visualization of pockets
1560 detected by Fpocket:
1561
1562 Dir: <OutFileRoot>_out_PyMOL or <OutfilesDir>
1563 <OutfileRoot>.pml
1564 <PDBFileRoot>.pdb
1565 <PDBFileRoot>_out.pdb
1566
1567 You may visualize pockets in PyMOL by loading <OutfileRoot>.pml from
1568 <OutfileRoot>_out_PyMOL or <OutfilesDir> directory.
1569
1570 A variety of PyMOL groups and objects may be created for visualization of
1571 fpockets in macromolecules. These groups and objects correspond to complexes,
1572 chains, fpockets, and surfaces. A complete hierarchy of all possible PyMOL
1573 groups and objects is shown below:
1574
1575 <PDBFileRoot>
1576 .Complex
1577 .Initial_PDB
1578 .Fpocket_PDB
1579 .Chain<ID>
1580 .Complex
1581 .Complex
1582 .Chain
1583 .Chain
1584 .Surface
1585 .Surface
1586 .Hydrophobicity
1587 .Hydrophobicity_Charge
1588 .FPocket<ID>
1589 .FPocket
1590 .Residues
1591 .Surface
1592 .Surface
1593 .Hydrophobicity
1594 .Hydrophobicity_Charge
1595 .Chain<ID>
1596 ... ... ...
1597 .FPocket<ID>
1598 ... ... ...
1599 .FPocket<ID>
1600 ... ... ...
1601 .Chain<ID>
1602 ... ... ...
1603 <PDBFileRoot>
1604 .Complex
1605 ... ... ...
1606 .Chain<ID>
1607 ... ... ...
1608 .FPocket<ID>
1609 ... ... ...
1610 .FPocket<ID>
1611 ... ... ...
1612 .Chain<ID>
1613 ... ... ...
1614
1615 Options:
1616 -a, --align <yes or no> [default: no]
1617 Align input files to a reference file before visualization.
1618 --alignMethod <align, cealign, super> [default: super]
1619 Alignment methodology to use for aligning input files to a
1620 reference file.
1621 --alignMode <FirstChain or Complex> [default: FirstChain]
1622 Portion of input and reference files to use for spatial alignment of
1623 input files against reference file. Possible values: FirstChain or
1624 Complex.
1625
1626 The FirstChain mode allows alignment of the first chain in each input
1627 file to the first chain in the reference file along with moving the rest
1628 of the complex to coordinate space of the reference file. The complete
1629 complex in each input file is aligned to the complete complex in reference
1630 file for the Complex mode.
1631 --alignRefFile <filename> [default: FirstInputFile]
1632 Reference input file name. The default is to use the first input file
1633 name specified using '-i, --infiles' option.
1634 -c, --chainIDs <First, All or ID1,ID2...> [default: First]
1635 List of chain IDs to use for visualizing fpockets in macromolecules. Possible
1636 values: First, All, or a comma delimited list of chain IDs. The default is to
1637 use the chain ID for the first chain in each input file.
1638 -e, --examples
1639 Print examples.
1640 -f, --fpocketMode <All, TopN, or Specify> [default: All]
1641 Fpockets specification mode for visualizing fpockets across chains in
1642 macromolecules. Possible values: All, TopN, or specify. By default, all
1643 available fpockets are visualized across specified chains.
1644
1645 The fpocket IDs must be specified using '--fpocketIDs' option for 'TopN'
1646 and 'Specifiy' value of '--fpocketMode '.
1647 --fpocketIDs <Value or Value1,Value2...>
1648 List of Fpocket IDs for visualizing fpockets across chains. This value is
1649 dependent on the value of '--fpocketMode'. The possible values are
1650 either a number or a comma delimited list of number for 'TopN' and
1651 'Specify' value '--fpocketMode' option. For example:
1652
1653 This option is ignored during 'All' value of '--fpocketMode' option.
1654 --fpocketPropertiesAppend <yes or no> [default: yes]
1655 Append fpocket properties to names of PyMOL fpocket groups and
1656 objects. The following properties are appended to the names of PyMOL
1657 groups using their abbreviations and values: PocketScore - S; DrugScore - D;
1658 PocketVolume - V; HydrophobicityScore - H; PolarityScore - P.
1659 For example:
1660
1661 Fpocket1_S0p50_D0p00_V638p81_Hneg6p67_P11p00.Fpocket
1662 -h, --help
1663 Print this help message.
1664 -i, --infiles <infile1,infile2,infile3...>
1665 Input PDB file names. The current directory must contain the results from
1666 Fpocket calculations for all the input PDB files.
1667 --labelFontID <number> [default: 7]
1668 Font ID for drawing labels. Default: 7 (Sans Bold). Valid values: 5 to 16.
1669 The specified value must be a valid PyMOL font ID. No validation is
1670 performed. The complete lists of valid font IDs is available at:
1671 pymolwiki.org/index.php/Label_font_id. Examples: 5 - Sans;
1672 7 - Sans Bold; 9 - Serif; 10 - Serif Bold.
1673 -o, --outfile <outfile>
1674 PML output file name for visualizing fpockets. The PML outfile is created
1675 in a new output directory named <OutfileRoot>_out_PyMOL. In addition, the
1676 output directory contains all appropriate PDB files generated by Fpocket for
1677 visualization of fpockets in PyMOL.
1678 --outfilesDir <outfilesDir> [default: auto]
1679 Output files directory name. Default: <OutfileRoot>_out_PyMOL.
1680 --pocketColorByPocketNum <yes or no> [default: yes]
1681 Color fpocket residues and residue labels by pocket number. Otherwise,
1682 the pocket residues are colored by element names using default PyMOL
1683 color scheme. No color is set for residue labels.
1684 --pocketLabel <yes or no> [default: yes]
1685 Display residue labels on fpocket residues. The residue number is always
1686 appended to residue label. You may specify a one or thee letter residue
1687 labels using '--pocketLabelType' option.
1688 --pocketLabelType <OneLetter or ThreeLetter> [default: OneLetter]
1689 Display one or three letter residue labels on fpocket residues
1690 --pocketSurface <yes or no> [default: yes]
1691 Surfaces around fpocket residues colored by hydrophobicity alone and
1692 both hydrophobicity and charge. The hydrophobicity surface is colored
1693 at residue level using Eisenberg hydrophobicity scale for residues and color
1694 gradient specified by '--surfaceColorPalette' option. The hydrophobicity and
1695 charge surface is colored at atom level using colors specified for
1696 groups of atoms by '--surfaceAtomTypesColors' option. This scheme allows
1697 simultaneous mapping of hyrophobicity and charge values on the surfaces.
1698
1699 In addition, generic surfaces colored by '--surfaceColor' are always created
1700 for pockets.
1701 --sphereScale <number> [default: 0.4]
1702 Scaling factor for spheres used to display fpocket alpha spheres.
1703 --sphereTransparency <number> [default: 0.25]
1704 Transparency for spheres used to display fpocket alpha spheres.
1705 --surfaceChain <yes or no> [default: yes]
1706 Surfaces around individual chain colored by hydrophobicity alone and
1707 both hydrophobicity and charge. The hydrophobicity surface is colored
1708 at residue level using Eisenberg hydrophobicity scale for residues and color
1709 gradient specified by '--surfaceColorPalette' option. The hydrophobicity and
1710 charge surface is colored at atom level using colors specified for
1711 groups of atoms by '--surfaceAtomTypesColors' option. This scheme allows
1712 simultaneous mapping of hyrophobicity and charge values on the surfaces.
1713
1714 In addition, generic surfaces colored by '--surfaceColor' are always created
1715 for chains.
1716 --surfaceAtomTypesColors <ColorType,ColorSpec,...> [default: auto]
1717 Atom colors for generating surfaces colored by hyrophobicity and charge
1718 around chains and pockets in proteins. It's a pairwise comma delimited list
1719 of atom color type and color specification for groups of atoms.
1720
1721 The default values for color types along wth color specifications
1722 are shown below:
1723
1724 HydrophobicAtomsColor, yellow,
1725 NegativelyChargedAtomsColor, red,
1726 PositivelyChargedAtomsColor, blue,
1727 OtherAtomsColor, gray90
1728
1729 The color names must be valid PyMOL names.
1730
1731 The color values may also be specified as space delimited RGB triplets:
1732
1733 HydrophobicAtomsColor, 0.95 0.78 0.0,
1734 NegativelyChargedAtomsColor, 1.0 0.4 0.4,
1735 PositivelyChargedAtomsColor, 0.2 0.5 0.8,
1736 OtherAtomsColor, 0.95 0.95 0.95
1737
1738 --surfaceColor <ColorName> [default: lightblue]
1739 Color name for surfaces around chains and pockets. This color is not used
1740 for surfaces colored by hydrophobicity and charge. The color name must be
1741 a valid PyMOL name.
1742 --surfaceColorPalette <RedToWhite or WhiteToGreen> [default: RedToWhite]
1743 Color palette for hydrophobic surfaces around chains and pockets in proteins.
1744 Possible values: RedToWhite or WhiteToGreen from most hydrophobic amino
1745 acid to least hydrophobic. The colors values for amino acids are taken from
1746 color_h script available as part of the Script Library at PyMOL Wiki.
1747 --surfaceTransparency <number> [default: 0.25]
1748 Surface transparency for molecular surfaces.
1749 --overwrite
1750 Overwrite existing files.
1751 -w, --workingdir <dir>
1752 Location of working directory which defaults to the current directory.
1753
1754 Examples:
1755 To visualize all fpockets available in a directory <PDBRoot>_out for the first
1756 chain, along pocket residues and surfaces, in a PDB file, and generate a PML
1757 file in a new directory <PDBRoot>_out_pymol, type:
1758
1759 % PyMOLVisualizeFpockets.py -i Sample5.pdb -o Sample5.pml
1760
1761 To rerun the first example without displaying pocket residue labels,
1762 coloring pockets by element type, and write out a PML file, type:
1763
1764 % PyMOLVisualizeFpockets.py --pocketColorByPocketNum no
1765 --pocketLabel no -i Sample5.pdb -o Sample5.pml
1766
1767 To rerun the first example to visualize only top 5 fpockets and write out a
1768 PML file, type:
1769
1770 % PyMOLVisualizeFpockets.py -f TopN --fpocketIDs 5 -i Sample5.pdb
1771 -o Sample5.pml
1772
1773 To rerun the first example to visualize a specific set of fpockets and write
1774 out a PML file, type:
1775
1776 % PyMOLVisualizeFpockets.py -f Specify --fpocketIDs "1,2,3" -i Sample5.pdb
1777 -o Sample5.pml
1778
1779 To rerun the first example to visualize all fpockets across all chains and write
1780 out a PML file, type:
1781
1782 % PyMOLVisualizeFpockets.py -c All -f All -i Sample5.pdb -o Sample5.pml
1783
1784 To rerun the first example without displaying hydrophobic and charge surfaces
1785 around chain and pockets and and write out a PML file, type:
1786
1787 % PyMOLVisualizeFpockets.py --surfaceChain no --pocketSurface no
1788 -i Sample5.pdb -o Sample5.pml
1789
1790 To visualize top 5 fpockets available in a directories <PDBRoot>_out for the
1791 first chain, along pocket residues and surfaces, in PDB files, aligning first
1792 fchain in each input file to the first chain in first input file, and generate a
1793 PML file in a new directory <PDBRoot>_out_pymol, type:
1794
1795 % PyMOLVisualizeFpockets.py -f TopN --fpocketIDs 5 --align yes
1796 -i "Sample5.pdb,Sample6.pdb" -o Sample5Aligned.pml
1797
1798 To visualize top 5 fpockets available in a directories <PDBRoot>_out for the
1799 first chain, along pocket residues and surfaces, in PDB files, aligning first
1800 chain in each input file to the first chain in first chain in a specified PDB
1801 file using a specified alignment method,, and generate a PML file in a new
1802 directory <PDBRoot>_out_pymol, type:
1803
1804 % PyMOLVisualizeFpockets.py -f TopN --fpocketIDs 5 --align yes
1805 --alignMode FirstChain --alignRefFile Sample6.pdb --alignMethod super
1806 -i "Sample5.pdb,Sample6.pdb" -o Sample5Aligned.pml
1807
1808 Author:
1809 Manish Sud
1810
1811 Collaborators:
1812 Joann Prescott-Roy and Pat Walters
1813
1814 See also:
1815 DownloadPDBFiles.pl, PyMOLVisualizeCavities.py,
1816 PyMOLVisualizeCryoEMDensity.py, PyMOLVisualizeElectronDensity.py,
1817 PyMOLVisualizeInterfaces.py, PyMOLVisualizeMacromolecules.py,
1818 PyMOLVisualizeSurfaceAndBuriedResidues.py
1819
1820 Copyright:
1821 Copyright (C) 2026 Manish Sud. All rights reserved.
1822
1823 The functionality available in this script is implemented using PyMOL, a
1824 molecular visualization system on an open source foundation originally
1825 developed by Warren DeLano.
1826
1827 This file is part of MayaChemTools.
1828
1829 MayaChemTools is free software; you can redistribute it and/or modify it under
1830 the terms of the GNU Lesser General Public License as published by the Free
1831 Software Foundation; either version 3 of the License, or (at your option) any
1832 later version.
1833
1834 """
1835
1836 if __name__ == "__main__":
1837 main()