1 #!/bin/env python 2 # 3 # File: PyMOLInfoMacromolecules.py 4 # Author: Manish Sud <msud@san.rr.com> 5 # 6 # Copyright (C) 2024 Manish Sud. All rights reserved. 7 # 8 # The functionality available in this script is implemented using PyMOL, a 9 # molecular visualization system on an open source foundation originally 10 # developed by Warren DeLano. 11 # 12 # This file is part of MayaChemTools. 13 # 14 # MayaChemTools is free software; you can redistribute it and/or modify it under 15 # the terms of the GNU Lesser General Public License as published by the Free 16 # Software Foundation; either version 3 of the License, or (at your option) any 17 # later version. 18 # 19 # MayaChemTools is distributed in the hope that it will be useful, but without 20 # any warranty; without even the implied warranty of merchantability of fitness 21 # for a particular purpose. See the GNU Lesser General Public License for more 22 # details. 23 # 24 # You should have received a copy of the GNU Lesser General Public License 25 # along with MayaChemTools; if not, see <http://www.gnu.org/licenses/> or 26 # write to the Free Software Foundation Inc., 59 Temple Place, Suite 330, 27 # Boston, MA, 02111-1307, USA. 28 # 29 30 from __future__ import print_function 31 32 # Add local python path to the global path and import standard library modules... 33 import os 34 import sys; sys.path.insert(0, os.path.join(os.path.dirname(sys.argv[0]), "..", "lib", "Python")) 35 import time 36 import re 37 38 # PyMOL imports... 39 try: 40 import pymol 41 # Finish launching PyMOL in a command line mode for batch processing (-c) 42 # along with the following options: disable loading of pymolrc and plugins (-k); 43 # suppress start up messages (-q) 44 pymol.finish_launching(['pymol', '-ckq']) 45 except ImportError as ErrMsg: 46 sys.stderr.write("\nFailed to import PyMOL module/package: %s\n" % ErrMsg) 47 sys.stderr.write("Check/update your PyMOL environment and try again.\n\n") 48 sys.exit(1) 49 50 # MayaChemTools imports... 51 try: 52 from docopt import docopt 53 import MiscUtil 54 import PyMOLUtil 55 except ImportError as ErrMsg: 56 sys.stderr.write("\nFailed to import MayaChemTools module/package: %s\n" % ErrMsg) 57 sys.stderr.write("Check/update your MayaChemTools environment and try again.\n\n") 58 sys.exit(1) 59 60 ScriptName = os.path.basename(sys.argv[0]) 61 Options = {} 62 OptionsInfo = {} 63 64 def main(): 65 """Start execution of the script.""" 66 67 MiscUtil.PrintInfo("\n%s (PyMOL v%s; MayaChemTools v%s; %s): Starting...\n" % (ScriptName, pymol.cmd.get_version()[0], MiscUtil.GetMayaChemToolsVersion(), time.asctime())) 68 69 (WallClockTime, ProcessorTime) = MiscUtil.GetWallClockAndProcessorTime() 70 71 # Retrieve command line arguments and options... 72 RetrieveOptions() 73 74 # Process and validate command line arguments and options... 75 ProcessOptions() 76 77 # Perform actions required by the script... 78 ListInfo() 79 80 MiscUtil.PrintInfo("\n%s: Done...\n" % ScriptName) 81 MiscUtil.PrintInfo("Total time: %s" % MiscUtil.GetFormattedElapsedTime(WallClockTime, ProcessorTime)) 82 83 def ListInfo(): 84 """List information for macromolecules.""" 85 86 for Infile in OptionsInfo["InfilesNames"]: 87 MiscUtil.PrintInfo("\nProcessing file %s..." % Infile) 88 ListFileInfo(Infile) 89 90 def ListFileInfo(Infile): 91 """List information for macromolecules in a file.""" 92 93 FileDir, FileName, FileExt = MiscUtil.ParseFileName(Infile) 94 MolName = FileName 95 96 # Load infile... 97 pymol.cmd.load(Infile, MolName) 98 99 ChainIDs = PyMOLUtil.GetChains(MolName) 100 ListHeaderInfo(Infile) 101 102 ListChainsInfo(MolName, ChainIDs) 103 ListChainsResiduesInfo(MolName, ChainIDs) 104 105 ListLigandsInfo(MolName, ChainIDs) 106 ListSolventsInfo(MolName, ChainIDs) 107 ListInorganicsInfo(MolName, ChainIDs) 108 109 ListPocketsInfo(MolName, ChainIDs) 110 111 ListInterfaceResiduesInfo(MolName, ChainIDs) 112 ListSurfaceResiduesInfo(MolName, ChainIDs) 113 ListPhiPsiAnglesInfo(MolName, ChainIDs) 114 115 ListBoundingBoxInfo(MolName) 116 ListCentroid(MolName) 117 118 # Delete infile object... 119 pymol.cmd.delete(MolName) 120 121 ListFileSizeAndModificationInfo(Infile) 122 123 def ListHeaderInfo(Infile): 124 """List header information.""" 125 126 if not (OptionsInfo["All"] or OptionsInfo["Header"]): 127 return 128 129 FileDir, FileName, FileExt = MiscUtil.ParseFileName(Infile) 130 131 Classification, DepositionDate, IDCode, ExperimentalTechnique, Resolution = ["Not Available"] * 5 132 if re.match("^pdb$", FileExt, re.I): 133 Classification, DepositionDate, IDCode, ExperimentalTechnique, Resolution = RetriveHeadAndExperimentalInfoFromPDBFile(Infile) 134 elif re.match("^cif$", FileExt, re.I): 135 Classification, DepositionDate, IDCode, ExperimentalTechnique, Resolution = RetriveHeadAndExperimentalInfoFromCIFFile(Infile) 136 137 MiscUtil.PrintInfo("\nID: %s\nClassification: %s\nDeposition date: %s" % (IDCode, Classification, DepositionDate)) 138 MiscUtil.PrintInfo("\nExperimental technique: %s\nResolution: %s" % (ExperimentalTechnique, Resolution)) 139 140 def RetriveHeadAndExperimentalInfoFromPDBFile(Infile): 141 """Retrieve header and experimental information from PDB file.""" 142 143 Classification, DepositionDate, IDCode, ExperimentalTechnique, Resolution = ["Not Available"] * 5 144 145 Lines = MiscUtil.GetTextLines(Infile) 146 147 # Retrieve header info... 148 for Line in Lines: 149 if re.match("^HEADER", Line, re.I): 150 # Format: 10x40s9s3x4s 151 FormatSize = 66 152 Line = PrepareLineForFormatSize(Line, FormatSize) 153 154 Classification = Line[10:50] 155 DepositionDate = Line[50:59] 156 IDCode = Line[62:66] 157 158 Classification = Classification.strip() if len(Classification.strip()) else "Not Available" 159 DepositionDate = DepositionDate.strip() if len(DepositionDate.strip()) else "Not Available" 160 IDCode = IDCode.strip() if len(IDCode.strip()) else "Not Available" 161 162 break 163 164 # Retrieve experimental info... 165 for Line in Lines: 166 if re.match("^EXPDTA", Line, re.I): 167 ExperimentalTechnique = re.sub("^EXPDTA", "", Line, re.I) 168 ExperimentalTechnique = ExperimentalTechnique.strip() 169 elif re.match("^REMARK 2 RESOLUTION.", Line, re.I): 170 if re.search("NOT APPLICABLE", Line, re.I): 171 Resolution = "NOT APPLICABLE" 172 else: 173 FormatSize = 70 174 Line = PrepareLineForFormatSize(Line, FormatSize) 175 Resolution = Line[22:70] 176 Resolution = Resolution.strip() if len(Resolution.strip()) else "Not Available" 177 elif re.match("^(ATOM|HETATM)", Line, re.I): 178 break 179 180 return Classification, DepositionDate, IDCode, ExperimentalTechnique, Resolution 181 182 def RetriveHeadAndExperimentalInfoFromCIFFile(Infile): 183 """Retrieve header information from CIF file.""" 184 185 Classification, DepositionDate, IDCode, ExperimentalTechnique, Resolution = ["Not Available"] * 5 186 187 Lines = MiscUtil.GetTextLines(Infile) 188 189 # IDCode... 190 for Line in Lines: 191 if re.match("^_struct_keywords.entry_id", Line, re.I): 192 IDCode = re.sub("^_struct_keywords.entry_id", "", Line, re.I) 193 IDCode = IDCode.strip() if len(IDCode.strip()) else "Not Available" 194 break 195 196 # Classification... 197 for Line in Lines: 198 if re.match("^_struct_keywords.pdbx_keywords", Line, re.I): 199 Classification = re.sub("^_struct_keywords.pdbx_keywords", "", Line, re.I) 200 Classification = Classification.strip() if len(Classification.strip()) else "Not Available" 201 break 202 203 # Deposition date... 204 for Line in Lines: 205 if re.match("^_pdbx_database_status.recvd_initial_deposition_date", Line, re.I): 206 DepositionDate = re.sub("^_pdbx_database_status.recvd_initial_deposition_date", "", Line, re.I) 207 DepositionDate = DepositionDate.strip() if len(DepositionDate.strip()) else "Not Available" 208 break 209 210 # Experimental technique... 211 for Line in Lines: 212 if re.match("^_exptl.method", Line, re.I): 213 ExperimentalTechnique = re.sub("(_exptl.method|')", "", Line, flags = re.I) 214 ExperimentalTechnique = ExperimentalTechnique.strip() if len(ExperimentalTechnique.strip()) else "Not Available" 215 break 216 217 # Resolution... 218 for Line in Lines: 219 if re.match("^_reflns.d_resolution_high", Line, re.I): 220 Resolution = re.sub("^_reflns.d_resolution_high", "", Line, re.I) 221 Resolution = Resolution.strip() if len(Resolution.strip()) else "Not Available" 222 break 223 224 return Classification, DepositionDate, IDCode, ExperimentalTechnique, Resolution 225 226 def PrepareLineForFormatSize(Text, FormatSize): 227 """Prepare text string for format size padding or truncation to 228 alter its size. 229 """ 230 231 TextLen = len(Text) 232 if TextLen < FormatSize: 233 PaddingLen = FormatSize - TextLen 234 TextPadding = " " * PaddingLen 235 Text = Text + TextPadding 236 elif TextLen > FormatSize: 237 Text = Text[:FormatSize] 238 239 return Text 240 241 def ListChainsInfo(MolName, ChainIDs): 242 """List chains information across all chains.""" 243 244 if not (OptionsInfo["All"] or OptionsInfo["Chains"]): 245 return 246 247 ChainsInfo = ", ".join(ChainIDs) if len(ChainIDs) else "None" 248 249 MiscUtil.PrintInfo("\nNumber of chains: %s" % len(ChainIDs)) 250 MiscUtil.PrintInfo("ChainIDs: %s" % ChainsInfo) 251 252 def ListChainsResiduesInfo(MolName, ChainIDs): 253 """List polymer chain residue information across all chains.""" 254 255 if not (OptionsInfo["All"] or OptionsInfo["CountResidues"]): 256 return 257 258 ListSelectionResiduesInfo(MolName, ChainIDs, "Chains") 259 260 # List information for non-standard amino acids... 261 ListSelectionResiduesInfo(MolName, ChainIDs, "NonStandardAminoAcids") 262 263 def ListLigandsInfo(MolName, ChainIDs): 264 """List ligand information across all chains.""" 265 266 if not (OptionsInfo["All"] or OptionsInfo["Ligands"]): 267 return 268 269 ListSelectionResiduesInfo(MolName, ChainIDs, "Ligands") 270 271 def ListSolventsInfo(MolName, ChainIDs): 272 """List solvents information across all chains.""" 273 274 if not (OptionsInfo["All"] or OptionsInfo["Solvents"]): 275 return 276 277 ListSelectionResiduesInfo(MolName, ChainIDs, "Solvents") 278 279 def ListInorganicsInfo(MolName, ChainIDs): 280 """List inorganics information across all chains.""" 281 282 if not (OptionsInfo["All"] or OptionsInfo["Inorganics"]): 283 return 284 285 ListSelectionResiduesInfo(MolName, ChainIDs, "Inorganics") 286 287 def ListSelectionResiduesInfo(MolName, ChainIDs, SelectionType): 288 """List residues information for a specified selection type.""" 289 290 Lines = [] 291 TotalResCount = 0 292 SelectionLabel = None 293 294 if not len(ChainIDs): 295 SelectionInfo, SelectionLabel = GetSelectionResiduesInfo(MolName, None, SelectionType) 296 MiscUtil.PrintInfo("\nNumber of %s residues: %s" % (SelectionLabel, TotalResCount)) 297 return 298 299 for ChainID in ChainIDs: 300 SelectionInfo, SelectionLabel = GetSelectionResiduesInfo(MolName, ChainID, SelectionType) 301 302 ChainResCount = 0 303 LineWords = [] 304 305 SortedResNames = sorted(SelectionInfo["ResNames"], key = lambda ResName: SelectionInfo["ResCount"][ResName], reverse = True) 306 for ResName in SortedResNames: 307 ResCount = SelectionInfo["ResCount"][ResName] 308 LineWords.append("%s - %s" % (ResName, ResCount)) 309 310 ChainResCount += ResCount 311 TotalResCount += ResCount 312 313 Line = "; ".join(LineWords) if len(LineWords) else None 314 Lines.append("Chain ID: %s; Count: %s; Names: %s" % (ChainID, ChainResCount, Line)) 315 316 MiscUtil.PrintInfo("\nNumber of %s residues: %s" % (SelectionLabel, TotalResCount)) 317 for Line in Lines: 318 MiscUtil.PrintInfo("%s" % Line) 319 320 def GetSelectionResiduesInfo(MolName, ChainID, SelectionType): 321 """Get residues info for a specified selection type.""" 322 323 SelectionInfo = None 324 SelectionLabel = None 325 326 if re.match("^Ligands$", SelectionType, re.I): 327 SelectionLabel = "ligand" 328 SelectionInfo = PyMOLUtil.GetLigandResiduesInfo(MolName, ChainID) if ChainID is not None else None 329 elif re.match("^Solvents$", SelectionType, re.I): 330 SelectionLabel = "solvent" 331 SelectionInfo = PyMOLUtil.GetSolventResiduesInfo(MolName, ChainID) if ChainID is not None else None 332 elif re.match("^Inorganics$", SelectionType, re.I): 333 SelectionLabel = "inorganic" 334 SelectionInfo = PyMOLUtil.GetInorganicResiduesInfo(MolName, ChainID) if ChainID is not None else None 335 elif re.match("^Chains$", SelectionType, re.I): 336 SelectionLabel = "polymer chain" 337 SelectionInfo = PyMOLUtil.GetPolymerResiduesInfo(MolName, ChainID) if ChainID is not None else None 338 elif re.match("^NonStandardAminoAcids$", SelectionType, re.I): 339 SelectionLabel = "non-standard amino acids" 340 SelectionInfo = PyMOLUtil.GetAminoAcidResiduesInfo(MolName, ChainID, "NonStandard") if ChainID is not None else None 341 else: 342 MiscUtil.PrintError("Failed to retrieve residues information: Selection type %s is not valid..." % SelectionType) 343 344 return SelectionInfo, SelectionLabel 345 346 def ListPocketsInfo(MolName, ChainIDs): 347 """List pockect residues information across all chains.""" 348 349 if not (OptionsInfo["All"] or OptionsInfo["PocketLigands"] or OptionsInfo["PocketSolvents"] or OptionsInfo["PocketInorganics"]) : 350 return 351 352 for ChainID in ChainIDs: 353 MiscUtil.PrintInfo("\nListing ligand pockets information for chain %s..." % (ChainID)) 354 355 LigandsInfo = PyMOLUtil.GetLigandResiduesInfo(MolName, ChainID) 356 if not len(LigandsInfo["ResNames"]): 357 MiscUtil.PrintInfo("\nNumber of residues in ligand pocket: None") 358 MiscUtil.PrintInfo("Chain ID: %s; Ligands: None" % (ChainID)) 359 continue 360 361 for LigandResName in sorted(LigandsInfo["ResNames"]): 362 for LigandResNum in LigandsInfo["ResNum"][LigandResName]: 363 ListPocketsPolymerInfo(MolName, ChainID, LigandResName, LigandResNum) 364 ListPocketsSolventsInfo(MolName, ChainID, LigandResName, LigandResNum) 365 ListPocketsInorganicsInfo(MolName, ChainID, LigandResName, LigandResNum) 366 367 def ListPocketsPolymerInfo(MolName, ChainID, LigandResName, LigandResNum): 368 """List pockect residues information across all chains.""" 369 370 if not (OptionsInfo["All"] or OptionsInfo["PocketLigands"]): 371 return 372 373 ListPocketSelectionResiduesInfo(MolName, ChainID, LigandResName, LigandResNum, "Pockets") 374 375 def ListPocketsSolventsInfo(MolName, ChainID, LigandResName, LigandResNum): 376 """List pockect solvent residues information across all chains.""" 377 378 if not (OptionsInfo["All"] or OptionsInfo["PocketSolvents"]): 379 return 380 381 ListPocketSelectionResiduesInfo(MolName, ChainID, LigandResName, LigandResNum, "PocketSolvents") 382 383 def ListPocketsInorganicsInfo(MolName, ChainID, LigandResName, LigandResNum): 384 """List pockect inorganic residues information across all chains.""" 385 386 if not (OptionsInfo["All"] or OptionsInfo["PocketInorganics"]): 387 return 388 389 ListPocketSelectionResiduesInfo(MolName, ChainID, LigandResName, LigandResNum, "PocketInorganics") 390 391 def ListPocketSelectionResiduesInfo(MolName, ChainID, LigandResName, LigandResNum, SelectionType): 392 """List residues information for a specified pocket selection type.""" 393 394 PocketDistanceCutoff = OptionsInfo["PocketDistanceCutoff"] 395 SelectionLabel = GetPocketSelectionResiduesInfoLabel(SelectionType) 396 397 SelectionInfo = GetPocketSelectionResiduesInfo(MolName, ChainID, LigandResName, LigandResNum, PocketDistanceCutoff, SelectionType) 398 399 ResiduesCount, ResiduesDistribution, ResiduesIDs = SetupSelectionResiduesInfo(SelectionInfo) 400 MiscUtil.PrintInfo("\nNumber of %s residues in ligand pocket: %s" % (SelectionLabel, ResiduesCount)) 401 MiscUtil.PrintInfo("Chain ID: %s; Ligand ID: %s_%s\nResidue distribution: %s\nResidue IDs: %s" % (ChainID, LigandResName, LigandResNum, ResiduesDistribution, ResiduesIDs)) 402 403 def GetPocketSelectionResiduesInfo(MolName, ChainID, LigandResName, LigandResNum, PocketDistanceCutoff, SelectionType): 404 """Get pocket residues info for a specified selection type.""" 405 406 SelectionInfo = None 407 408 if re.match("^Pockets$", SelectionType, re.I): 409 SelectionInfo = PyMOLUtil.GetPocketPolymerResiduesInfo(MolName, ChainID, LigandResName, LigandResNum, PocketDistanceCutoff) 410 elif re.match("^PocketSolvents$", SelectionType, re.I): 411 SelectionInfo = PyMOLUtil.GetPocketSolventResiduesInfo(MolName, ChainID, LigandResName, LigandResNum, PocketDistanceCutoff) 412 elif re.match("^PocketInorganics$", SelectionType, re.I): 413 SelectionInfo = PyMOLUtil.GetPocketInorganicResiduesInfo(MolName, ChainID, LigandResName, LigandResNum, PocketDistanceCutoff) 414 else: 415 MiscUtil.PrintError("Failed to retrieve pocket residues information: Selection type %s is not valid..." % SelectionType) 416 417 return SelectionInfo 418 419 def ListSurfaceResiduesInfo(MolName, ChainIDs): 420 """List surface and buried residues for polymer chains with in a molecule.""" 421 422 if not (OptionsInfo["All"] or OptionsInfo["SurfaceResidues"]): 423 return 424 425 MiscUtil.PrintInfo("\nListing surface and buried residues information...") 426 if not len(ChainIDs): 427 MiscUtil.PrintInfo("\nNumber of surface residues: None\nNumber of buried residues: None") 428 return 429 430 TotalSurfaceResidues, TotalBuriedResidues = [0] * 2 431 432 for ChainID in ChainIDs: 433 SurfaceResiduesSelectionInfo, BuriedResiduesSelectionInfo = PyMOLUtil.GetSurfaceAndBuriedResiduesInfo(MolName, ChainID, OptionsInfo["SurfaceResiduesCutoff"]) 434 435 SurfaceResiduesCount, SurfaceResiduesDistribution, SurfaceResiduesIDs = SetupSelectionResiduesInfo(SurfaceResiduesSelectionInfo) 436 BuriedResiduesCount, BuriedResiduesDistribution, BuriedResiduesIDs = SetupSelectionResiduesInfo(BuriedResiduesSelectionInfo) 437 438 TotalSurfaceResidues += SurfaceResiduesCount 439 MiscUtil.PrintInfo("\nChainID: %s; Number of surface residues: %d" % (ChainID, SurfaceResiduesCount)) 440 MiscUtil.PrintInfo("Residue distribution: %s" % (SurfaceResiduesDistribution)) 441 if OptionsInfo["SurfaceResiduesIDs"]: 442 MiscUtil.PrintInfo("Residue IDs: %s" % (SurfaceResiduesIDs)) 443 444 TotalBuriedResidues += BuriedResiduesCount 445 MiscUtil.PrintInfo("\nChainID: %s; Number of buried residues: %d" % (ChainID, BuriedResiduesCount)) 446 MiscUtil.PrintInfo("Residue distribution: %s" % (BuriedResiduesDistribution)) 447 if OptionsInfo["SurfaceResiduesIDs"]: 448 MiscUtil.PrintInfo("Residue IDs: %s" % (BuriedResiduesIDs)) 449 450 MiscUtil.PrintInfo("\nTotal number of surface residues: %d\nTotal number of buried residues: %s" % (TotalSurfaceResidues, TotalBuriedResidues)) 451 452 def ListPhiPsiAnglesInfo(MolName, ChainIDs): 453 """List phi and psi torsion angles for polymer chains with in a molecule.""" 454 455 if not (OptionsInfo["All"] or OptionsInfo["PhiPsi"]): 456 return 457 458 MiscUtil.PrintInfo("\nListing phi and psi angles information...") 459 460 if not len(ChainIDs): 461 MiscUtil.PrintInfo("\nNumber of phi and psi angles: None\n") 462 return 463 464 for ChainID in ChainIDs: 465 if re.match("^Categories$", OptionsInfo["PhiPsiMode"], re.I): 466 # Retrieve phi and psi angles by categories used for Ramachandran plots 467 GeneralPhiPsiInfo, GlyPhiPsiInfo, ProPhiPsiInfo, PreProPhiPsiInfo = PyMOLUtil.GetPhiPsiCategoriesResiduesInfo(MolName, ChainID) 468 469 SetupAndListPhiPsiResiduesInfo(GeneralPhiPsiInfo, "General (All residues except glycine, proline, or pre-proline)", ChainID) 470 SetupAndListPhiPsiResiduesInfo(GlyPhiPsiInfo, "Glycine (Only glycine residues)", ChainID) 471 SetupAndListPhiPsiResiduesInfo(ProPhiPsiInfo, "Proline (Only proline residues)", ChainID) 472 SetupAndListPhiPsiResiduesInfo(PreProPhiPsiInfo, "Pre-Proline (Only residues before proline not including glycine or proline)", ChainID) 473 else: 474 PhiPsiResiduesInfo = PyMOLUtil.GetPhiPsiResiduesInfo(MolName, ChainID, Categorize = True) 475 SetupAndListPhiPsiResiduesInfo(PhiPsiResiduesInfo, "All", ChainID) 476 477 def SetupAndListPhiPsiResiduesInfo(PhiPsiResiduesInfo, AnglesType, ChainID): 478 """Setup and list information for phi and psi torsion angles.""" 479 480 MiscUtil.PrintInfo("\nChainID: %s; Phi and Psi angles: %s" %(ChainID, AnglesType)) 481 482 PhiPsiCount = len(PhiPsiResiduesInfo["ResNums"]) 483 if not PhiPsiCount: 484 MiscUtil.PrintInfo("Number of angles: None") 485 return 486 487 MiscUtil.PrintInfo("Number of phi and psi angles: %d" % PhiPsiCount) 488 489 CategoriesMode = True if re.match("^Categories$", OptionsInfo["PhiPsiMode"], re.I) else False 490 491 if CategoriesMode: 492 MiscUtil.PrintInfo("\nResNum, ResName, Phi, Psi") 493 else: 494 MiscUtil.PrintInfo("\nResNum, ResName, Phi, Psi, Category") 495 496 Precision = OptionsInfo["PhiPsiPrecision"] 497 for ResNum in PhiPsiResiduesInfo["ResNums"]: 498 ResName = PhiPsiResiduesInfo["ResName"][ResNum] 499 Phi = PhiPsiResiduesInfo["Phi"][ResNum] 500 Psi = PhiPsiResiduesInfo["Psi"][ResNum] 501 if CategoriesMode: 502 MiscUtil.PrintInfo("%s, %s, %.*f, %.*f" % (ResNum, ResName, Precision, Phi, Precision, Psi)) 503 else: 504 Category = PhiPsiResiduesInfo["Category"][ResNum] 505 MiscUtil.PrintInfo("%s, %s, %.*f, %.*f, %s " % (ResNum, ResName, Precision, Phi, Precision, Psi, Category)) 506 507 def ListInterfaceResiduesInfo(MolName, ChainIDs): 508 """List interface residues between all unique pairs of polymer chains 509 with in a molecule.""" 510 511 if not (OptionsInfo["All"] or OptionsInfo["InterfaceResidues"]): 512 return 513 514 MiscUtil.PrintInfo("\nListing interface residues information...") 515 516 # Get chain ID pairs for identifying interface residues... 517 ChainIDsPairs = GetChainIDsPairsForInterfaceResidues(ChainIDs) 518 if not len(ChainIDsPairs): 519 MiscUtil.PrintInfo("Valid interface chain ID pairs: None") 520 return 521 522 InterfaceResiduesMethod = OptionsInfo["InterfaceResiduesMethod"] 523 InterfaceResiduesCutoff = OptionsInfo["InterfaceResiduesCutoff"] 524 MiscUtil.PrintInfo("Methodology: %s; Cutoff: %.2f" % (InterfaceResiduesMethod, InterfaceResiduesCutoff)) 525 526 for ChainIDsPair in ChainIDsPairs: 527 InterfaceChainIDs1, InterfaceChainIDs2 = ChainIDsPair 528 InterfaceID = "%s-%s" % ("+".join(InterfaceChainIDs1), "+".join(InterfaceChainIDs2)) 529 530 InterfaceResiduesInfo1, InterfaceResiduesInfo2 = GetInterfaceChainsAndResiduesInfo(MolName, InterfaceChainIDs1, MolName, InterfaceChainIDs2, InterfaceResiduesMethod, InterfaceResiduesCutoff) 531 532 ChainNames1, ResiduesInfo1 = SetupSelectionChainsResiduesInfo(InterfaceResiduesInfo1) 533 ChainNames2, ResiduesInfo2 = SetupSelectionChainsResiduesInfo(InterfaceResiduesInfo2) 534 535 if len(ChainNames1) and len(ChainNames2): 536 MiscUtil.PrintInfo("\nListing interface residues for interface chain IDs: %s" % (InterfaceID)) 537 538 ListInterfaceChainsAndResiduesInfo(InterfaceID, InterfaceChainIDs1, ChainNames1, ResiduesInfo1) 539 ListInterfaceChainsAndResiduesInfo(InterfaceID, InterfaceChainIDs2, ChainNames2, ResiduesInfo2) 540 else: 541 MiscUtil.PrintInfo("\nListing interface residues for interface chain IDs: %s" % (InterfaceID)) 542 MiscUtil.PrintInfo("Interface chain IDs: None; ChainID: None; Number of interface residues: 0") 543 544 def ListInterfaceChainsAndResiduesInfo(InterfaceID, InterfaceChainIDs, ChainNames, ResiduesInfo): 545 """List interface chains and residues.""" 546 547 for ChainID in InterfaceChainIDs: 548 if not ChainID in ChainNames: 549 MiscUtil.PrintInfo("\nInterface chain IDs: %s; ChainID: %s; Number of interface residues: 0" % (InterfaceID, ChainID)) 550 continue 551 552 for Index in range(0, len(ChainNames)): 553 ChainName = ChainNames[Index] 554 ChainResiduesInfo = ResiduesInfo[Index] 555 if re.match(ChainID, ChainName, re.I): 556 MiscUtil.PrintInfo("\nInterface chain IDs: %s; ChainID: %s; Number of interface residues: %d" % (InterfaceID, ChainName, ChainResiduesInfo[0])) 557 MiscUtil.PrintInfo("Residue distribution: %s\nResidue IDs: %s" % (ChainResiduesInfo[1], ChainResiduesInfo[2])) 558 continue 559 560 def GetInterfaceChainsAndResiduesInfo(MolName1, ChainIDs1, MolName2, ChainIDs2, Method, Cutoff): 561 """Get interface chains and residues info for chains using a specified methodology.""" 562 563 InterfaceChainsResiduesInfo1 = None 564 InterfaceChainsResiduesInfo2 = None 565 566 ChainNames1 = ",".join(ChainIDs1) 567 ChainNames2 = ",".join(ChainIDs2) 568 569 if re.match("^BySASAChange$", Method, re.I): 570 InterfaceChainsResiduesInfo1, InterfaceChainsResiduesInfo2 = PyMOLUtil.GetInterfaceChainsResiduesBySASAChange(MolName1, ChainNames1, MolName2, ChainNames2, Cutoff) 571 elif re.match("^ByHeavyAtomsDistance$", Method, re.I): 572 InterfaceChainsResiduesInfo1, InterfaceChainsResiduesInfo2 = PyMOLUtil.GetInterfaceChainsResiduesByHeavyAtomsDistance(MolName1, ChainNames1, MolName2, ChainNames2, Cutoff) 573 elif re.match("^ByCAlphaAtomsDistance$", Method, re.I): 574 InterfaceChainsResiduesInfo1, InterfaceChainsResiduesInfo2 = PyMOLUtil.GetInterfaceChainsResiduesByCAlphaAtomsDistance(MolName1, ChainNames1, MolName2, ChainNames2, Cutoff) 575 else: 576 MiscUtil.PrintError("Failed to retrieve interface residues information: Method %s is not valid..." % Method) 577 578 return InterfaceChainsResiduesInfo1, InterfaceChainsResiduesInfo2 579 580 def GetChainIDsPairsForInterfaceResidues(ChainIDs): 581 """Get chain IDs pairs for identifying interface residues.""" 582 583 ChainIDsPairsList = [] 584 585 InterfaceResiduesChainsList = OptionsInfo["InterfaceResiduesChainsList"] 586 if not len(InterfaceResiduesChainsList): 587 # Use first two chain IDs... 588 if len(ChainIDs) >= 2: 589 ChainIDsPair = [ChainIDs[0], ChainIDs[1]] 590 ChainIDsPairsList.append(ChainIDsPair) 591 return ChainIDsPairsList 592 593 # Validate specified pairwise chain IDs... 594 for Index in range(0, len(InterfaceResiduesChainsList), 2): 595 ChainIDs1 = InterfaceResiduesChainsList[Index] 596 ChainIDs2 = InterfaceResiduesChainsList[Index + 1] 597 598 ValidChainIDs = True 599 SpecifiedChainIDs = [] 600 SpecifiedChainIDs.extend(ChainIDs1) 601 SpecifiedChainIDs.extend(ChainIDs2) 602 603 for ChainID in (SpecifiedChainIDs): 604 if not ChainID in ChainIDs: 605 ValidChainIDs = False 606 MiscUtil.PrintWarning("The chain ID, %s, specified using \"--interfaceResiduesChains\" for a chain IDs pairs is not a valid chain ID." % (ChainID)) 607 608 if not ValidChainIDs: 609 MiscUtil.PrintWarning("Ignoring chain IDs pair: %s, %s" % ("+".join(ChainIDs1), "+".join(ChainIDs2))) 610 continue 611 612 ChainIDsPair = [ChainIDs1, ChainIDs2] 613 ChainIDsPairsList.append(ChainIDsPair) 614 615 return ChainIDsPairsList 616 617 def SetupSelectionResiduesInfo(SelectionInfo): 618 """Setup residues info.""" 619 620 # Setup distribution of residues... 621 LineWords = [] 622 ResiduesCount = 0 623 SortedResNames = sorted(SelectionInfo["ResNames"], key = lambda ResName: SelectionInfo["ResCount"][ResName], reverse = True) 624 for ResName in SortedResNames: 625 ResCount = SelectionInfo["ResCount"][ResName] 626 LineWords.append("%s - %s" % (ResName, ResCount)) 627 ResiduesCount += ResCount 628 629 ResiduesDistribution = "; ".join(LineWords) if len(LineWords) else None 630 631 # Setup residue IDs sorted by residue numbers... 632 ResNumMap = {} 633 for ResName in SelectionInfo["ResNames"]: 634 for ResNum in SelectionInfo["ResNum"][ResName]: 635 ResNumMap[ResNum] = ResName 636 637 LineWords = [] 638 for ResNum in sorted(ResNumMap, key = int): 639 ResName = ResNumMap[ResNum] 640 ResID = "%s_%s" % (ResName, ResNum) 641 LineWords.append(ResID) 642 ResiduesIDs = ", ".join(LineWords) if len(LineWords) else None 643 644 return ResiduesCount, ResiduesDistribution, ResiduesIDs 645 646 def SetupSelectionChainsResiduesInfo(SelectionInfo): 647 """Setup chains and residues info.""" 648 649 ChainNames = [] 650 ResiduesInfo = [] 651 652 for ChainID in SelectionInfo["ChainIDs"]: 653 ChainNames.append(ChainID) 654 655 # Setup distribution of residues... 656 LineWords = [] 657 ResiduesCount = 0 658 SortedResNames = sorted(SelectionInfo["ResNames"][ChainID], key = lambda ResName: SelectionInfo["ResCount"][ChainID][ResName], reverse = True) 659 for ResName in SortedResNames: 660 ResCount = SelectionInfo["ResCount"][ChainID][ResName] 661 LineWords.append("%s - %s" % (ResName, ResCount)) 662 ResiduesCount += ResCount 663 664 ResiduesDistribution = "; ".join(LineWords) if len(LineWords) else None 665 666 # Setup residue IDs sorted by residue numbers... 667 ResNumMap = {} 668 for ResName in SelectionInfo["ResNames"][ChainID]: 669 for ResNum in SelectionInfo["ResNum"][ChainID][ResName]: 670 ResNumMap[ResNum] = ResName 671 672 LineWords = [] 673 for ResNum in sorted(ResNumMap, key = int): 674 ResName = ResNumMap[ResNum] 675 ResID = "%s_%s" % (ResName, ResNum) 676 LineWords.append(ResID) 677 ResiduesIDs = ", ".join(LineWords) if len(LineWords) else None 678 679 ResiduesInfo.append([ResiduesCount, ResiduesDistribution, ResiduesIDs]) 680 681 return ChainNames, ResiduesInfo 682 683 def ListBoundingBoxInfo(MolName): 684 """List bounding box information.""" 685 686 if not (OptionsInfo["All"] or OptionsInfo["BoundingBox"]): 687 return 688 689 MolSelection = "(%s)" % MolName 690 MolExtents = pymol.cmd.get_extent(MolSelection) 691 692 XMin, YMin, ZMin = MolExtents[0] 693 XMax, YMax, ZMax = MolExtents[1] 694 695 XSize = abs(XMax - XMin) 696 YSize = abs(YMax - YMin) 697 ZSize = abs(ZMax - ZMin) 698 699 MiscUtil.PrintInfo("\nBounding box coordinates: <XMin, XMax> - <%.3f, %.3f>; <YMin, YMax> - <%.3f, %.3f>; <ZMin, ZMax> - <%.3f, %.3f>" % (XMin, XMax, YMin, YMax, ZMin, ZMax)) 700 MiscUtil.PrintInfo("Bounding box size in Angstroms: XSize - %.3f; YSize - %.3f; ZSize - %.3f" % (XSize, YSize, ZSize)) 701 702 def ListCentroid(MolName): 703 """List centroid information.""" 704 705 if not (OptionsInfo["All"] or OptionsInfo["Centroid"]): 706 return 707 708 MolSelection = "(%s)" % MolName 709 Centroid = PyMOLUtil.GetCentroid(MolSelection) 710 711 MiscUtil.PrintInfo("\nCentroid: <%.3f, %.3f, %.3f>" % (Centroid[0], Centroid[1], Centroid[2])) 712 713 def ListFileSizeAndModificationInfo(Infile): 714 """List file size and modification time info.""" 715 716 MiscUtil.PrintInfo("\nFile size: %s" % MiscUtil.GetFormattedFileSize(Infile)) 717 MiscUtil.PrintInfo("Last modified: %s" % time.ctime(os.path.getmtime(Infile))) 718 MiscUtil.PrintInfo("Created: %s" % time.ctime(os.path.getctime(Infile))) 719 720 def GetPocketSelectionResiduesInfoLabel(SelectionType): 721 """Get pocket residues info label for a specified selection type.""" 722 723 SelectionLabel = None 724 725 if re.match("^Pockets$", SelectionType, re.I): 726 SelectionLabel = "polymer" 727 elif re.match("^PocketSolvents$", SelectionType, re.I): 728 SelectionLabel = "solvent" 729 elif re.match("^PocketInorganics$", SelectionType, re.I): 730 SelectionLabel = "inorganic" 731 else: 732 MiscUtil.PrintError("Failed to retrieve pocket residues label information: Selection type %s is not valid..." % SelectionType) 733 734 return SelectionLabel 735 736 def ProcessOptions(): 737 """Process and validate command line arguments and options.""" 738 739 MiscUtil.PrintInfo("Processing options...") 740 741 # Validate options... 742 ValidateOptions() 743 744 OptionsInfo["All"] = Options["--all"] 745 OptionsInfo["BoundingBox"] = Options["--boundingBox"] 746 OptionsInfo["Centroid"] = Options["--centroid"] 747 748 OptionsInfo["Chains"] = Options["--chains"] 749 750 OptionsInfo["CountResidues"] = Options["--countResidues"] 751 OptionsInfo["Header"] = Options["--header"] 752 753 OptionsInfo["Infiles"] = Options["--infiles"] 754 OptionsInfo["InfilesNames"] = Options["--infilesNames"] 755 756 OptionsInfo["Inorganics"] = Options["--inorganics"] 757 758 OptionsInfo["InterfaceResidues"] = Options["--interfaceResidues"] 759 OptionsInfo["InterfaceResiduesMethod"] = Options["--interfaceResiduesMethod"] 760 761 InterfaceResiduesChains = Options["--interfaceResiduesChains"] 762 InterfaceResiduesChainsList = [] 763 if not re.match("^auto$", InterfaceResiduesChains, re.I): 764 InterfaceResiduesChains = re.sub(" ", "", Options["--interfaceResiduesChains"]) 765 InterfaceResiduesChainsWords = InterfaceResiduesChains.split(",") 766 if len(InterfaceResiduesChainsWords) % 2: 767 MiscUtil.PrintError("The number of comma delimited chain IDs, %d, specified using \"--interfaceResiduesChains\" option, \"%s\", must be a multple of 2." % (len(InterfaceResiduesChainsWords), Options["--interfaceResiduesChains"])) 768 for ChainID in InterfaceResiduesChainsWords: 769 ChainIDWords = ChainID.split("+") 770 InterfaceResiduesChainsList.append(ChainIDWords) 771 OptionsInfo["InterfaceResiduesChains"] = InterfaceResiduesChains 772 OptionsInfo["InterfaceResiduesChainsList"] = InterfaceResiduesChainsList 773 774 InterfaceResiduesCutoff = Options["--interfaceResiduesCutoff"] 775 InterfaceResiduesMethod = OptionsInfo["InterfaceResiduesMethod"] 776 if re.match("^auto$", InterfaceResiduesCutoff, re.I): 777 if re.match("^BySASAChange$", InterfaceResiduesMethod, re.I): 778 InterfaceResiduesCutoff = 1.0 779 elif re.match("^ByHeavyAtomsDistance$", InterfaceResiduesMethod, re.I): 780 InterfaceResiduesCutoff = 5.0 781 elif re.match("^ByCAlphaAtomsDistance$", InterfaceResiduesMethod, re.I): 782 InterfaceResiduesCutoff = 8.0 783 else: 784 MiscUtil.PrintError("The specified value, %s, for option \"--interfaceResiduesMethod\" is not supported." % (InterfaceResiduesMethod)) 785 else: 786 InterfaceResiduesCutoff = float(InterfaceResiduesCutoff) 787 OptionsInfo["InterfaceResiduesCutoff"] = InterfaceResiduesCutoff 788 789 OptionsInfo["Ligands"] = Options["--ligands"] 790 791 OptionsInfo["PocketLigands"] = Options["--pocketLigands"] 792 OptionsInfo["PocketDistanceCutoff"] = float(Options["--pocketDistanceCutoff"]) 793 OptionsInfo["PocketSolvents"] = Options["--pocketSolvents"] 794 OptionsInfo["PocketInorganics"] = Options["--pocketInorganics"] 795 796 OptionsInfo["PhiPsi"] = Options["--phiPsi"] 797 OptionsInfo["PhiPsiMode"] = Options["--phiPsiMode"] 798 OptionsInfo["PhiPsiPrecision"] = int(Options["--phiPsiPrecision"]) 799 800 OptionsInfo["Solvents"] = Options["--solvents"] 801 802 OptionsInfo["SurfaceResidues"] = Options["--surfaceResidues"] 803 OptionsInfo["SurfaceResiduesCutoff"] = float(Options["--surfaceResiduesCutoff"]) 804 OptionsInfo["SurfaceResiduesIDs"] = True if re.match("^Yes$", Options["--surfaceResiduesIDs"], re.I) else False 805 806 # Always list header, chains, and ligands... 807 OptionNames = ["Chains", "Header", "Ligands"] 808 for Name in OptionNames: 809 if Name in OptionsInfo: 810 OptionsInfo[Name] = True 811 else: 812 MiscUtil.PrintError("Option name %s is not a valid name..." % s) 813 814 def RetrieveOptions(): 815 """Retrieve command line arguments and options.""" 816 817 # Get options... 818 global Options 819 Options = docopt(_docoptUsage_) 820 821 # Set current working directory to the specified directory... 822 WorkingDir = Options["--workingdir"] 823 if WorkingDir: 824 os.chdir(WorkingDir) 825 826 # Handle examples option... 827 if "--examples" in Options and Options["--examples"]: 828 MiscUtil.PrintInfo(MiscUtil.GetExamplesTextFromDocOptText(_docoptUsage_)) 829 sys.exit(0) 830 831 def ValidateOptions(): 832 """Validate option values.""" 833 834 # Expand infile names.. 835 InfilesNames = MiscUtil.ExpandFileNames(Options["--infiles"], ",") 836 837 # Validate file extensions... 838 for Infile in InfilesNames: 839 MiscUtil.ValidateOptionFilePath("-i, --infiles", Infile) 840 MiscUtil.ValidateOptionFileExt("-i, --infiles", Infile, "pdb cif") 841 Options["--infilesNames"] = InfilesNames 842 843 if not re.match("^auto$", Options["--interfaceResiduesCutoff"], re.I): 844 MiscUtil.ValidateOptionFloatValue("--interfaceResiduesCutoff", Options["--interfaceResiduesCutoff"], {">": 0.0}) 845 MiscUtil.ValidateOptionTextValue("--interfaceResiduesMethod", Options["--interfaceResiduesMethod"], "BySASAChange ByHeavyAtomsDistance ByCAlphaAtomsDistance") 846 847 MiscUtil.ValidateOptionFloatValue("--pocketDistanceCutoff", Options["--pocketDistanceCutoff"], {">": 0.0}) 848 MiscUtil.ValidateOptionTextValue("--phiPsiMode", Options["--phiPsiMode"], "All Categories") 849 MiscUtil.ValidateOptionIntegerValue("--phiPsiPrecision", Options["--phiPsiPrecision"], {">": 0}) 850 MiscUtil.ValidateOptionFloatValue("--surfaceResiduesCutoff", Options["--surfaceResiduesCutoff"], {">": 0.0}) 851 MiscUtil.ValidateOptionTextValue("--surfaceResiduesIDs", Options["--surfaceResiduesIDs"], "Yes No") 852 853 # Setup a usage string for docopt... 854 _docoptUsage_ = """ 855 PyMOLInfoMacromolecules.py - List information about macromolecules 856 857 Usage: 858 PyMOLInfoMacromolecules.py [--all] [--boundingBox] [--centroid] [--chains] 859 [--countResidues] [--header] [--inorganics] [--interfaceResidues] 860 [--interfaceResiduesChains <ChainID1,ChainD2,...>] [--interfaceResiduesMethod <text>] 861 [--interfaceResiduesCutoff <number>] [--ligands] [--pocketLigands] 862 [--pocketDistanceCutoff <number>] [--pocketSolvents] [--pocketInorganics] 863 [--phiPsi] [--phiPsiMode <All or Categories>] [--phiPsiPrecision <number>] 864 [--surfaceResidues] [--surfaceResiduesCutoff <number>] [--surfaceResiduesIDs <yes or no>] 865 [--solvents] [-w <dir>] -i <infile1,infile2,infile3...> 866 PyMOLInfoMacromolecules.py -h | --help | -e | --examples 867 868 Description: 869 List information regarding ID, classification, experimental technique, chains, 870 solvents, inorganics, ligands, and ligand binding pockets in macromolecules 871 present including proteins and nucleic acids. 872 873 The supported input file format are: PDB (.pdb), mmCIF (.cif) 874 875 Options: 876 -a, --all 877 All available information. 878 -b, --boundingBox 879 Min and max coordinates for bounding box along with its size. 880 -c, --chains 881 Number of chains and their IDs. This is also default behavior. 882 --centroid 883 Centroid of atomic coordinates. It corresponds to the mean of all 3D 884 coordinates in input file. 885 --countResidues 886 Number of residues across chains. The chain residues are identified 887 using polymer selection operator available in PyMOL. In addition, 888 the non-standard amino acid residues are listed. 889 -e, --examples 890 Print examples. 891 -h, --help 892 Print this help message. 893 --header 894 Header information including experimental technique information 895 along with any available resolution. This is also default behavior. 896 -i, --infiles <infile1,infile2,infile3...> 897 A comma delimited list of input files. The wildcards are also allowed 898 in file names. 899 --inorganics 900 Inorganic residues across chains. The inorganic residues are identified 901 using inorganic selection operator available in PyMOL. 902 --interfaceResidues 903 Interface residues between specified pairs of chains. 904 --interfaceResiduesChains <ChainID1,Chain1D2,...> [default: Auto] 905 Pairwise comma delimited list of chain IDs for the identification of 906 interface residues. Each chain ID may contain mutiple chain IDs 907 delimited by a plus sign. For example: A+B,C+D chain pair specifies 908 interface between chain complexes A+B and C+D. 909 910 The interface residues are identified between first two chains in 911 input files by default. 912 --interfaceResiduesMethod <text> [default: BySASAChange] 913 Methodology for the identification of interface residues between a pair 914 of chains in an input file. The interface residues may be identified by 915 change in solvent accessible surface area (SASA) for a residue between 916 a chain and chains complex, distance between heavy atoms 917 in two chains, or distance between CAlpha atoms. Possible values: 918 BySASAChange, ByHeavyAtomsDistance, or ByCAlphaAtomsDistance. 919 --interfaceResiduesCutoff <number> [default: auto] 920 Cutoff value used by different methodologies during identification of 921 interface residues between a pair of chains. The default values are 922 shown below: 923 924 BySASAChange: 1.0; Units: Angstrom**2 [ Ref 141 ] 925 ByHeavyAtomsDistance: 5.0; Units: Angstrom [ Ref 142 ] 926 ByCAlphaAtomsDistance: 8.0; Units: Angstrom [ Ref 143 ] 927 928 -l, --ligands 929 Ligands across chains. This is also default behavior. The ligands 930 residues are identified using organic selection operator available 931 in PyMOL. 932 -p, --pocketLigands 933 Chain residues in ligand pockets. 934 --pocketDistanceCutoff <number> [default: 5.0] 935 Distance in Angstroms for identifying pocket residues around ligands. 936 --pocketSolvents 937 Solvent residues in ligand pockets. The solvent residues are identified 938 using solvent selection operator available in PyMOL. 939 --pocketInorganics 940 Inorganic residues in ligand pockets. The inorganic residues are identified 941 using Inorganic selection operator available in PyMOL. 942 --phiPsi 943 Phi and psi torsion angles across chains in macromolecules containing 944 amino acids. 945 --phiPsiMode <All or Categories> [default: Categories] 946 List all phi and psi torsion angles for residues as a single group or split 947 them into the following categories corresponding to four types of 948 Ramachandran plots: 949 950 General: All residues except glycine, proline, or pre-proline 951 Glycine: Only glycine residues 952 Proline: Only proline residues 953 Pre-Proline: Only residues before proline not including glycine 954 or proline 955 956 --phiPsiPrecision <number> [default: 2] 957 Precision for listing phi and psi torsion angles. 958 -s, --solvents 959 Solvent residues across chains. The solvent residues are identified 960 using solvent selection operator available in PyMOL. 961 --surfaceResidues 962 Surface and buried residues in chains. 963 --surfaceResiduesCutoff <number> [default: 2.5] 964 Solvenet Accessible Surface Area (SASA) cutoff value in Angstroms**2 965 for surface and buried resiudes in chains. The residues with SASA less than 966 the cutoff value correspond to burried residues. 967 --surfaceResiduesIDs <yes or no> [default: No] 968 List residue IDs for surface and buried residues during listing of the 969 distribution of these residues for '--surfaceResidues' option. 970 -w, --workingdir <dir> 971 Location of working directory which defaults to the current directory. 972 973 Examples: 974 To list header, chains, and ligand information for macromolecules in input 975 file, type: 976 977 % PyMOLInfoMacromolecules.py -i Sample3.pdb 978 979 To list all available information for macromolecules in input files, type: 980 981 % PyMOLInfoMacromolecules.py -a -i "Sample3.pdb,Sample4.pdb" 982 983 To list pockets residues information along with other default information 984 for marcomolecules in input file, type: 985 986 % PyMOLInfoMacromolecules.py -p --pocketDistanceCutoff 4.5 987 --pocketSolvents --pocketInorganics -i Sample3.pdb 988 989 To list chain residues information along with other default information 990 for marcomolecules in input file, type: 991 992 % PyMOLInfoMacromolecules.py -c --countResidues --solvents 993 --inorganics -i "Sample3.pdb,Sample4.pdb" 994 995 To list interface residues between first two chains by SASA change for 996 marcomolecules in input file, type: 997 998 % PyMOLInfoMacromolecules.py --interfaceResidues 999 -i Sample3.pdb 1000 1001 To list interface residues between chains E and I by heay atoms 1002 distance for marcomolecules in input file, type: 1003 1004 % PyMOLInfoMacromolecules.py --interfaceResidues 1005 --interfaceResiduesChains E,I --interfaceResiduesMethod 1006 ByHeavyAtomsDistance --interfaceResiduesCutoff 5 -i Sample3.pdb 1007 1008 To list interface residues between two sets of chains by SASA change for 1009 marcomolecules in input file, type: 1010 1011 % PyMOLInfoMacromolecules.py --interfaceResidues 1012 --interfaceResiduesChains "A+B,C+D" -i Sample8.pdb 1013 1014 Author: 1015 Manish Sud(msud@san.rr.com) 1016 1017 See also: 1018 DownloadPDBFiles.pl, PyMOLSplitChainsAndLigands.py, 1019 PyMOLVisualizeMacromolecules.py 1020 1021 Copyright: 1022 Copyright (C) 2024 Manish Sud. All rights reserved. 1023 1024 The functionality available in this script is implemented using PyMOL, a 1025 molecular visualization system on an open source foundation originally 1026 developed by Warren DeLano. 1027 1028 This file is part of MayaChemTools. 1029 1030 MayaChemTools is free software; you can redistribute it and/or modify it under 1031 the terms of the GNU Lesser General Public License as published by the Free 1032 Software Foundation; either version 3 of the License, or (at your option) any 1033 later version. 1034 1035 """ 1036 1037 if __name__ == "__main__": 1038 main()