MayaChemTools

   1 #!/bin/env python
   2 #
   3 # File: PyMOLCalculateRMSD.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     CalculateRMSDValues()
  79     
  80     MiscUtil.PrintInfo("\n%s: Done...\n" % ScriptName)
  81     MiscUtil.PrintInfo("Total time: %s" % MiscUtil.GetFormattedElapsedTime(WallClockTime, ProcessorTime))
  82 
  83 def CalculateRMSDValues():
  84     """Calculate RMSD between reference and probe files."""
  85 
  86     Outfile = OptionsInfo["Outfile"]
  87     OutDelim = OptionsInfo["OutDelim"]
  88     
  89     MiscUtil.PrintInfo("\nGenerating file %s..." % Outfile)
  90     OutFH = open(Outfile, "w")
  91     if OutFH is None:
  92         MiscUtil.PrintError("Couldn't open output file: %s.\n" % (Outfile))
  93 
  94     WriteColumnLabels(OutFH, OutDelim)
  95     
  96     pymol.cmd.reinitialize()
  97     if re.match("^OneToOne$", OptionsInfo["Mode"], re.I):
  98         CalculateOneToOneRMSDValues(OutFH, OutDelim)
  99     elif re.match("^AllToAll$", OptionsInfo["Mode"], re.I):
 100         CalculateAllToAllRMSDValues(OutFH, OutDelim)
 101     elif re.match("^FirstToAll$", OptionsInfo["Mode"], re.I):
 102         CalculateFirstToAllRMSDValues(OutFH, OutDelim)
 103     else:
 104         MiscUtil.PrintError("RMSD couldn't be calculated: Specified mode, %s, is not supported" % OptionsInfo["Mode"])
 105 
 106     OutFH.close()
 107 
 108 def CalculateOneToOneRMSDValues(OutFH, OutDelim):
 109     """Calculate pairwise RMSD values."""
 110     
 111     RefFilesCount = len(OptionsInfo["RefFilesNames"])
 112     ProbeFilesCount = len(OptionsInfo["ProbeFilesNames"])
 113 
 114     FilesCount = ProbeFilesCount if RefFilesCount > ProbeFilesCount else RefFilesCount
 115     
 116     if RefFilesCount != ProbeFilesCount:
 117         MiscUtil.PrintWarning("Number of reference files, %d,  is not equal to number of probe files, %d .\n" % (RefFilesCount, ProbeFilesCount))
 118         MiscUtil.PrintWarning("Pairwise RMSD will be calculated only for first %s files.\n" % (FilesCount))
 119 
 120     # Process files...
 121     for FileIndex in range(0, FilesCount):
 122         RefFileIndex = FileIndex
 123         ProbeFileIndex = FileIndex
 124         
 125         LoadRefFile(RefFileIndex)
 126         LoadProbeFile(ProbeFileIndex)
 127         
 128         RMSD = CalculateRMSDValue(RefFileIndex, ProbeFileIndex)
 129         
 130         RefID = OptionsInfo["RefFilesInfo"]["FilesRoots"][RefFileIndex]
 131         ProbeID = OptionsInfo["ProbeFilesInfo"]["FilesRoots"][ProbeFileIndex]
 132         Line = "%s%s%s%s%s\n" % (RefID, OutDelim, ProbeID, OutDelim, RMSD)
 133         OutFH.write(Line)
 134         
 135         DeleteRefObject(RefFileIndex)
 136         DeleteProbeObject(ProbeFileIndex)
 137         
 138 def CalculateAllToAllRMSDValues(OutFH, OutDelim):
 139     """Calculate RMSD values between all pairs of files."""
 140     
 141     RefFilesCount = len(OptionsInfo["RefFilesNames"])
 142     ProbeFilesCount = len(OptionsInfo["ProbeFilesNames"])
 143     OutMatrix = OptionsInfo["OutMatrix"]
 144     
 145     for RefFileIndex in range(0, RefFilesCount):
 146         LoadRefFile(RefFileIndex)
 147         RefID = OptionsInfo["RefFilesInfo"]["FilesRoots"][RefFileIndex]
 148 
 149         LineWords = []
 150         if OutMatrix:
 151             LineWords.append(RefID)
 152             
 153         for ProbeFileIndex in range(0, ProbeFilesCount):
 154             LoadProbeFile(ProbeFileIndex)
 155             RMSD = CalculateRMSDValue(RefFileIndex, ProbeFileIndex)
 156             DeleteProbeObject(ProbeFileIndex)
 157             
 158             if OutMatrix:
 159                 LineWords.append(RMSD)
 160             else:
 161                 ProbeID = OptionsInfo["ProbeFilesInfo"]["FilesRoots"][ProbeFileIndex]
 162                 Line = "%s%s%s%s%s\n" % (RefID, OutDelim, ProbeID, OutDelim, RMSD)
 163                 OutFH.write(Line)
 164         
 165         DeleteRefObject(RefFileIndex)
 166         
 167         if OutMatrix:
 168             Line = OutDelim.join(LineWords)
 169             OutFH.write("%s\n" % Line)
 170 
 171 def CalculateFirstToAllRMSDValues(OutFH, OutDelim):
 172     """Calculate RMSD values between first reference file and all probe files."""
 173 
 174     # Setup reference...
 175     RefFileIndex = 0
 176     RefID = OptionsInfo["RefFilesInfo"]["FilesRoots"][RefFileIndex]
 177     LoadRefFile(RefFileIndex)
 178 
 179     # Go over probe files...
 180     for ProbeFileIndex in range(0, len(OptionsInfo["ProbeFilesNames"])):
 181         LoadProbeFile(ProbeFileIndex)
 182         
 183         RMSD = CalculateRMSDValue(RefFileIndex, ProbeFileIndex)
 184         
 185         ProbeID = OptionsInfo["ProbeFilesInfo"]["FilesRoots"][ProbeFileIndex]
 186         Line = "%s%s%s%s%s\n" % (RefID, OutDelim, ProbeID, OutDelim, RMSD)
 187         OutFH.write(Line)
 188         
 189         DeleteProbeObject(ProbeFileIndex)
 190 
 191     DeleteRefObject(RefFileIndex)
 192 
 193 def WriteColumnLabels(OutFH, OutDelim):
 194     """Write out column labels."""
 195 
 196     ColLabels = []
 197     
 198     if re.match("^AllToAll$", OptionsInfo["Mode"], re.I) and OptionsInfo["OutMatrix"]:
 199         ColLabels.append("")
 200         ColLabels.extend(OptionsInfo["ProbeFilesInfo"]["FilesRoots"])
 201     else:
 202         ColLabels = ["RefFileID", "ProbeFileID", "RMSD"]
 203     
 204     Line = OutDelim.join(ColLabels)
 205     OutFH.write("%s\n" % Line)
 206     
 207 def LoadRefFile(RefFileIndex):
 208     """Load reference file."""
 209     
 210     RefFile = OptionsInfo["RefFilesNames"][RefFileIndex]
 211     RefName = OptionsInfo["RefFilesInfo"]["PyMOLObjectNames"][RefFileIndex]
 212     LoadFile(RefFile, RefName)
 213     
 214 def LoadProbeFile(ProbeFileIndex):
 215     """Load probe file."""
 216     
 217     ProbeFile = OptionsInfo["ProbeFilesNames"][ProbeFileIndex]
 218     ProbeName = OptionsInfo["ProbeFilesInfo"]["PyMOLObjectNames"][ProbeFileIndex]
 219     LoadFile(ProbeFile, ProbeName)
 220 
 221 def LoadFile(FileName, ObjectName):
 222     """Load a file."""
 223     
 224     pymol.cmd.load(FileName, ObjectName)
 225     
 226 def DeleteRefObject(RefFileIndex):
 227     """Delete reference object."""
 228     
 229     RefName = OptionsInfo["RefFilesInfo"]["PyMOLObjectNames"][RefFileIndex]
 230     DeleteObject(RefName)
 231     
 232 def DeleteProbeObject(ProbeFileIndex):
 233     """Delete probe object."""
 234     
 235     ProbeName = OptionsInfo["ProbeFilesInfo"]["PyMOLObjectNames"][ProbeFileIndex]
 236     DeleteObject(ProbeName)
 237 
 238 def DeleteObject(Name):
 239     """Delete PyMOL object."""
 240     
 241     pymol.cmd.delete(Name)
 242     
 243 def CalculateRMSDValue(RefFileIndex, ProbeFileIndex):
 244     """Calculate RMSD value between referece and probe objects."""
 245 
 246     RefName = OptionsInfo["RefFilesInfo"]["PyMOLObjectNames"][RefFileIndex]
 247     ProbeName = OptionsInfo["ProbeFilesInfo"]["PyMOLObjectNames"][ProbeFileIndex]
 248     
 249     if re.match("^FirstChain$", OptionsInfo["AlignMode"], re.I):
 250         RefFirstChainID = OptionsInfo["RefFilesInfo"]["ChainIDs"][RefFileIndex][0]
 251         RefSelection = "(%s and chain %s)" % (RefName, RefFirstChainID)
 252         
 253         ProbeFirstChainID = OptionsInfo["ProbeFilesInfo"]["ChainIDs"][ProbeFileIndex][0]
 254         ProbeSelection = "(%s and chain %s)" % (ProbeName, ProbeFirstChainID)
 255     else:
 256         RefSelection = RefName
 257         ProbeSelection = ProbeName
 258         
 259     RMSD = CalculateRMSD(RefSelection, ProbeSelection, OptionsInfo["AlignMethod"])
 260 
 261     return RMSD
 262 
 263 def CalculateRMSD(RefSelectionName, ProbeSelectionName, AlignMethod):
 264     """Calculate RMSD between two selections after aligning the selections."""
 265     
 266     if re.match("^align$", AlignMethod, re.I):
 267         Results = pymol.cmd.align(ProbeSelectionName, RefSelectionName)
 268         RMSD = Results[0]
 269     elif re.match("^cealign$", AlignMethod, re.I):
 270         Results = pymol.cmd.cealign(RefSelectionName, ProbeSelectionName)
 271         RMSD = Results["RMSD"]
 272     elif re.match("^super$", AlignMethod, re.I):
 273         Results = pymol.cmd.super(ProbeSelectionName, RefSelectionName)
 274         RMSD = Results[0]
 275     else:
 276         RMSD = None
 277         MiscUtil.PrintWarning("Failed to calculate RMSD. Unknown alignment method: %s" % AlignMethod)
 278     
 279     if RMSD is not None:
 280         RMSD = "%.2f" % RMSD
 281     
 282     return RMSD
 283 
 284 def RetrieveProbeFilesInfo():
 285     """Retrieve information for probe input files."""
 286 
 287     RetrieveInfilesInfo("ProbeFiles")
 288     
 289 def RetrieveRefFilesInfo():
 290     """Retrieve information for reference input files."""
 291 
 292     RetrieveInfilesInfo("RefFiles")
 293     
 294 def RetrieveInfilesInfo(InfilesMode):
 295     """Retrieve information for input files."""
 296 
 297     if re.match("^ProbeFiles$", InfilesMode, re.I):
 298         MiscUtil.PrintInfo("Retrieving information for probe files...")
 299         InfilesNames = OptionsInfo["ProbeFilesNames"]
 300         NameSuffix = "_Probe"
 301     elif re.match("^RefFiles$", InfilesMode, re.I):
 302         MiscUtil.PrintInfo("Retrieving information for reference files...")
 303         InfilesNames = OptionsInfo["RefFilesNames"]
 304         NameSuffix = "_Ref"
 305     else:
 306         MiscUtil.PrintError("Internal Error: Unknown infiles mode: %s" % InfilesMode)
 307     
 308     InfilesInfo = {}
 309     
 310     InfilesInfo["FilesNames"] = []
 311     InfilesInfo["FilesRoots"] = []
 312     InfilesInfo["ChainIDs"] = []
 313     InfilesInfo["PyMOLObjectNames"] = []
 314 
 315     for Infile in InfilesNames:
 316         MiscUtil.PrintInfo("\nRetrieving chains information for input file %s..." % Infile)
 317         
 318         FileDir, FileName, FileExt = MiscUtil.ParseFileName(Infile)
 319         InfileRoot = FileName
 320         
 321         ChainIDs = RetrieveChainIDs(Infile, InfileRoot)
 322         if not len(ChainIDs):
 323             if re.match("^FirstChain$", OptionsInfo["AlignMode"], re.I):
 324                 MiscUtil.PrintError("The align mode, %s, can't be used for calculating RMSD: No non-empty chain IDs found in input file." % (OptionsInfo["AlignMode"]))
 325         
 326         InfilesInfo["FilesNames"].append(Infile)
 327         InfilesInfo["FilesRoots"].append(InfileRoot)
 328         InfilesInfo["ChainIDs"].append(ChainIDs)
 329 
 330         Name = "%s%s" % (InfileRoot, NameSuffix)
 331         InfilesInfo["PyMOLObjectNames"].append(Name)
 332 
 333     if re.match("^ProbeFiles$", InfilesMode, re.I):
 334         OptionsInfo["ProbeFilesInfo"] = InfilesInfo
 335     elif re.match("^RefFiles$", InfilesMode, re.I):
 336         OptionsInfo["RefFilesInfo"] = InfilesInfo
 337         
 338 def RetrieveChainIDs(Infile, InfileRoot):
 339     """Retrieve chains IDs for an input file."""
 340 
 341     pymol.cmd.reinitialize()
 342     
 343     MolName = InfileRoot
 344     pymol.cmd.load(Infile, MolName)
 345 
 346     ChainIDs = PyMOLUtil.GetChains(MolName, RemoveEmpty = True)
 347     pymol.cmd.delete(MolName)
 348 
 349     if ChainIDs is None:
 350         ChainIDs = []
 351 
 352     # Print out chain and ligand IDs...
 353     ChainInfo = ", ".join(ChainIDs) if len(ChainIDs) else "None"
 354     MiscUtil.PrintInfo("Chain IDs: %s" % ChainInfo)
 355                          
 356     return ChainIDs
 357 
 358 def ProcessOptions():
 359     """Process and validate command line arguments and options."""
 360 
 361     MiscUtil.PrintInfo("Processing options...")
 362     
 363     # Validate options...
 364     ValidateOptions()
 365     
 366     OptionsInfo["AlignMethod"] = Options["--alignMethod"].lower()
 367     OptionsInfo["AlignMode"] = Options["--alignMode"]
 368 
 369     OptionsInfo["Mode"] = Options["--mode"]
 370     
 371     OptionsInfo["ProbeFiles"] = Options["--probefiles"]
 372     OptionsInfo["ProbeFilesNames"] =  Options["--probeFilesNames"]
 373 
 374     OptionsInfo["RefFiles"] = Options["--reffiles"]
 375     OptionsInfo["RefFilesNames"] =  Options["--refFilesNames"]
 376     
 377     RetrieveProbeFilesInfo()
 378     RetrieveRefFilesInfo()
 379     
 380     OptionsInfo["Outfile"] = Options["--outfile"]
 381     OptionsInfo["OutMatrix"] = True if re.match("^Yes$", Options["--outMatrix"], re.I) else False
 382     
 383     OptionsInfo["Overwrite"] = Options["--overwrite"]
 384     
 385     OptionsInfo["OutDelim"] = " "
 386     if MiscUtil.CheckFileExt(OptionsInfo["Outfile"], "csv"):
 387         OptionsInfo["OutDelim"] = ","
 388     elif MiscUtil.CheckFileExt(OptionsInfo["Outfile"], "tsv txt"):
 389         OptionsInfo["OutDelim"] = "\t"
 390     else:
 391         MiscUtil.PrintError("The file name specified , %s, for option \"--outfile\" is not valid. Supported file formats: csv tsv txt\n" % (OptionsInfo["Outfile"]))
 392 
 393 def RetrieveOptions(): 
 394     """Retrieve command line arguments and options."""
 395     
 396     # Get options...
 397     global Options
 398     Options = docopt(_docoptUsage_)
 399     
 400     # Set current working directory to the specified directory...
 401     WorkingDir = Options["--workingdir"]
 402     if WorkingDir:
 403         os.chdir(WorkingDir)
 404     
 405     # Handle examples option...
 406     if "--examples" in Options and Options["--examples"]:
 407         MiscUtil.PrintInfo(MiscUtil.GetExamplesTextFromDocOptText(_docoptUsage_))
 408         sys.exit(0)
 409 
 410 def ValidateOptions():
 411     """Validate option values."""
 412     
 413     MiscUtil.ValidateOptionTextValue("-a, --alignMethod", Options["--alignMethod"], "align cealign super")
 414     MiscUtil.ValidateOptionTextValue("--alignMode", Options["--alignMode"], "FirstChain Complex")
 415 
 416     MiscUtil.ValidateOptionTextValue("-m, --mode", Options["--mode"], "OneToOne AllToAll FirstToAll")
 417     
 418     # Expand reffiles to handle presence of multiple input files...
 419     RefFilesNames = MiscUtil.ExpandFileNames(Options["--reffiles"], ",")
 420 
 421     # Validate file extensions...
 422     for RefFile in RefFilesNames:
 423         MiscUtil.ValidateOptionFilePath("-r, --reffiles", RefFile)
 424         MiscUtil.ValidateOptionFileExt("-r, --reffiles", RefFile, "pdb cif")
 425     Options["--refFilesNames"] = RefFilesNames
 426 
 427     # Expand probefiles to handle presence of multiple input files...
 428     ProbeFilesNames = MiscUtil.ExpandFileNames(Options["--probefiles"], ",")
 429 
 430     # Validate file extensions...
 431     for ProbeFile in ProbeFilesNames:
 432         MiscUtil.ValidateOptionFilePath("-p, --probefiles", ProbeFile)
 433         MiscUtil.ValidateOptionFileExt("-p, --probefiles", ProbeFile, "pdb cif")
 434     Options["--probeFilesNames"] = ProbeFilesNames
 435 
 436     MiscUtil.ValidateOptionFileExt("-o, --outfile", Options["--outfile"], "csv tsv txt")
 437     MiscUtil.ValidateOptionsOutputFileOverwrite("-o, --outfile", Options["--outfile"], "--overwrite", Options["--overwrite"])
 438     
 439     MiscUtil.ValidateOptionTextValue("--outMatrix", Options["--outMatrix"], "Yes No")
 440     
 441 # Setup a usage string for docopt...
 442 _docoptUsage_ = """
 443 PyMOLCalculateRMSD.py - Calculate RMSD between macromolecules
 444 
 445 Usage:
 446     PyMOLCalculateRMSD.py [--alignMethod <align, cealign, super>]
 447                           [--alignMode <FirstChain or Complex>] [--mode <OneToOne, AllToAll, FirstToAll>]
 448                           [--outMatrix <yes or no>] [--overwrite]
 449                           [-w <dir>] -p <probefile1,probefile2,probefile3...> -r <reffile1,reffile2,reffile3...> -o <outfile>
 450     PyMOLCalculateRMSD.py -h | --help | -e | --examples
 451 
 452 Description:
 453     Calculate Root Mean Square Distance (RMSD) between a set of similar
 454     macromolecules in reference and probe input files. The probe and reference
 455     files are spatially aligned before the the calculation of RMSD values.
 456 
 457     The supported input  file format are: PDB (.pdb), mmCIF (.cif)
 458 
 459     The supported output file formats are:  CSV (.csv), TSV (.tsv, .txt)
 460 
 461 Options:
 462     -a, --alignMethod <align, cealign, super>  [default: super]
 463         Alignment methodology to use for aligning probe input files to
 464         reference files.
 465     --alignMode <FirstChain or Complex>  [default: FirstChain]
 466         Portion of probe and reference files to use for spatial alignment of
 467         probe files against reference files.  Possible values: FirstChain or
 468         Complex.
 469         
 470         The FirstChain mode allows alignment of the first chain in probe files
 471         to the first chain in reference files along with moving the rest of the
 472         complex to coordinate space of the reference files. The complete
 473         complex in probe files is aligned to the complete complex in reference
 474         files for the Complex mode.
 475     -e, --examples
 476         Print examples.
 477     -h, --help
 478         Print this help message.
 479     -m, --mode <OneToOne, AllToAll, FirstToAll>  [default: OneToOne]
 480         Specify how reference and probe input files are handled during the calculation
 481         of RMSD between reference and probe files.  Possible values: OneToOne,
 482         AllToAll and AllToFirst. For OneToOne mode, the number of reference input
 483         files must be equal to the number of probe input files. The RMSD is
 484         calculated for each pair of reference and probe file and written to the
 485         output file. For AllToAll mode, the RMSD is calculated for each reference
 486         input file against all probe input files. For FirstToAll mode, however, the RMSD
 487         is only calculated for the first reference input file against all probe files.
 488     -p, --probefiles <probefile1,probefile2,probelfile3...>
 489         A comma delimited list of probe input files. The wildcards are also allowed
 490         in file names.
 491     -r, --reffiles <reffile1,reffile2,reffile3...>
 492         A comma delimited list of reference input files. The wildcards are also allowed
 493         in file names.
 494     -o, --outfile <outfile>
 495         Output file name for writing out RMSD values. Supported text file extensions:
 496         csv, tsv or txt.
 497     --outMatrix <yes or no>  [default: yes]
 498         Output file in a matrix format during 'AllToAll' value for '-m, --mode' option.
 499     --overwrite
 500         Overwrite existing files.
 501     -w, --workingdir <dir>
 502         Location of working directory which defaults to the current directory.
 503 
 504 Examples:
 505     To calculate RMSD between pair of macromolecules in reference and probe files
 506     using only first chain in each file and write out a CSV file containing calculated RMSD
 507     values along with IDs, type:
 508 
 509         % PyMOLCalculateRMSD.py  -r "Sample3.pdb,Sample4.pdb,Sample5.pdb"
 510           -p "Sample3.pdb,Sample4.pdb,Sample5.pdb" -o SampleOut.csv 
 511 
 512     To calculate RMSD between all macromolecules in reference and probe files using
 513     complete complex and write out a CSV matrix file, type:
 514 
 515         % PyMOLCalculateRMSD.py  -m AllToAll --alignMode Complex
 516            --outMatrix Yes -r "Sample3.pdb,Sample4.pdb,Sample5.pdb"
 517           -p "Sample3.pdb,Sample4.pdb" -o SampleOut.csv 
 518 
 519     To calculate RMSD between macromolecule in first reference against all probe files
 520     using only first chain in each file and write out a TSV file containing calculated RMSD
 521     values along with IDs, type:
 522 
 523         % PyMOLCalculateRMSD.py  -m FirstToAll
 524           -r "Sample3.pdb,Sample4.pdb,Sample5.pdb"
 525           -p "Sample3.pdb,Sample4.pdb,Sample5.pdb" -o SampleOut.tsv 
 526 
 527     To calculate RMSD between pair of macromolecules in reference and probe files
 528     using only first chain in each file along with a specific alignment method and write
 529     out a CSV file containing calculated RMSD values, type:
 530 
 531         % PyMOLCalculateRMSD.py  --alignMethod align
 532           -r "Sample3.pdb,Sample4.pdb,Sample5.pdb"
 533           -p "Sample3.pdb,Sample4.pdb,Sample5.pdb" -o SampleOut.csv 
 534 
 535 Author:
 536     Manish Sud(msud@san.rr.com)
 537 
 538 See also:
 539     PyMOLAlignChains.py, PyMOLSplitChainsAndLigands.py,
 540     PyMOLVisualizeMacromolecules.py
 541 
 542 Copyright:
 543     Copyright (C) 2024 Manish Sud. All rights reserved.
 544 
 545     The functionality available in this script is implemented using PyMOL, a
 546     molecular visualization system on an open source foundation originally
 547     developed by Warren DeLano.
 548 
 549     This file is part of MayaChemTools.
 550 
 551     MayaChemTools is free software; you can redistribute it and/or modify it under
 552     the terms of the GNU Lesser General Public License as published by the Free
 553     Software Foundation; either version 3 of the License, or (at your option) any
 554     later version.
 555 
 556 """
 557 
 558 if __name__ == "__main__":
 559     main()