MayaChemTools

    1 #!/bin/env python
    2 #
    3 # File: OpenMMPerformMDSimulation.py
    4 # Author: Manish Sud <msud@san.rr.com>
    5 #
    6 # Copyright (C) 2025 Manish Sud. All rights reserved.
    7 #
    8 # The functionality available in this script is implemented using OpenMM, an
    9 # open source molecuar simulation package.
   10 #
   11 # This file is part of MayaChemTools.
   12 #
   13 # MayaChemTools is free software; you can redistribute it and/or modify it under
   14 # the terms of the GNU Lesser General Public License as published by the Free
   15 # Software Foundation; either version 3 of the License, or (at your option) any
   16 # later version.
   17 #
   18 # MayaChemTools is distributed in the hope that it will be useful, but without
   19 # any warranty; without even the implied warranty of merchantability of fitness
   20 # for a particular purpose.  See the GNU Lesser General Public License for more
   21 # details.
   22 #
   23 # You should have received a copy of the GNU Lesser General Public License
   24 # along with MayaChemTools; if not, see <http://www.gnu.org/licenses/> or
   25 # write to the Free Software Foundation Inc., 59 Temple Place, Suite 330,
   26 # Boston, MA, 02111-1307, USA.
   27 #
   28 
   29 from __future__ import print_function
   30 
   31 # Add local python path to the global path and import standard library modules...
   32 import os
   33 import sys;  sys.path.insert(0, os.path.join(os.path.dirname(sys.argv[0]), "..", "lib", "Python"))
   34 import time
   35 import re
   36 
   37 # OpenMM imports...
   38 try:
   39     import openmm as mm
   40     import openmm.app
   41 except ImportError as ErrMsg:
   42     sys.stderr.write("\nFailed to import OpenMM related module/package: %s\n" % ErrMsg)
   43     sys.stderr.write("Check/update your OpenMM environment and try again.\n\n")
   44     sys.exit(1)
   45 
   46 # MDTraj import...
   47 try:
   48     import mdtraj
   49 except ImportError as ErrMsg:
   50     sys.stderr.write("\nFailed to import MDTraj: %s\n" % ErrMsg)
   51     sys.stderr.write("Check/update your MDTraj environment and try again.\n\n")
   52     sys.exit(1)
   53 
   54 # MayaChemTools imports...
   55 try:
   56     from docopt import docopt
   57     import MiscUtil
   58     import OpenMMUtil
   59 except ImportError as ErrMsg:
   60     sys.stderr.write("\nFailed to import MayaChemTools module/package: %s\n" % ErrMsg)
   61     sys.stderr.write("Check/update your MayaChemTools environment and try again.\n\n")
   62     sys.exit(1)
   63 
   64 ScriptName = os.path.basename(sys.argv[0])
   65 Options = {}
   66 OptionsInfo = {}
   67 
   68 def main():
   69     """Start execution of the script."""
   70     
   71     MiscUtil.PrintInfo("\n%s (OpenMM v%s; MayaChemTools v%s; %s): Starting...\n" % (ScriptName, mm.Platform.getOpenMMVersion(), MiscUtil.GetMayaChemToolsVersion(), time.asctime()))
   72     
   73     (WallClockTime, ProcessorTime) = MiscUtil.GetWallClockAndProcessorTime()
   74     
   75     # Retrieve command line arguments and options...
   76     RetrieveOptions()
   77     
   78     # Process and validate command line arguments and options...
   79     ProcessOptions()
   80 
   81     # Perform actions required by the script...
   82     PerformMinimization()
   83     
   84     MiscUtil.PrintInfo("\n%s: Done...\n" % ScriptName)
   85     MiscUtil.PrintInfo("Total time: %s" % MiscUtil.GetFormattedElapsedTime(WallClockTime, ProcessorTime))
   86 
   87 def PerformMinimization():
   88     """Perform minimization."""
   89 
   90     # Prepare system for simulation...
   91     System, Topology, Positions = PrepareSystem()
   92 
   93     # Freeze and restraint atoms...
   94     FreezeRestraintAtoms(System, Topology, Positions)
   95 
   96     # Setup integrator...
   97     Integrator = SetupIntegrator()
   98 
   99     # Setup simulation...
  100     Simulation = SetupSimulation(System, Integrator, Topology, Positions)
  101 
  102     # Perform energy minimization...
  103     PerformEnergyMinimization(Simulation)
  104 
  105 def PrepareSystem():
  106     """Prepare system for simulation."""
  107 
  108     System, Topology, Positions  = OpenMMUtil.InitializeSystem(OptionsInfo["Infile"], OptionsInfo["ForcefieldParams"], OptionsInfo["SystemParams"], OptionsInfo["WaterBox"], OptionsInfo["WaterBoxParams"], OptionsInfo["SmallMolFile"], OptionsInfo["SmallMolID"])
  109     
  110     # Write out a PDB file for the system...
  111     MiscUtil.PrintInfo("\nWriting PDB file %s..." % OptionsInfo["InitialPDBOutfile"])
  112     OpenMMUtil.WritePDBFile(OptionsInfo["InitialPDBOutfile"], Topology, Positions, OptionsInfo["OutputParams"]["PDBOutKeepIDs"])
  113 
  114     return (System, Topology, Positions)
  115 
  116 def SetupIntegrator():
  117     """Setup integrator. """
  118 
  119     Integrator = OpenMMUtil.InitializeIntegrator(OptionsInfo["IntegratorParams"], OptionsInfo["SystemParams"]["ConstraintErrorTolerance"])
  120 
  121     return Integrator
  122 
  123 def SetupSimulation(System, Integrator, Topology, Positions):
  124     """Setup simulation. """
  125 
  126     Simulation = OpenMMUtil.InitializeSimulation(System, Integrator, Topology, Positions, OptionsInfo["PlatformParams"])
  127 
  128     return Simulation
  129 
  130 def PerformEnergyMinimization(Simulation):
  131     """Perform energy minimization."""
  132 
  133     SimulationParams = OpenMMUtil.SetupSimulationParameters(OptionsInfo["SimulationParams"])
  134 
  135     OutputParams = OptionsInfo["OutputParams"]
  136 
  137     # Setup a local minimization reporter...
  138     MinimizeReporter = None
  139     if OutputParams["MinimizationDataStdout"] or OutputParams["MinimizationDataLog"]:
  140         MinimizeReporter = LocalMinimizationReporter()
  141 
  142     if MinimizeReporter is not None:
  143         MiscUtil.PrintInfo("\nAdding minimization reporters...")
  144         if OutputParams["MinimizationDataLog"]:
  145             MiscUtil.PrintInfo("Adding data log minimization reporter (Steps: %s; File: %s)..." % (OutputParams["MinimizationDataSteps"], OutputParams["MinimizationDataLogFile"]))
  146         if OutputParams["MinimizationDataStdout"]:
  147             MiscUtil.PrintInfo("Adding data stdout minimization reporter (Steps: %s)..." % (OutputParams["MinimizationDataSteps"]))
  148     else:
  149         MiscUtil.PrintInfo("\nSkipping addition of minimization reporters...")
  150         
  151     MaxSteps = SimulationParams["MinimizationMaxSteps"]
  152 
  153     MaxStepsMsg = "MaxSteps: %s" % ("UntilConverged" if MaxSteps == 0 else MaxSteps)
  154     ToleranceMsg = "Tolerance: %.2f kcal/mol/A (%.2f kjoules/mol/nm)" % (SimulationParams["MinimizationToleranceInKcal"], SimulationParams["MinimizationToleranceInJoules"])
  155 
  156     MiscUtil.PrintInfo("\nPerforming energy minimization (%s; %s)..." % (MaxStepsMsg, ToleranceMsg))
  157 
  158     if OutputParams["MinimizationDataStdout"]:
  159         HeaderLine = SetupMinimizationDataOutHeaderLine()
  160         print("\n%s" % HeaderLine)
  161 
  162     Simulation.minimizeEnergy(tolerance = SimulationParams["MinimizationTolerance"], maxIterations = MaxSteps, reporter = MinimizeReporter)
  163 
  164     if OutputParams["MinimizationDataLog"]:
  165         WriteMinimizationDataLogFile(MinimizeReporter.DataOutValues)
  166 
  167     # Write out minimized structure...
  168     MiscUtil.PrintInfo("\nWriting PDB file %s..." % OptionsInfo["MinimizedPDBOutfile"])
  169     OpenMMUtil.WriteSimulationStatePDBFile(Simulation, OptionsInfo["MinimizedPDBOutfile"], OptionsInfo["OutputParams"]["PDBOutKeepIDs"])
  170 
  171 class LocalMinimizationReporter(mm.MinimizationReporter):
  172     """Setup a local minimization reporter. """
  173 
  174     (DataSteps, DataOutTypeList, DataOutDelimiter, StdoutStatus) = [None] * 4
  175 
  176     DataOutValues = []
  177     First = True
  178 
  179     def report(self, Iteration, PositonsList, GradientsList, DataStatisticsMap):
  180         """Report and track minimization."""
  181 
  182         if self.First:
  183             # Initialize...
  184             self.DataSteps = OptionsInfo["OutputParams"]["MinimizationDataSteps"]
  185             self.DataOutTypeList = OptionsInfo["OutputParams"]["MinimizationDataOutTypeOpenMMNameList"]
  186             self.DataOutDelimiter = OptionsInfo["OutputParams"]["DataOutDelimiter"]
  187             self.StdoutStatus = True if OptionsInfo["OutputParams"]["MinimizationDataStdout"] else False
  188 
  189             self.First = False
  190 
  191         if Iteration % self.DataSteps == 0:
  192             # Setup data values...
  193             DataValues = []
  194             DataValues.append("%s" % Iteration)
  195             for DataType in self.DataOutTypeList:
  196                 DataValue = "%.4f" % DataStatisticsMap[DataType]
  197                 DataValues.append(DataValue)
  198 
  199             # Track data...
  200             self.DataOutValues.append(DataValues)
  201 
  202             # Print data values...
  203             if self.StdoutStatus:
  204                 print("%s" % self.DataOutDelimiter.join(DataValues))
  205                 
  206         # This method must return a bool. You may return true for early termination.
  207         return False
  208 
  209 def WriteMinimizationDataLogFile(DataOutValues):
  210     """Write minimization data log file. """
  211 
  212     OutputParams = OptionsInfo["OutputParams"]
  213 
  214     Outfile = OutputParams["MinimizationDataLogFile"]
  215     OutDelimiter = OutputParams["DataOutDelimiter"]
  216 
  217     MiscUtil.PrintInfo("\nWriting minimization log file %s..." % Outfile)
  218     OutFH = open(Outfile, "w")
  219 
  220     HeaderLine = SetupMinimizationDataOutHeaderLine()
  221     OutFH.write("%s\n" % HeaderLine)
  222 
  223     for LineWords in DataOutValues:
  224         Line = OutDelimiter.join(LineWords)
  225         OutFH.write("%s\n" % Line)
  226 
  227     OutFH.close()
  228     
  229 def SetupMinimizationDataOutHeaderLine():
  230     """Setup minimization data output header line. """
  231 
  232     LineWords = ["Iteration"]
  233     for Label in OptionsInfo["OutputParams"]["MinimizationDataOutTypeList"]:
  234         if re.match("^(SystemEnergy|RestraintEnergy)$", Label, re.I):
  235             LineWords.append("%s(kjoules/mol)" % Label)
  236         elif re.match("^RestraintStrength$", Label, re.I):
  237             LineWords.append("%s(kjoules/mol/nm^2)" % Label)
  238         else:
  239             LineWords.append(Label)
  240 
  241     Line = OptionsInfo["OutputParams"]["DataOutDelimiter"].join(LineWords)
  242 
  243     return Line
  244 
  245 def FreezeRestraintAtoms(System, Topology, Positions):
  246     """Handle freezing and restraining of atoms."""
  247 
  248     # Get atoms for freezing...
  249     FreezeAtomList = None
  250     if OptionsInfo["FreezeAtoms"]:
  251         FreezeAtomList =  OpenMMUtil.GetAtoms(Topology, OptionsInfo["FreezeAtomsParams"]["CAlphaProteinStatus"], OptionsInfo["FreezeAtomsParams"]["ResidueNames"], OptionsInfo["FreezeAtomsParams"]["Negate"])
  252         if FreezeAtomList is None:
  253             MiscUtil.PrintError("The freeze atoms parameters specified, \"selection, %s, selectionSpec, %s, negate, %s\", - using \"--freezeAtomsParams\" option didn't match any atoms in the system. You must specify a valid set of parameters for freezing atoms or disable freezing using \"No\" value for \"--freezeAtoms\" option.." % (OptionsInfo["FreezeAtomsParams"]["Selection"], OptionsInfo["FreezeAtomsParams"]["SelectionSpec"], OptionsInfo["FreezeAtomsParams"]["Negate"]))
  254 
  255     # Get atoms for restraining...
  256     RestraintAtomList = None
  257     if OptionsInfo["RestraintAtoms"]:
  258         RestraintAtomList =  OpenMMUtil.GetAtoms(Topology, OptionsInfo["RestraintAtomsParams"]["CAlphaProteinStatus"], OptionsInfo["RestraintAtomsParams"]["ResidueNames"], OptionsInfo["RestraintAtomsParams"]["Negate"])
  259         if RestraintAtomList is None:
  260             MiscUtil.PrintError("The restraint atoms parameters specified, \"selection, %s, selectionSpec, %s, negate, %s\", - using \"--restraintAtomsParams\" option didn't match any atoms in the system. You must specify a valid set of parameters for restraining atoms or disable restraining using \"No\" value for \"--restraintAtoms\" option." % (OptionsInfo["RestraintAtomsParams"]["Selection"], OptionsInfo["RestraintAtomsParams"]["SelectionSpec"], OptionsInfo["RestraintAtomsParams"]["Negate"]))
  261 
  262     # Check for atoms to freeze or restraint...
  263     if FreezeAtomList is None and RestraintAtomList is None:
  264         return
  265 
  266     #   Check for overlap between freeze and restraint atoms...
  267     if OpenMMUtil.DoAtomListsOverlap(FreezeAtomList, RestraintAtomList):
  268         MiscUtil.PrintError("The atoms specified using \"--freezeAtomsParams\" and \"--restraintAtomsParams\" options appear to overlap. You must specify unique sets of atoms to freeze and restraint.")
  269 
  270     #  Check overlap of freeze atoms with system constraints...
  271     if OpenMMUtil.DoesAtomListOverlapWithSystemConstraints(System, FreezeAtomList):
  272         MiscUtil.PrintError("The atoms specified using \"--freezeAtomsParams\" appear to overlap with atoms being constrained corresponding to the value specified, %s, for paramater name \"constraints\" using \"--systemParams\" option.\n\nYou must specify a unique set of atoms to freeze or turn off system constaints by specifying value, None, for \"constraints\" parameter using option \"--systemsParams\".\n\nIn addtion, you may want specify, no, value for \"rigidWater\" option.\n\nThe atoms are frozen by setting their particle mass to zero. OpenMM doesn't allow to both constraint atoms and set their mass to zero." % (OptionsInfo["SystemParams"]["Constraints"]))
  273 
  274     #  Check overlap of restraint atoms with system constraints...
  275     if OpenMMUtil.DoesAtomListOverlapWithSystemConstraints(System, RestraintAtomList):
  276         MiscUtil.PrintInfo("")
  277         MiscUtil.PrintWarning("The atoms specified using \"--restraintAtomsParams\" appear to overlap with atoms being constrained corresponding to the value specified, %s, for paramater name \"constraints\" using \"--systemParams\" option. You may want to specify a unique set of atoms to restraints or turn off system constaints by specifying value, None, for \"constraints\" parameter using option \"--systemsParams\"." % (OptionsInfo["SystemParams"]["Constraints"]))
  278 
  279     # Freeze atoms...
  280     if FreezeAtomList is None:
  281         MiscUtil.PrintInfo("\nSkipping freezing of atoms...")
  282     else:
  283         MiscUtil.PrintInfo("\nFreezing atoms (Selection: %s)..." % OptionsInfo["FreezeAtomsParams"]["Selection"])
  284         OpenMMUtil.FreezeAtoms(System, FreezeAtomList)
  285         
  286     # Restraint atoms...
  287     if RestraintAtomList is None:
  288         MiscUtil.PrintInfo("\nSkipping restraining of atoms...")
  289     else:
  290         MiscUtil.PrintInfo("\nRestraining atoms (Selection: %s)..." % OptionsInfo["RestraintAtomsParams"]["Selection"])
  291         
  292         SprintConstantInKcal = OptionsInfo["RestraintSpringConstant"]
  293         OpenMMUtil.RestraintAtoms(System, Positions, RestraintAtomList, SprintConstantInKcal)
  294 
  295 def ProcessOutfilePrefixParameter():
  296     """Process outfile prefix paramater."""
  297 
  298     OutfilePrefix = Options["--outfilePrefix"]
  299 
  300     if not re.match("^auto$", OutfilePrefix, re.I):
  301         OptionsInfo["OutfilePrefix"] = OutfilePrefix
  302         return
  303 
  304     if OptionsInfo["SmallMolFileMode"]:
  305         OutfilePrefix = "%s_%s_Complex" % (OptionsInfo["InfileRoot"], OptionsInfo["SmallMolFileRoot"])
  306     else:
  307         OutfilePrefix = "%s" % (OptionsInfo["InfileRoot"])
  308 
  309     if re.match("^yes$", Options["--waterBox"], re.I):
  310         OutfilePrefix = "%s_Solvated" % (OutfilePrefix)
  311 
  312     OptionsInfo["OutfilePrefix"] = OutfilePrefix
  313 
  314 def ProcessOutfileNames():
  315     """Process outfile names."""
  316 
  317     OutputParams = OptionsInfo["OutputParams"]
  318 
  319     OutfileParamName = "MinimizationDataLogFile"
  320     OutfileParamValue = OutputParams[OutfileParamName]
  321     if not Options["--overwrite"]:
  322         if os.path.exists(OutfileParamValue):
  323             MiscUtil.PrintError("The file specified, %s, for parameter name, %s, using option \"--outfileParams\" already exist. Use option \"--ov\" or \"--overwrite\" and try again. " % (OutfileParamValue, OutfileParamName))
  324 
  325     InitialPDBOutfile = "%s_Initial.%s" % (OptionsInfo["OutfilePrefix"], OutputParams["PDBOutfileExt"])
  326     MinimizedPDBOutfile = "%s_Minimized.%s" % (OptionsInfo["OutfilePrefix"], OutputParams["PDBOutfileExt"])
  327     for Outfile in [InitialPDBOutfile, MinimizedPDBOutfile]:
  328         if not Options["--overwrite"]:
  329             if os.path.exists(Outfile):
  330                 MiscUtil.PrintError("The file name, %s, generated using option \"--outfilePrefix\" already exist. Use option \"--ov\" or \"--overwrite\" and try again. " % (Outfile))
  331     OptionsInfo["InitialPDBOutfile"] = InitialPDBOutfile
  332     OptionsInfo["MinimizedPDBOutfile"] = MinimizedPDBOutfile
  333 
  334 def ProcessWaterBoxParameters():
  335     """Process water box parameters. """
  336 
  337     OptionsInfo["WaterBox"] = True if re.match("^yes$", Options["--waterBox"], re.I) else False
  338     OptionsInfo["WaterBoxParams"] = OpenMMUtil.ProcessOptionOpenMMWaterBoxParameters("--waterBoxParams", Options["--waterBoxParams"])
  339     
  340     if OptionsInfo["WaterBox"]:
  341         if OptionsInfo["ForcefieldParams"]["ImplicitWater"]:
  342             MiscUtil.PrintInfo("")
  343             MiscUtil.PrintWarning("The value, %s, specified using option \"--waterBox\" may not be valid for the combination of biopolymer and water forcefields, %s and %s, specified using \"--forcefieldParams\". You may consider using a valid combination of biopolymer and water forcefields for explicit water during the addition of a water box." % (Options["--waterBox"], OptionsInfo["ForcefieldParams"]["Biopolymer"], OptionsInfo["ForcefieldParams"]["Water"]))
  344 
  345 def ProcessOptions():
  346     """Process and validate command line arguments and options."""
  347 
  348     MiscUtil.PrintInfo("Processing options...")
  349 
  350     ValidateOptions()
  351 
  352     OptionsInfo["Infile"] = Options["--infile"]
  353     FileDir, FileName, FileExt = MiscUtil.ParseFileName(OptionsInfo["Infile"])
  354     OptionsInfo["InfileRoot"] = FileName
  355 
  356     SmallMolFile = Options["--smallMolFile"]
  357     SmallMolID = Options["--smallMolID"]
  358     SmallMolFileMode = False
  359     SmallMolFileRoot = None
  360     if SmallMolFile is not None:
  361         FileDir, FileName, FileExt = MiscUtil.ParseFileName(SmallMolFile)
  362         SmallMolFileRoot = FileName
  363         SmallMolFileMode = True
  364 
  365     OptionsInfo["SmallMolFile"] = SmallMolFile
  366     OptionsInfo["SmallMolFileRoot"] = SmallMolFileRoot
  367     OptionsInfo["SmallMolFileMode"] = SmallMolFileMode
  368     OptionsInfo["SmallMolID"] = SmallMolID.upper()
  369 
  370     ProcessOutfilePrefixParameter()
  371 
  372     ParamsDefaultInfoOverride = {"MinimizationDataSteps": 100, "MinimizationDataStdout": False, "MinimizationDataLog": True}
  373     OptionsInfo["OutputParams"] = OpenMMUtil.ProcessOptionOpenMMOutputParameters("--outputParams", Options["--outputParams"], OptionsInfo["OutfilePrefix"], ParamsDefaultInfoOverride)
  374     ProcessOutfileNames()
  375 
  376     OptionsInfo["ForcefieldParams"] = OpenMMUtil.ProcessOptionOpenMMForcefieldParameters("--forcefieldParams", Options["--forcefieldParams"])
  377 
  378     OptionsInfo["FreezeAtoms"] = True if re.match("^yes$", Options["--freezeAtoms"], re.I) else False
  379     if OptionsInfo["FreezeAtoms"]:
  380         OptionsInfo["FreezeAtomsParams"] = OpenMMUtil.ProcessOptionOpenMMAtomsSelectionParameters("--freezeAtomsParams", Options["--freezeAtomsParams"])
  381     else:
  382         OptionsInfo["FreezeAtomsParams"] = None
  383 
  384     ParamsDefaultInfoOverride = {"Name": Options["--platform"], "Threads": 1}
  385     OptionsInfo["PlatformParams"] = OpenMMUtil.ProcessOptionOpenMMPlatformParameters("--platformParams", Options["--platformParams"], ParamsDefaultInfoOverride)
  386 
  387     OptionsInfo["RestraintAtoms"] = True if re.match("^yes$", Options["--restraintAtoms"], re.I) else False
  388     if OptionsInfo["RestraintAtoms"]:
  389         OptionsInfo["RestraintAtomsParams"] = OpenMMUtil.ProcessOptionOpenMMAtomsSelectionParameters("--restraintAtomsParams", Options["--restraintAtomsParams"])
  390     else:
  391         OptionsInfo["RestraintAtomsParams"] = None
  392     OptionsInfo["RestraintSpringConstant"] = float(Options["--restraintSpringConstant"])
  393 
  394     OptionsInfo["SystemParams"] = OpenMMUtil.ProcessOptionOpenMMSystemParameters("--systemParams", Options["--systemParams"])
  395 
  396     OptionsInfo["IntegratorParams"] = OpenMMUtil.ProcessOptionOpenMMIntegratorParameters("--integratorParams", Options["--integratorParams"], HydrogenMassRepartioningStatus = OptionsInfo["SystemParams"]["HydrogenMassRepartioning"])
  397 
  398     OptionsInfo["SimulationParams"] = OpenMMUtil.ProcessOptionOpenMMSimulationParameters("--simulationParams", Options["--simulationParams"])
  399 
  400     ProcessWaterBoxParameters()
  401 
  402     OptionsInfo["Overwrite"] = Options["--overwrite"]
  403     
  404 def RetrieveOptions(): 
  405     """Retrieve command line arguments and options."""
  406 
  407     # Get options...
  408     global Options
  409     Options = docopt(_docoptUsage_)
  410 
  411     # Set current working directory to the specified directory...
  412     WorkingDir = Options["--workingdir"]
  413     if WorkingDir:
  414         os.chdir(WorkingDir)
  415     
  416     # Handle examples option...
  417     if "--examples" in Options and Options["--examples"]:
  418         MiscUtil.PrintInfo(MiscUtil.GetExamplesTextFromDocOptText(_docoptUsage_))
  419         sys.exit(0)
  420 
  421 def ValidateOptions():
  422     """Validate option values."""
  423 
  424     MiscUtil.ValidateOptionFilePath("-i, --infile", Options["--infile"])
  425     MiscUtil.ValidateOptionFileExt("-i, --infile", Options["--infile"], "pdb cif")
  426 
  427     FileDir, FileName, FileExt = MiscUtil.ParseFileName(Options["--infile"])
  428     OutfilePrefix = Options["--outfilePrefix"]
  429     if not re.match("^auto$", OutfilePrefix, re.I):
  430         if re.match("^(%s)$" % OutfilePrefix, FileName, re.I):
  431             MiscUtil.PrintError("The value specified, %s, for option \"--outfilePrefix\" is not valid. You must specify a value different from, %s, the root of infile name." % (OutfilePrefix, FileName))
  432 
  433     if Options["--smallMolFile"] is not None:
  434         MiscUtil.ValidateOptionFilePath("-l, --smallMolFile", Options["--smallMolFile"])
  435         MiscUtil.ValidateOptionFileExt("-l, --smallMolFile", Options["--smallMolFile"], "sd sdf")
  436 
  437     SmallMolID = Options["--smallMolID"]
  438     if len(SmallMolID) != 3:
  439         MiscUtil.PrintError("The value specified, %s, for option \"--smallMolID\" is not valid. You must specify a three letter small molecule ID." % (SmallMolID))
  440 
  441     MiscUtil.ValidateOptionTextValue("--freezeAtoms", Options["--freezeAtoms"], "yes no")
  442     if re.match("^yes$", Options["--freezeAtoms"], re.I):
  443         if Options["--freezeAtomsParams"] is None:
  444             MiscUtil.PrintError("No value specified for option \"--freezeAtomsParams\". You must specify valid values during, yes, value for \"--freezeAtoms\" option.")
  445     
  446     MiscUtil.ValidateOptionTextValue("-p, --platform", Options["--platform"], "CPU CUDA OpenCL Reference")
  447 
  448     MiscUtil.ValidateOptionTextValue("--restraintAtoms", Options["--restraintAtoms"], "yes no")
  449     if re.match("^yes$", Options["--restraintAtoms"], re.I):
  450         if Options["--restraintAtomsParams"] is None:
  451             MiscUtil.PrintError("No value specified for option \"--restraintAtomsParams\". You must specify valid values during, yes, value for \"--restraintAtoms\" option.")
  452     
  453     MiscUtil.ValidateOptionFloatValue("--restraintSpringConstant", Options["--restraintSpringConstant"], {">": 0})
  454 
  455     MiscUtil.ValidateOptionTextValue("--waterBox", Options["--waterBox"], "yes no")
  456 
  457 # Setup a usage string for docopt...
  458 _docoptUsage_ = """
  459 OpenMMPerformMinimization.py - Perform an energy minimization.
  460 
  461 Usage:
  462     OpenMMPerformMDSimulation.py [--forcefieldParams <Name,Value,..>] [--freezeAtoms <yes or no>]
  463                                  [--freezeAtomsParams <Name,Value,..>] [--integratorParams <Name,Value,..>]
  464                                  [--outputParams <Name,Value,..>] [--outfilePrefix <text>]
  465                                  [--overwrite] [--platform <text>] [--platformParams <Name,Value,..>]
  466                                  [--restraintAtoms <yes or no>]
  467                                  [--restraintAtomsParams <Name,Value,..>] [--restraintSpringConstant <number>]
  468                                  [--simulationParams <Name,Value,..>] [--smallMolFile <SmallMolFile>] [--smallMolID <text>]
  469                                  [--systemParams <Name,Value,..>] [--waterBox <yes or no>]
  470                                  [--waterBoxParams <Name,Value,..>] [-w <dir>] -i <infile>
  471     OpenMMPerformMDSimulation.py -h | --help | -e | --examples
  472 
  473 Description:
  474     Perform energy minimization for a macromolecule or a macromolecule in a
  475     complex with small molecule. You may optionally add a water box and
  476     freeze/restraint atoms to your system before minimization.
  477 
  478     The input file must contain a macromolecule already prepared for simulation.
  479     The preparation of the macromolecule for a simulation generally involves the
  480     following: tasks:  Identification and replacement non-standard residues;
  481     Addition of missing residues; Addition of missing heavy atoms; Addition of
  482     missing hydrogens; Addition of a water box which is optional.
  483 
  484     In addition, the small molecule input file must contain a molecule already
  485     prepared for simulation. It must contain  appropriate 3D coordinates relative
  486     to the macromolecule along with no missing hydrogens.
  487 
  488     The supported macromolecule input file formats are:  PDB (.pdb) and
  489     CIF (.cif)
  490 
  491     The supported small molecule input file format are : SD (.sdf, .sd)
  492 
  493     Possible outfile prefixes:
  494          
  495         <InfieRoot>
  496         <InfieRoot>_Solvated
  497         <InfieRoot>_<SmallMolFileRoot>_Complex
  498         <InfieRoot>_<SmallMolFileRoot>_Complex_Solvated
  499          
  500     Possible output files:
  501          
  502         <OutfilePrefix>_Initial.<pdb or cif>
  503         <OutfilePrefix>_Minimized.<pdb or cif>
  504         <OutfilePrefix>_Minimization.csv
  505          
  506 Options:
  507     -e, --examples
  508         Print examples.
  509     -f, --forcefieldParams <Name,Value,..>  [default: auto]
  510         A comma delimited list of parameter name and value pairs for biopolymer,
  511         water, and small molecule forcefields.
  512         
  513         The supported parameter names along with their default values are
  514         are shown below:
  515             
  516             biopolymer, amber14-all.xml  [ Possible values: Any Valid value ]
  517             smallMolecule, openff-2.2.1  [ Possible values: Any Valid value ]
  518             water, auto  [ Possible values: Any Valid value ]
  519             additional, none [ Possible values: Space delimited list of any
  520                 valid value ]
  521             
  522         Possible biopolymer forcefield values:
  523             
  524             amber14-all.xml, amber99sb.xml, amber99sbildn.xml, amber03.xml,
  525             amber10.xml
  526             charmm36.xml, charmm_polar_2019.xml
  527             amoeba2018.xml
  528         
  529         Possible small molecule forcefield values:
  530             
  531             openff-2.2.1, openff-2.0.0, openff-1.3.1, openff-1.2.1,
  532             openff-1.1.1, openff-1.1.0,...
  533             smirnoff99Frosst-1.1.0, smirnoff99Frosst-1.0.9,...
  534             gaff-2.11, gaff-2.1, gaff-1.81, gaff-1.8, gaff-1.4,...
  535         
  536         The default water forcefield valus is dependent on the type of the
  537         biopolymer forcefield as shown below:
  538             
  539             Amber: amber14/tip3pfb.xml
  540             CHARMM: charmm36/water.xml or None for charmm_polar_2019.xml
  541             Amoeba: None (Explicit)
  542             
  543         Possible water forcefield values:
  544             
  545             amber14/tip3p.xml, amber14/tip3pfb.xml, amber14/spce.xml,
  546             amber14/tip4pew.xml, amber14/tip4pfb.xml,
  547             charmm36/water.xml, charmm36/tip3p-pme-b.xml,
  548             charmm36/tip3p-pme-f.xml, charmm36/spce.xml,
  549             charmm36/tip4pew.xml, charmm36/tip4p2005.xml,
  550             charmm36/tip5p.xml, charmm36/tip5pew.xml,
  551             implicit/obc2.xml, implicit/GBn.xml, implicit/GBn2.xml,
  552             amoeba2018_gk.xml (Implict water)
  553             None (Explicit water for amoeba)
  554         
  555         The additional forcefield value is a space delimited list of any valid
  556         forcefield values and is passed on to the OpenMMForcefields
  557         SystemGenerator along with the specified forcefield  values for
  558         biopolymer, water, and mall molecule. Possible additional forcefield
  559         values are:
  560             
  561             amber14/DNA.OL15.xml amber14/RNA.OL3.xml
  562             amber14/lipid17.xml amber14/GLYCAM_06j-1.xml
  563             ... ... ...
  564             
  565         You may specify any valid forcefield names supported by OpenMM. No
  566         explicit validation is performed.
  567     --freezeAtoms <yes or no>  [default: no]
  568         Freeze atoms during energy minimization. The specified atoms are kept
  569         completely fixed by setting their masses to zero. Their positions do not
  570         change during  energy minimization.
  571     --freezeAtomsParams <Name,Value,..>
  572         A comma delimited list of parameter name and value pairs for freezing
  573         atoms during energy minimization. You must specify these parameters for 'yes'
  574         value of '--freezeAtoms' option.
  575         
  576         The supported parameter names along with their default values are
  577         are shown below:
  578             
  579             selection, none [ Possible values: CAlphaProtein, Ions, Ligand,
  580                 Protein, Residues, or Water ]
  581             selectionSpec, auto [ Possible values: A space delimited list of
  582                 residue names ]
  583             negate, no [ Possible values: yes or no ]
  584             
  585         A brief description of parameters is provided below:
  586             
  587             selection: Atom selection to freeze.
  588             selectionSpec: A space delimited list of residue names for
  589                 selecting atoms to freeze. You must specify its value during
  590                 'Ligand' and 'Protein' value for 'selection'. The default values
  591                 are automatically set for 'CAlphaProtein', 'Ions', 'Protein',
  592                 and 'Water' values of 'selection' as shown below:
  593                 
  594                 CAlphaProtein: List of stadard protein residues from pdbfixer
  595                     for selecting CAlpha atoms.
  596                 Ions: Li Na K Rb Cs Cl Br F I
  597                 Water: HOH
  598                 Protein: List of standard protein residues from pdbfixer.
  599                 
  600             negate: Negate atom selection match to select atoms for freezing.
  601             
  602         In addition, you may specify an explicit space delimited list of residue
  603         names using 'selectionSpec' for any 'selection". The specified residue
  604         names are appended to the appropriate default values during the
  605         selection of atoms for freezing.
  606     -h, --help
  607         Print this help message.
  608     -i, --infile <infile>
  609         Input file name containing a macromolecule.
  610     --integratorParams <Name,Value,..>  [default: auto]
  611         A comma delimited list of parameter name and value pairs for integrator
  612         to setup the system for local energy minimization. No MD simulation is
  613         performed.
  614         
  615         The supported parameter names along with their default values are
  616         are shown below:
  617             
  618             temperature, 300.0 [ Units: kelvin ]
  619             
  620     --outfilePrefix <text>  [default: auto]
  621         File prefix for generating the names of output files. The default value
  622         depends on the names of input files for macromolecule and small molecule
  623         along with the type of statistical ensemble and the nature of the solvation.
  624         
  625         The possible values for outfile prefix are shown below:
  626             
  627             <InfieRoot>
  628             <InfieRoot>_Solvated
  629             <InfieRoot>_<SmallMolFileRoot>_Complex
  630             <InfieRoot>_<SmallMolFileRoot>_Complex_Solvated
  631             
  632     --outputParams <Name,Value,..>  [default: auto]
  633         A comma delimited list of parameter name and value pairs for generating
  634        output during energy minimization..
  635         
  636         The supported parameter names along with their default values are
  637         are shown below:
  638             
  639             minimizationDataSteps, 100
  640             minimizationDataStdout, no  [ Possible values: yes or no ]
  641             minimizationDataLog, yes  [ Possible values: yes or no ]
  642             minimizationDataLogFile, auto  [ Default:
  643                 <OutfilePrefix>_MinimizationOut.csv ]
  644             minimizationDataOutType, auto [ Possible values: A space delimited
  645                list of valid parameter names.  Default: SystemEnergy
  646                RestraintEnergy MaxConstraintError.
  647                Other valid names: RestraintStrength ]
  648             
  649             pdbOutFormat, PDB  [ Possible values: PDB or CIF ]
  650             pdbOutKeepIDs, yes  [ Possible values: yes or no ]
  651             
  652         A brief description of parameters is provided below:
  653             
  654             minimizationDataSteps: Frequency of writing data to stdout
  655                 and log file.
  656             minimizationDataStdout: Write data to stdout.
  657             minimizationDataLog: Write data to log file.
  658             minimizationDataLogFile: Data log fie name.
  659             minimizationDataOutType: Type of data to write to stdout
  660                 and log file.
  661             
  662             pdbOutFormat: Format of output PDB files.
  663             pdbOutKeepIDs: Keep existing chain and residue IDs.
  664             
  665     --overwrite
  666         Overwrite existing files.
  667     -p, --platform <text>  [default: CPU]
  668         Platform to use for running MD simulation. Possible values: CPU, CUDA,
  669        OpenCL, or Reference.
  670     --platformParams <Name,Value,..>  [default: auto]
  671         A comma delimited list of parameter name and value pairs to configure
  672         platform for running energy minimization calculations..
  673         
  674         The supported parameter names along with their default values for
  675         different platforms are shown below:
  676             
  677             CPU:
  678             
  679             threads, 1  [ Possible value: >= 0 or auto.  The value of 'auto'
  680                 or zero implies the use of all available CPUs for threading. ]
  681             
  682             CUDA:
  683             
  684             deviceIndex, auto  [ Possible values: 0, '0 1' etc. ]
  685             deterministicForces, auto [ Possible values: yes or no ]
  686             precision, single  [ Possible values: single, double, or mix ]
  687             tempDirectory, auto [ Possible value: DirName ]
  688             useBlockingSync, auto [ Possible values: yes or no ]
  689             useCpuPme, auto [ Possible values: yes or no ]
  690             
  691             OpenCL:
  692             
  693             deviceIndex, auto  [ Possible values: 0, '0 1' etc. ]
  694             openCLPlatformIndex, auto  [ Possible value: Number]
  695             precision, single  [ Possible values: single, double, or mix ]
  696             useCpuPme, auto [ Possible values: yes or no ]
  697             
  698         A brief description of parameters is provided below:
  699             
  700             CPU:
  701             
  702             threads: Number of threads to use for simulation.
  703             
  704             CUDA:
  705             
  706             deviceIndex: Space delimited list of device indices to use for
  707                 calculations.
  708             deterministicForces: Generate reproducible results at the cost of a
  709                 small decrease in performance.
  710             precision: Number precision to use for calculations.
  711             tempDirectory: Directory name for storing temporary files.
  712             useBlockingSync: Control run-time synchronization between CPU and
  713                 GPU.
  714             useCpuPme: Use CPU-based PME implementation.
  715             
  716             OpenCL:
  717             
  718             deviceIndex: Space delimited list of device indices to use for
  719                 simulation.
  720             openCLPlatformIndex: Platform index to use for calculations.
  721             precision: Number precision to use for calculations.
  722             useCpuPme: Use CPU-based PME implementation.
  723             
  724     --restraintAtoms <yes or no>  [default: no]
  725         Restraint atoms during energy minimization. The motion of specified atoms is
  726         restricted by adding a harmonic force that binds them to their starting
  727         positions. The atoms are not completely fixed unlike freezing of atoms.
  728         Their motion, however, is restricted and they are not able to move far away
  729         from their starting positions during energy minimization.
  730     --restraintAtomsParams <Name,Value,..>
  731         A comma delimited list of parameter name and value pairs for restraining
  732         atoms during energy minimization. You must specify these parameters for 'yes'
  733         value of '--restraintAtoms' option.
  734         
  735         The supported parameter names along with their default values are
  736         are shown below:
  737             
  738             selection, none [ Possible values: CAlphaProtein, Ions, Ligand,
  739                 Protein, Residues, or Water ]
  740             selectionSpec, auto [ Possible values: A space delimited list of
  741                 residue names ]
  742             negate, no [ Possible values: yes or no ]
  743             
  744         A brief description of parameters is provided below:
  745             
  746             selection: Atom selection to restraint.
  747             selectionSpec: A space delimited list of residue names for
  748                 selecting atoms to restraint. You must specify its value during
  749                 'Ligand' and 'Protein' value for 'selection'. The default values
  750                 are automatically set for 'CAlphaProtein', 'Ions', 'Protein',
  751                 and 'Water' values of 'selection' as shown below:
  752                 
  753                 CAlphaProtein: List of stadard protein residues from pdbfixer
  754                   for selecting CAlpha atoms.
  755                 Ions: Li Na K Rb Cs Cl Br F I
  756                 Water: HOH
  757                 Protein: List of standard protein residues from pdbfixer.
  758                 
  759             negate: Negate atom selection match to select atoms for freezing.
  760             
  761         In addition, you may specify an explicit space delimited list of residue
  762         names using 'selectionSpec' for any 'selection". The specified residue
  763         names are appended to the appropriate default values during the
  764         selection of atoms for restraining.
  765     --restraintSpringConstant <number>  [default: 2.5]
  766         Restraint spring constant for applying external restraint force to restraint
  767         atoms relative to their initial positions during 'yes' value of '--restraintAtoms'
  768         option. Default units: kcal/mol/A**2. The default value, 2.5, corresponds to
  769         1046.0 kjoules/mol/nm**2. The default value is automatically converted into
  770         units of kjoules/mol/nm**2 before its usage.
  771     --simulationParams <Name,Value,..>  [default: auto]
  772         A comma delimited list of parameter name and value pairs for simulation.
  773         
  774         The supported parameter names along with their default values are
  775         are shown below:
  776             
  777             minimizationMaxSteps, auto  [ Possible values: >= 0. The value of
  778                 zero implies until the minimization is converged. ]
  779             minimizationTolerance, 0.24  [ Units: kcal/mol/A. The default value
  780                 0.25, corresponds to OpenMM default of value of 10.04
  781                 kjoules/mol/nm. It is automatically converted into OpenMM
  782                 default units before its usage. ]
  783             
  784         A brief description of parameters is provided below:
  785             
  786             minimizationMaxSteps: Maximum number of minimization steps. The
  787                 value of zero implies until the minimization is converged.
  788             minimizationTolerance: Energy convergence tolerance during
  789                 minimization.
  790             
  791     -s, --smallMolFile <SmallMolFile>
  792         Small molecule input file name. The macromolecue and small molecule are
  793         merged for simulation and the complex is written out to a PDB file.
  794     --smallMolID <text>  [default: LIG]
  795         Three letter small molecule residue ID. The small molecule ID corresponds
  796         to the residue name of the small molecule and is written out to a PDB file
  797         containing the complex.
  798     --systemParams <Name,Value,..>  [default: auto]
  799         A comma delimited list of parameter name and value pairs to configure
  800         a system for energy minimization. No MD simulation is performed.
  801         
  802         The supported parameter names along with their default values are
  803         are shown below:
  804             
  805             constraints, BondsInvolvingHydrogens [ Possible values: None,
  806                 WaterOnly, BondsInvolvingHydrogens, AllBonds, or
  807                 AnglesInvolvingHydrogens ]
  808             constraintErrorTolerance, 0.000001
  809             ewaldErrorTolerance, 0.0005
  810             
  811             nonbondedMethodPeriodic, PME [ Possible values: NoCutoff,
  812                 CutoffNonPeriodic, or PME ]
  813             nonbondedMethodNonPeriodic, NoCutoff [ Possible values:
  814                 NoCutoff or CutoffNonPeriodic]
  815             nonbondedCutoff, 1.0 [ Units: nm ]
  816             
  817             hydrogenMassRepartioning, yes [ Possible values: yes or no ]
  818             hydrogenMass, 1.5 [ Units: amu]
  819             
  820             removeCMMotion, yes [ Possible values: yes or no ]
  821             rigidWater, auto [ Possible values: yes or no. Default: 'No' for
  822                'None' value of constraints; Otherwise, yes ]
  823             
  824         A brief description of parameters is provided below:
  825             
  826             constraints: Type of system constraints to use for simulation. These
  827                 constraints are different from freezing and restraining of any
  828                 atoms in the system.
  829             constraintErrorTolerance: Distance tolerance for constraints as a
  830                 fraction of the constrained distance.
  831             ewaldErrorTolerance: Ewald error tolerance for a periodic system.
  832             
  833             nonbondedMethodPeriodic: Nonbonded method to use during the
  834                 calculation of long range interactions for a periodic system.
  835             nonbondedMethodNonPeriodic: Nonbonded method to use during the
  836                 calculation of long range interactions for a non-periodic system.
  837             nonbondedCutoff: Cutoff distance to use for long range interactions
  838                 in both perioidic non-periodic systems.
  839             
  840             hydrogenMassRepartioning: Use hydrogen mass repartioning. It
  841                 increases the mass of the hydrogen atoms attached to the heavy
  842                 atoms and decreasing the mass of the bonded heavy atom to
  843                 maintain constant system mass. This allows the use of larger
  844                 integration step size (4 fs) during a simulation.
  845             hydrogenMass: Hydrogen mass to use during repartioning.
  846             
  847             removeCMMotion: Remove all center of mass motion at every time step.
  848             rigidWater: Keep water rigid during a simulation. This is determined
  849                 automatically based on the value of 'constraints' parameter.
  850             
  851     --waterBox <yes or no>  [default: no]
  852         Add water box.
  853     --waterBoxParams <Name,Value,..>  [default: auto]
  854         A comma delimited list of parameter name and value pairs for adding
  855         a water box.
  856         
  857         The supported parameter names along with their default values are
  858         are shown below:
  859             
  860             model, tip3p [ Possible values: tip3p, spce, tip4pew, tip5p or
  861                 swm4ndp ]
  862             mode, Padding  [ Possible values: Size or Padding ]
  863             padding, 1.0
  864             size, None  [ Possible value: xsize ysize zsize ]
  865             shape, cube  [ Possible values: cube, dodecahedron, or octahedron ]
  866             ionPositive, Na+ [ Possible values: Li+, Na+, K+, Rb+, or Cs+ ]
  867             ionNegative, Cl- [ Possible values: Cl-, Br-, F-, or I- ]
  868             ionicStrength, 0.0
  869             
  870         A brief description of parameters is provided below:
  871             
  872             model: Water model to use for adding water box. The van der
  873                 Waals radii and atomic charges are determined using the
  874                 specified water forcefield. You must specify an appropriate
  875                 water forcefield. No validation is performed.
  876             mode: Specify the size of the waterbox explicitly or calculate it
  877                 automatically for a macromolecule along with adding padding
  878                 around ther macromolecule.
  879             padding: Padding around a macromolecule in nanometers for filling
  880                 box with water. It must be specified during 'Padding' value of
  881                 'mode' parameter.
  882             size: A space delimited triplet of values corresponding to water
  883                 size in nanometers. It must be specified during 'Size' value of
  884                 'mode' parameter.
  885             ionPositive: Type of positive ion to add during the addition of a
  886                 water box.
  887             ionNegative: Type of negative ion to add during the addition of a
  888                 water box.
  889             ionicStrength: Total concentration of both positive and negative
  890                 ions to add excluding the ions added to neutralize the system
  891                 during the addition of a water box.
  892             
  893     -w, --workingdir <dir>
  894         Location of working directory which defaults to the current directory.
  895 
  896 Examples:
  897     To perform energy minimization for a macromolecule in a PDB file until the
  898     energy is converged, writing information to log file every 100 steps and 
  899     generate a PDB file for the minimized system, type:
  900 
  901         % OpenMMPerformMinimization.py -i Sample13.pdb
  902 
  903     To run the first example for writing information to both stdout and log file
  904      every 100 steps and generate various output files, type:
  905 
  906         % OpenMMPerformMinimization.py -i Sample13.pdb --outputParams
  907           "minimizationDataStdout, yes"
  908 
  909     To run the first example for performing OpenMM simulation using multi-
  910     threading employing all available CPUs on your machine and generate various
  911     output files, type:
  912 
  913         % OpenMMPerformMinimization.py -i Sample13.pdb
  914           --platformParams "threads,0"
  915 
  916     To run the first example for performing OpenMM simulation using CUDA platform
  917     on your machine and generate various output files, type:
  918 
  919         % OpenMMPerformMinimization.py -i Sample13.pdb -p CUDA
  920 
  921     To run the second example for a marcomolecule in a complex with a small
  922     molecule and generate various output files, type:
  923 
  924         % OpenMMPerformMinimization.py -i Sample13.pdb -s Sample13Ligand.sdf
  925           --platformParams "threads,0"
  926 
  927     To run the second example by adding a water box to the system and generate
  928     various output files, type:
  929 
  930         % OpenMMPerformMinimization.py -i Sample13.pdb --waterBox yes
  931           --platformParams "threads,0"
  932 
  933     To run the second example for a marcomolecule in a complex with a small
  934     molecule by adding a water box to the system and generate various output
  935     files, type:
  936 
  937         % OpenMMPerformMinimization.py -i Sample13.pdb -s Sample13Ligand.sdf
  938           --waterBox yes --platformParams "threads,0"
  939 
  940     To run the second example by freezing CAlpha atoms in a macromolecule without
  941     using any system constraints to avoid any issues with the freezing of the same atoms
  942     and generate various output files, type:
  943 
  944         % OpenMMPerformMinimization.py -i Sample13.pdb
  945           --freezeAtoms yes --freezeAtomsParams "selection,CAlphaProtein"
  946           --systemParams "constraints, None"
  947           --platformParams "threads,0"
  948 
  949         % OpenMMPerformMinimization.py -i Sample13.pdb
  950           --freezeAtoms yes --freezeAtomsParams "selection,CAlphaProtein"
  951           --systemParams "constraints, None"
  952           --platformParams "threads,0" --waterBox yes
  953 
  954     To run the second example by restrainting CAlpha atoms in a macromolecule and
  955     and generate various output files, type:
  956 
  957         % OpenMMPerformMinimization.py -i Sample13.pdb
  958           --restraintAtomsParams "selection,CAlphaProtein"
  959           --platformParams "threads,0"
  960 
  961         % OpenMMPerformMinimization.py -i Sample13.pdb
  962           --restraintAtomsParams "selection,CAlphaProtein"
  963           --platformParams "threads,0"
  964           --waterBox yes
  965 
  966     To run the second example by specifying explict values for various parametres
  967     and generate various output files, type:
  968 
  969         % OpenMMPerformMinimization.py -i Sample13.pdb
  970           -f " biopolymer,amber14-all.xml,smallMolecule, openff-2.2.1,
  971           water,amber14/tip3pfb.xml" --waterBox yes
  972           --outputParams "minimizationDataSteps, 100, minimizationDataStdout,
  973           yes,minimizationDataLog,yes"
  974           -p CPU --platformParams "threads,0"
  975           --simulationParams "minimizationMaxSteps,500,
  976           minimizationTolerance, 0.24"
  977           --systemParams "constraints,BondsInvolvingHydrogens,
  978           nonbondedMethodPeriodic,PME,nonbondedMethodNonPeriodic,NoCutoff,
  979           hydrogenMassRepartioning, yes"
  980 
  981 Author:
  982     Manish Sud(msud@san.rr.com)
  983 
  984 See also:
  985     OpenMMPrepareMacromolecule.py, OpenMMPerformMDSimulation.py,
  986     OpenMMPerformSimulatedAnnealing.py
  987 
  988 Copyright:
  989     Copyright (C) 2025 Manish Sud. All rights reserved.
  990 
  991     The functionality available in this script is implemented using OpenMM, an
  992     open source molecuar simulation package.
  993 
  994     This file is part of MayaChemTools.
  995 
  996     MayaChemTools is free software; you can redistribute it and/or modify it under
  997     the terms of the GNU Lesser General Public License as published by the Free
  998     Software Foundation; either version 3 of the License, or (at your option) any
  999     later version.
 1000 
 1001 """
 1002 
 1003 if __name__ == "__main__":
 1004     main()