1 #!/bin/env python 2 # File: OpenMMUtil.py 3 # Author: Manish Sud <msud@san.rr.com> 4 # 5 # Copyright (C) 2025 Manish Sud. All rights reserved. 6 # 7 # The functionality available in this script is implemented using OpenMM, an 8 # open source molecuar simulation package. 9 # 10 # This file is part of MayaChemTools. 11 # 12 # MayaChemTools is free software; you can redistribute it and/or modify it under 13 # the terms of the GNU Lesser General Public License as published by the Free 14 # Software Foundation; either version 3 of the License, or (at your option) any 15 # later version. 16 # 17 # MayaChemTools is distributed in the hope that it will be useful, but without 18 # any warranty; without even the implied warranty of merchantability of fitness 19 # for a particular purpose. See the GNU Lesser General Public License for more 20 # details. 21 # 22 # You should have received a copy of the GNU Lesser General Public License 23 # along with MayaChemTools; if not, see <http://www.gnu.org/licenses/> or 24 # write to the Free Software Foundation Inc., 59 Temple Place, Suite 330, 25 # Boston, MA, 02111-1307, USA. 26 # 27 28 from __future__ import print_function 29 30 import os 31 import sys 32 import re 33 import glob 34 import multiprocessing as mp 35 36 import openmm as mm 37 import openmm.app 38 39 import openmmforcefields as mmff 40 import openmmforcefields.generators 41 import openff as ff 42 import openff.toolkit 43 44 import pdbfixer 45 import mdtraj 46 47 import MiscUtil 48 49 __all__ = ["AddWaterBox", "DoAtomListsOverlap", "DoesAtomListOverlapWithSystemConstraints", "DoesSystemContainWater", "FreezeAtoms", "GetAtoms", "GetFormattedTotalSimulationTime", "InitializeBarostat", "InitializeIntegrator", "InitializeReporters", "InitializeSimulation", "InitializeSystem", "InitializeSystemGenerator", "MergeSmallMoleculeWithMacromolecule", "ProcessOptionOpenMMRestartParameters", "ProcessOptionOpenMMAtomsSelectionParameters", "ProcessOptionOpenMMForcefieldParameters", "ProcessOptionOpenMMIntegratorParameters", "ProcessOptionOpenMMPlatformParameters", "ProcessOptionOpenMMOutputParameters", "ProcessOptionOpenMMSimulationParameters", "ProcessOptionOpenMMSystemParameters", "ProcessOptionOpenMMWaterBoxParameters", "ReadPDBFile", "ReadSmallMoleculeFile", "RestraintAtoms", "SetupIntegratorParameters", "SetupSimulationParameters", "SetupSystemGeneratorForcefieldsParameters", "WritePDBFile", "WriteSimulationStatePDBFile"] 50 51 def InitializeSystem(PDBFile, ForcefieldParamsInfo, SystemParamsInfo, WaterBoxAdd = False, WaterBoxParamsInfo = None, SmallMolFile = None, SmallMolID = "LIG"): 52 """Initialize OpenMM system using specified forcefields, system and water box 53 parameters along with a small molecule file and ID. 54 55 The ForcefieldParamsInfo parameter is a dictionary of name and value pairs for 56 system parameters and may be generated by calling the function named 57 ProcessOptionOpenMMForcefieldParameters(). 58 59 The SystemParamsInfo parameter is a dictionary of name and value pairs for 60 system parameters and may be generated by calling the function named 61 ProcessOptionOpenMMSystemParameters(). 62 63 The WaterBoxParamsInfo parameter is a dictionary of name and value pairs for 64 system parameters and may be generated by calling the function named 65 ProcessOptionOpenMMWaterBoxParameters(). 66 67 Arguments: 68 PDBFile (str): PDB file name.. 69 ForcefieldParamsInfo (dict): Parameter name and value pairs. 70 SystemParamsInfo (dict): Parameter name and value pairs. 71 WaterBoxAdd (bool): Add water box. 72 WaterBoxParamsInfo (dict): Parameter name and value pairs. 73 SmallMolFile (str): Small molecule file name.. 74 SmallMolID (str): Three letter small molecule ID 75 76 Returns: 77 Object: OpenMM system object. 78 Object: OpenMM topology object. 79 Object: OpenMM positions object. 80 81 Examples: 82 83 ... ... ... 84 OptionsInfo["ForcefieldParams"] = 85 OpenMMUtil.ProcessOptionOpenMMForcefieldParameters( 86 "--forcefieldParams", Options["--forcefieldParams"]) 87 ... ... ... 88 OptionsInfo["SystemParams"] = 89 OpenMMUtil.ProcessOptionOpenMMSystemParameters("--systemParams", 90 Options["--systemParams"]) 91 ... ... ... 92 OptionsInfo["WaterBoxParams"] = 93 OpenMMUtil.ProcessOptionOpenMMWaterBoxParameters( 94 "--waterBoxParams", Options["--waterBoxParams"]) 95 ... ... ... 96 System, Topology, Positions = OpenMMUtil.InitializeSystem( 97 OptionsInfo["Infile"], OptionsInfo["ForcefieldParams"], 98 OptionsInfo["SystemParams"], OptionsInfo["WaterBox"], 99 OptionsInfo["WaterBoxParams"], OptionsInfo["SmallMolFile"], 100 OptionsInfo["SmallMolID"]) 101 102 """ 103 104 # Read PDB file file... 105 MiscUtil.PrintInfo("\nReading PDB file %s..." % PDBFile) 106 PDBHandle = ReadPDBFile(PDBFile) 107 108 ModellerHandle = mm.app.Modeller(PDBHandle.topology, PDBHandle.positions) 109 MiscUtil.PrintInfo("Number of residues: %s; Number of atoms: %s" % (ModellerHandle.topology.getNumResidues(), ModellerHandle.topology.getNumAtoms())) 110 111 # Read small molecule file... 112 SmallMols = None 113 if SmallMolFile is not None: 114 MiscUtil.PrintInfo("\nReading small molecule file %s..." % SmallMolFile) 115 SmallMol = ReadSmallMoleculeFile(SmallMolFile) 116 if SmallMol is None: 117 MiscUtil.PrintError("Failed to read small molecule file: %s" % SmallMolFile) 118 SmallMols = [SmallMol] 119 120 MiscUtil.PrintInfo("\nGenerating macromolecule and small molecule complex...") 121 MergeSmallMoleculeWithMacromolecule(ModellerHandle, SmallMol, SmallMolID) 122 MiscUtil.PrintInfo("Number of residues: %s; Number of atoms: %s" % (ModellerHandle.topology.getNumResidues(), ModellerHandle.topology.getNumAtoms())) 123 124 # Initialize system generator... 125 BiopolymerForcefield = ForcefieldParamsInfo["Biopolymer"] 126 SmallMoleculeForcefield = ForcefieldParamsInfo["SmallMolecule"] 127 WaterForcefield = ForcefieldParamsInfo["Water"] 128 AdditionalForcefiedsList = ForcefieldParamsInfo["AdditionalList"] 129 SystemGeneratorHandle = InitializeSystemGenerator(BiopolymerForcefield, SmallMoleculeForcefield, WaterForcefield, SystemParamsInfo, SmallMols, AdditionalForcefiedsList) 130 131 if WaterBoxAdd: 132 AddWaterBox(ModellerHandle, SystemGeneratorHandle, WaterBoxParamsInfo) 133 MiscUtil.PrintInfo("Number of residues: %s; Number of atoms: %s" % (ModellerHandle.topology.getNumResidues(), ModellerHandle.topology.getNumAtoms())) 134 else: 135 MiscUtil.PrintInfo("\nSkipping addition of a water box...") 136 if DoesSystemContainWater(ModellerHandle.topology): 137 if ForcefieldParamsInfo["ImplicitWater"]: 138 MiscUtil.PrintInfo("Your system contains water molecules during the use of implicit water forcefield. The combination of biopolymer and water forcefields, %s and %s, specified using \"--forcefieldParams\" option may not be valid. You may consider removing water molecules from your system or specify a valid combination of biopolymer and water forcefields for explicit water." % (ForcefieldParamsInfo["Biopolymer"], ForcefieldParamsInfo["Water"])) 139 140 MiscUtil.PrintInfo("\nBuilding system...") 141 SystemHandle = SystemGeneratorHandle.create_system(ModellerHandle.topology, molecules = SmallMols) 142 143 MiscUtil.PrintInfo("Periodic boundary conditions: %s" % ("Yes" if DoesSystemUsesPeriodicBoundaryConditions(SystemHandle) else "No")) 144 145 return (SystemHandle, ModellerHandle.topology, ModellerHandle.positions) 146 147 def InitializeSystemGenerator(BiopolymerForcefield, SmallMoleculeForcefield, WaterForcefield, SystemParamsInfo, SmallMols, AdditionalForcefieldsList = None): 148 """Initialize MMFF system generator using specified forcefields and system parameters 149 along with a list of molecules. 150 151 The SystemParamsInfo parameter is a dictionary of name and value pairs for 152 system parameters and may be generated by calling the function named 153 ProcessOptionOpenMMSystemParameters(). 154 155 Arguments: 156 BiopolymerForcefield (str): Biopolymer force field name. 157 SmallMoleculeForcefield (str): Small molecule force field name. 158 WaterForcefield (str): Water force field name. 159 SystemParamsInfo (dict): Parameter name and value pairs. 160 SmallMols (list): List of OpenFF toolkit molecule objects. 161 AdditionalForcefieldsList (list): List of any additional forcefield 162 names 163 164 Returns: 165 Object: MMFF system generator object. 166 167 Examples: 168 169 OptionsInfo["SystemParams"] = 170 OpenMMUtil.ProcessOptionOpenMMSystemParameters("--systemParams", 171 Options["--systemParams"]) 172 ... ... ... 173 SystemGeneratorHandle = OpenMMUtil.InitializeSystemGenerator( 174 BiopolymerForcefield, SmallMoleculeForcefield, WaterForcefield, 175 OptionsInfo["SystemParams"], SmallMols, AdditionalForcefiedsList) 176 177 """ 178 179 (ForcefieldParams, PeriodicForcefieldParams, NonPeriodicForcefieldParams) = SetupSystemGeneratorForcefieldsParameters(SystemParamsInfo) 180 181 AdditionalForcefieldMsg = "" 182 if AdditionalForcefieldsList is not None: 183 AdditionalForcefieldMsg = "; Additional forcefield(s): %s" % ", ".join(AdditionalForcefieldsList) 184 185 MiscUtil.PrintInfo("\nInitializing system generator (Biopolymer forcefield: %s; Small molecule forcefield: %s; Water forcefield: %s%s)..." % (BiopolymerForcefield, SmallMoleculeForcefield,WaterForcefield, AdditionalForcefieldMsg)) 186 187 ForcefieldsList = [BiopolymerForcefield, WaterForcefield] 188 if AdditionalForcefieldsList is not None: 189 ForcefieldsList.extend(AdditionalForcefieldsList) 190 191 SystemGeneratorHandle = mmff.generators.SystemGenerator(forcefields = ForcefieldsList, small_molecule_forcefield = SmallMoleculeForcefield, molecules = SmallMols, forcefield_kwargs = ForcefieldParams, periodic_forcefield_kwargs = PeriodicForcefieldParams, nonperiodic_forcefield_kwargs = NonPeriodicForcefieldParams) 192 193 return SystemGeneratorHandle 194 195 def InitializeIntegrator(ParamsInfo, ConstraintErrorTolerance): 196 """Initialize integrator. 197 198 The ParamsInfo parameter is a dictionary of name and value pairs for 199 integrator parameters and may be generated by calling the function named 200 ProcessOptionOpenMMIntegratorParameters(). 201 202 Arguments: 203 ParamsInfo (dict): Parameter name and value pairs. 204 ConstraintErrorTolerance (float): Distance tolerance for 205 constraints as a fraction of the constrained distance. 206 207 Returns: 208 Object: OpenMM integrator object. 209 210 Examples: 211 212 OptionsInfo["IntegratorParams"] = 213 OpenMMUtil.ProcessOptionOpenMMIntegratorParameters( 214 "--integratorParams", Options["--integratorParams"], 215 HydrogenMassRepartioningStatus = 216 OptionsInfo["SystemParams"]["HydrogenMassRepartioning"]) 217 ... ... ... 218 Integrator = OpenMMUtil.InitializeIntegrator( 219 OptionsInfo["IntegratorParams"], 220 OptionsInfo["SystemParams"]["ConstraintErrorTolerance"]) 221 222 """ 223 224 IntegratorParamsInfo = SetupIntegratorParameters(ParamsInfo) 225 226 IntegratorName = IntegratorParamsInfo["Integrator"] 227 RandomSeed = IntegratorParamsInfo["RandomSeed"] 228 StepSize = IntegratorParamsInfo["StepSize"] 229 Temperature = IntegratorParamsInfo["Temperature"] 230 FrictionCoefficient = IntegratorParamsInfo["FrictionCoefficient"] 231 232 MiscUtil.PrintInfo("\nIntializing integrator (Name: %s; StepSize: %s; Temperature: %s)..." % (IntegratorName, StepSize, Temperature)) 233 234 if re.match("^LangevinMiddle$", IntegratorName, re.I): 235 Integrator = mm.LangevinMiddleIntegrator(Temperature, FrictionCoefficient, StepSize) 236 elif re.match("^Langevin$", IntegratorName, re.I): 237 Integrator = mm.LangevinIntegrator(Temperature, FrictionCoefficient, StepSize) 238 elif re.match("^NoseHoover$", IntegratorName, re.I): 239 Integrator = mm.NoseHooverIntegrator(Temperature, FrictionCoefficient, StepSize) 240 elif re.match("^Brownian$", IntegratorName, re.I): 241 Integrator = mm.BrownianIntegrator(Temperature, FrictionCoefficient, StepSize) 242 else: 243 MiscUtil.PrintError("The parameter value specified, %s, for parameter name, integrator, for option \"--integratorParams\" is not a valid value. Supported values: LangevinMiddle, Langevin, NoseHoover, or Brownian" % IntegratorName) 244 245 Integrator.setConstraintTolerance(ConstraintErrorTolerance) 246 247 if RandomSeed is not None: 248 if re.match("^(LangevinMiddle|Langevin|Brownian)$", IntegratorName, re.I): 249 MiscUtil.PrintInfo("Setting random number seed for integrator to %s..." % RandomSeed) 250 Integrator.setRandomNumberSeed(RandomSeed) 251 else: 252 MiscUtil.PrintInfo("Skipping setting of random number seed. Not supported for integrator %s..." % IntegratorName) 253 254 return Integrator 255 256 def InitializeBarostat(ParamsInfo): 257 """Initialize barostat. 258 259 The ParamsInfo parameter is a dictionary of name and value pairs for 260 integrator parameters and may be generated by calling the function named 261 ProcessOptionOpenMMIntegratorParameters(). 262 263 Arguments: 264 ParamsInfo (dict): Parameter name and value pairs. 265 266 Returns: 267 Object: OpenMM barostat object. 268 269 Examples: 270 271 OptionsInfo["IntegratorParams"] = 272 OpenMMUtil.ProcessOptionOpenMMIntegratorParameters( 273 "--integratorParams", Options["--integratorParams"], 274 HydrogenMassRepartioningStatus = 275 OptionsInfo["SystemParams"]["HydrogenMassRepartioning"]) 276 ... ... ... 277 Barostat = OpenMMUtil.InitializeBarostat( 278 OptionsInfo["IntegratorParams"]) 279 280 """ 281 IntegratorParamsInfo = SetupIntegratorParameters(ParamsInfo) 282 283 BarostatName = IntegratorParamsInfo["Barostat"] 284 if re.match("^MonteCarlo$", BarostatName, re.I): 285 MiscUtil.PrintInfo("\nInitializing Monte Carlo barostat (Pressure: %s)... " % (IntegratorParamsInfo["Pressure"])) 286 Barostat = mm.MonteCarloBarostat(IntegratorParamsInfo["Pressure"], IntegratorParamsInfo["Temperature"], IntegratorParamsInfo["BarostatInterval"]) 287 elif re.match("^MonteCarloMembrane$", BarostatName, re.I): 288 MiscUtil.PrintInfo("\nInitializing Monte Carlo membrane barostat (Pressure: %s; SurfaceTension: %s; XYMode: %s; ZMode: %s)... " % (IntegratorParamsInfo["Pressure"], IntegratorParamsInfo["SurfaceTension"], IntegratorParamsInfo["XYModeSpecified"], IntegratorParamsInfo["ZModeSpecified"])) 289 Barostat = mm.MonteCarloMembraneBarostat(IntegratorParamsInfo["Pressure"], IntegratorParamsInfo["SurfaceTension"], IntegratorParamsInfo["Temperature"], IntegratorParamsInfo["XYMode"], IntegratorParamsInfo["ZMode"], IntegratorParamsInfo["BarostatInterval"]) 290 else: 291 MiscUtil.PrintError("The parameter value specified, %s, for parameter name, barostat, for option \"--integratorParams\" is not a valid value. Supported values: MonteCarlo or MonteCarloMembrane" % BarostatName) 292 293 if IntegratorParamsInfo["RandomSeed"] is not None: 294 RandomSeed = IntegratorParamsInfo["RandomSeed"] 295 MiscUtil.PrintInfo("Setting random number seed for barostat to %s..." % RandomSeed) 296 Barostat.setRandomNumberSeed(RandomSeed) 297 298 return Barostat 299 300 def InitializeSimulation(System, Integrator, Topology, Positions, PlatformParamsInfo): 301 """Initialize simulation. 302 303 The PlatformParamsInfo parameter is a dictionary of name and value pairs for 304 platform parameters and may be generated by calling the function named 305 ProcessOptionOpenMMPlatformParameters(). 306 307 Arguments: 308 System (object): OpenMM system object. 309 Integrator (object): OpenMM integrator object. 310 Topology (object): OpenMM topology object. 311 Positons (object): OpenMM Positions object. 312 PlatformParamsInfo (dict): Parameter name and value pairs. 313 314 Returns: 315 Object: OpenMM simulation object. 316 317 Examples: 318 319 ParamsDefaultInfoOverride = {"Name": Options["--platform"], 320 "Threads": 1} 321 OptionsInfo["PlatformParams"] = 322 OpenMMUtil.ProcessOptionOpenMMPlatformParameters("--platformParams", 323 Options["--platformParams"], ParamsDefaultInfoOverride) 324 ... ... ... 325 Simulation = OpenMMUtil.InitializeSimulation(System, Integrator, Topology, 326 Positions, OptionsInfo["PlatformParams"]) 327 328 """ 329 330 PlatformName, PlatformProperties, PlatformMsg = SetupPlatformParameters(PlatformParamsInfo) 331 MiscUtil.PrintInfo("\nInitializing simulation (%s)..." % PlatformMsg) 332 333 try: 334 PlatformHandle = mm.Platform.getPlatformByName(PlatformName) 335 except Exception as ErrMsg: 336 MiscUtil.PrintInfo("") 337 MiscUtil.PrintError("Failed to get platform %s:\n%s\n" % (PlatformName, ErrMsg)) 338 339 try: 340 SimulationHandle = mm.app.Simulation(Topology, System, Integrator, PlatformHandle, PlatformProperties) 341 except Exception as ErrMsg: 342 MiscUtil.PrintInfo("") 343 MiscUtil.PrintError("Failed to initialize simulation: %s\n" % (ErrMsg)) 344 345 SimulationHandle.context.setPositions(Positions) 346 347 return (SimulationHandle) 348 349 def InitializeReporters(OutputParamsInfo, TotalSteps, DataOutAppendStatus): 350 """Initialize reporters for writing data to trajectory, log, and checkpoint 351 files along with reporting to the stdout. 352 353 The OutputParamsInfo parameter is a dictionary of name and value pairs for 354 output parameters and may be generated by calling the function named 355 ProcessOptionOpenMMOutputParameters(). 356 357 Arguments: 358 OutputParamsInfo (dict): Parameter name and value pairs. 359 TotalSteps (int): Total number of simulation steps. 360 DataOutAppendStatus (bool): Append data to trajectory and log file. 361 362 Returns: 363 Object: OpenMM trajectory reporter object. 364 Object: OpenMM data log file reporter object. 365 Object: OpenMM stodut reporter object. 366 Object: OpenMM checkpoint reporter object. 367 368 Examples: 369 370 if OptionsInfo["NVTMode"]: 371 ParamsDefaultInfoOverride = {"DataOutType": "Step Speed Progress 372 PotentialEnergy Temperature Time Volume"} 373 else: 374 ParamsDefaultInfoOverride = {"DataOutType": "Step Speed Progress 375 PotentialEnergy Temperature Time Density"} 376 OptionsInfo["OutputParams"] = 377 OpenMMUtil.ProcessOptionOpenMMOutputParameters("--outputParams", 378 Options["--outputParams"], OptionsInfo["OutfilePrefix"], 379 ParamsDefaultInfoOverride) 380 ProcessOutfileNames() 381 ... ... ... 382 (TrajReporter, DataLogReporter, DataStdoutReporter, CheckpointReporter) 383 = OpenMMUtil.InitializeReporters(OptionsInfo["OutputParams"], 384 OptionsInfo["SimulationParams"]["Steps"], OptionsInfo["DataOutAppendMode"]) 385 386 """ 387 388 (TrajReporter, DataLogReporter, DataStdoutReporter, CheckpointReporter) = [None] * 4 389 if OutputParamsInfo["Traj"]: 390 if re.match("^DCD$", OutputParamsInfo["TrajFormat"], re.I): 391 TrajReporter = mm.app.DCDReporter(OutputParamsInfo["TrajFile"], OutputParamsInfo["TrajSteps"], append = DataOutAppendStatus) 392 elif re.match("^XTC$", OutputParamsInfo["TrajFormat"], re.I): 393 if not DataOutAppendStatus: 394 # Remove existing traj file; otherwise, XTCReporter fails... 395 if os.path.isfile(OutputParamsInfo["TrajFile"]): 396 os.remove(OutputParamsInfo["TrajFile"]) 397 TrajReporter = mm.app.XTCReporter(OutputParamsInfo["TrajFile"], OutputParamsInfo["TrajSteps"], append = DataOutAppendStatus) 398 else: 399 MiscUtil.PrintError("The parameter value specified, %s, for parameter name, trajFormat, for option \"--outputParams\" is not a valid value. Supported format: DCD or XTC") 400 401 if OutputParamsInfo["Checkpoint"]: 402 CheckpointReporter = mm.app.CheckpointReporter(OutputParamsInfo["CheckpointFile"], OutputParamsInfo["CheckpointSteps"]) 403 404 DataOutTypeStatusMap = OutputParamsInfo["DataOutTypeStatusMap"] 405 if OutputParamsInfo["DataLog"]: 406 DataLogReporter = mm.app.StateDataReporter(OutputParamsInfo["DataLogFile"], OutputParamsInfo["DataLogSteps"], totalSteps = TotalSteps, step = DataOutTypeStatusMap["Step"], time = DataOutTypeStatusMap["Time"], speed = DataOutTypeStatusMap["Speed"], progress = DataOutTypeStatusMap["Progress"], elapsedTime = DataOutTypeStatusMap["ElapsedTime"], remainingTime = DataOutTypeStatusMap["RemainingTime"], potentialEnergy = DataOutTypeStatusMap["PotentialEnergy"], kineticEnergy = DataOutTypeStatusMap["KineticEnergy"], totalEnergy = DataOutTypeStatusMap["TotalEnergy"], temperature = DataOutTypeStatusMap["Temperature"], volume = DataOutTypeStatusMap["Volume"], density = DataOutTypeStatusMap["Density"], separator = OutputParamsInfo["DataOutDelimiter"], append = DataOutAppendStatus) 407 408 if OutputParamsInfo["DataStdout"]: 409 DataStdoutReporter = mm.app.StateDataReporter(sys.stdout, OutputParamsInfo["DataStdoutSteps"], totalSteps = TotalSteps, step = DataOutTypeStatusMap["Step"], time = DataOutTypeStatusMap["Time"], speed = DataOutTypeStatusMap["Speed"], progress = DataOutTypeStatusMap["Progress"], elapsedTime = DataOutTypeStatusMap["ElapsedTime"], remainingTime = DataOutTypeStatusMap["RemainingTime"], potentialEnergy = DataOutTypeStatusMap["PotentialEnergy"], kineticEnergy = DataOutTypeStatusMap["KineticEnergy"], totalEnergy = DataOutTypeStatusMap["TotalEnergy"], temperature = DataOutTypeStatusMap["Temperature"], volume = DataOutTypeStatusMap["Volume"], density = DataOutTypeStatusMap["Density"], separator = OutputParamsInfo["DataOutDelimiter"]) 410 411 return (TrajReporter, DataLogReporter, DataStdoutReporter, CheckpointReporter) 412 413 def AddWaterBox(ModellerHandle, SystemGeneratorHandle, WaterBoxParamsInfo): 414 """Add a water box. 415 416 The WaterBoxParamsInfo parameter is a dictionary of name and value pairs for 417 waterbox parameters and may be generated by calling the function named 418 ProcessOptionOpenMMWaterBoxParameters(). 419 420 Arguments: 421 ModellerHandle (object): OpenMM modeller object. 422 SystemGeneratorHandle (object): OpenMM system generator object. 423 WaterBoxParamsInfo (dict): Parameter name and value pairs. 424 425 Returns: 426 None. 427 428 Examples: 429 430 OptionsInfo["WaterBoxParams"] = 431 OpenMMUtil.ProcessOptionOpenMMWaterBoxParameters("--waterBoxParams", 432 Options["--waterBoxParams"]) 433 ... ... ... 434 OpenMMUtil.AddWaterBox(ModellerHandle, SystemGeneratorHandle, 435 OptionsInfo["WaterBoxParams"]) 436 437 """ 438 439 MiscUtil.PrintInfo("\nRemoving any existing waters...") 440 ModellerHandle.deleteWater() 441 442 MiscUtil.PrintInfo("\nAdding a water box...") 443 444 Size, Padding, Shape = [None] * 3 445 if WaterBoxParamsInfo["ModeSize"]: 446 SizeList = WaterBoxParamsInfo["SizeList"] 447 Size = mm.Vec3(SizeList[0], SizeList[1], SizeList[2]) * mm.unit.nanometer 448 elif WaterBoxParamsInfo["ModePadding"]: 449 Padding = WaterBoxParamsInfo["Padding"] * mm.unit.nanometer 450 Shape = WaterBoxParamsInfo["Shape"] 451 else: 452 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, mode, using \"--waterBoxParams\" option is not a valid value. Supported values: Size Padding \n" % (WaterBoxParamsInfo["Mode"])) 453 454 IonicStrength = WaterBoxParamsInfo["IonicStrength"] * mm.unit.molar 455 456 ModellerHandle.addSolvent(SystemGeneratorHandle.forcefield, model = WaterBoxParamsInfo["Model"], boxSize = Size, boxVectors = None, padding = Padding, numAdded = None, boxShape = Shape, positiveIon = WaterBoxParamsInfo["IonPositive"], negativeIon = WaterBoxParamsInfo["IonNegative"], ionicStrength = IonicStrength, neutralize = True) 457 458 def SetupSystemGeneratorForcefieldsParameters(SystemParamsInfo): 459 """Setup forcefied parameters for OpenMM API calls. 460 461 The SystemParamsInfo parameter is a dictionary of name and value pairs for 462 system parameters and may be generated by calling the function named 463 ProcessOptionOpenMMSystemParameters(). 464 465 Arguments: 466 SystemParamsInfo (dict): Parameter name and value pairs. 467 468 Returns: 469 dict: Forcefield parameter name and value pairs. 470 dictionary2: Periodic forcefield parameter name and value pairs. 471 dictionary3: Non-periodic parameter name and value pairs. 472 473 Examples: 474 475 OptionsInfo["SystemParams"] = 476 OpenMMUtil.ProcessOptionOpenMMSystemParameters("--systemParams", 477 Options["--systemParams"]) 478 ... ... ... 479 (ForcefieldParams, PeriodicForcefieldParams, NonPeriodicForcefieldParams) 480 = SetupSystemGeneratorForcefieldsParameters(OptionsInfo["SystemParams"]) 481 482 """ 483 484 ForcefieldParams = {"constraints": SystemParamsInfo["Constraints"], "rigidWater": SystemParamsInfo["RigidWater"], "removeCMMotion": SystemParamsInfo["RemoveCMMotion"]} 485 if SystemParamsInfo["HydrogenMassRepartioning"]: 486 ForcefieldParams["hydrogenMass"] = SystemParamsInfo["HydrogenMass"] * mm.unit.amu 487 488 NonbondedCutoff = SystemParamsInfo["NonbondedCutoff"] * mm.unit.nanometers 489 PeriodicForcefieldParams = {"nonbondedMethod": SystemParamsInfo["NonbondedMethodPeriodic"], "nonbondedCutoff": NonbondedCutoff, "ewaldErrorTolerance": SystemParamsInfo["EwaldErrorTolerance"]} 490 NonPeriodicForcefieldParams = {"nonbondedMethod": SystemParamsInfo["NonbondedMethodNonPeriodic"], "nonbondedCutoff" : NonbondedCutoff} 491 492 return (ForcefieldParams, PeriodicForcefieldParams, NonPeriodicForcefieldParams) 493 494 def SetupPlatformParameters(ParamsInfo): 495 """Setup platform parameters for OpenMM calls. 496 497 The ParamsInfo parameter is a dictionary of name and value pairs for 498 platform parameters and may be generated by calling the function named 499 ProcessOptionOpenMMPlatformParameters(). 500 501 Arguments: 502 ParamsInfo (dict): Parameter name and value pairs. 503 504 Returns: 505 str: PlatformName. 506 dict: Platform properities parameter name and values pairs. 507 str: Text message describing platform. 508 509 Examples: 510 511 ParamsDefaultInfoOverride = {"Name": Options["--platform"], 512 "Threads": 1} 513 OptionsInfo["PlatformParams"] = 514 OpenMMUtil.ProcessOptionOpenMMPlatformParameters("--platformParams", 515 Options["--platformParams"], ParamsDefaultInfoOverride) 516 ... ... ... 517 PlatformName, PlatformProperties, PlatformMsg = 518 SetupPlatformParameters(PlatformParamsInfo) 519 520 """ 521 522 PlatformName = ParamsInfo["Name"] 523 ParamNames = None 524 525 if re.match("^CPU$", PlatformName, re.I): 526 ParamNames = ["Threads"] 527 elif re.match("^CUDA$", PlatformName, re.I): 528 ParamNames = ["DeviceIndex", "DeterministicForces", "Precision", "TempDirectory", "UseBlockingSync", "UseCpuPme"] 529 elif re.match("^OpenCL$", PlatformName, re.I): 530 ParamNames = ["DeviceIndex", "OpenCLPlatformIndex", "Precision", "UseCpuPme"] 531 elif re.match("^Reference$", PlatformName, re.I): 532 ParamNames = None 533 else: 534 MiscUtil.PrintError("The parameter value specified, %s, for parameter name, name, for option \"--platformParams\" is not a valid value. Supported values: CPU, CUDA, OpenCL, or Reference") 535 536 PlatformProperties = None 537 if ParamNames is not None: 538 FirstValue = True 539 for ParamName in ParamNames: 540 ParamValue = ParamsInfo[ParamName] 541 if ParamValue is not None: 542 if FirstValue: 543 FirstValue = False 544 PlatformProperties = {} 545 PlatformProperties[ParamName] = ParamValue 546 547 PlatformMsg = "Platform: %s" % PlatformName 548 if re.match("^CPU$", PlatformName, re.I): 549 Threads = ParamsInfo["Threads"] 550 if Threads is None or Threads == "0": 551 Threads = "auto" 552 PlatformMsg = "Platform: %s; Threads: %s" % (PlatformName, Threads) 553 elif re.match("^(CUDA|OpenCL)$", PlatformName, re.I): 554 DeviceIndex = "auto" if ParamsInfo["DeviceIndex"] is None else ParamsInfo["DeviceIndex"] 555 Precision = "auto" if ParamsInfo["Precision"] is None else ParamsInfo["Precision"] 556 PlatformMsg = "Platform: %s; DeviceIndex: %s; Precision: %s" % (PlatformName, DeviceIndex, Precision) 557 558 return (PlatformName, PlatformProperties, PlatformMsg) 559 560 def SetupIntegratorParameters(ParamsInfo): 561 """Setup integrator parameters for OpenMM API calls. 562 563 The ParamsInfo parameter is a dictionary of name and value pairs for 564 integrator parameters and may be generated by calling the function named 565 ProcessOptionOpenMMIntegratorParameters(). 566 567 Arguments: 568 ParamsInfo (dict): Parameter name and value pairs. 569 570 Returns: 571 dict: Integrator parameter name and values pairs. 572 573 Examples: 574 575 OptionsInfo["IntegratorParams"] = 576 OpenMMUtil.ProcessOptionOpenMMIntegratorParameters( 577 "--integratorParams", Options["--integratorParams"], 578 HydrogenMassRepartioningStatus = 579 OptionsInfo["SystemParams"]["HydrogenMassRepartioning"]) 580 ... ... ... 581 IntegratorParams = SetupIntegratorParameters( 582 OptionsInfo["IntegratorParams"]) 583 584 """ 585 586 ParamsInfoWithUnits = {} 587 588 ParamsInfoWithUnits["Integrator"] = ParamsInfo["Integrator"] 589 590 ParamsInfoWithUnits["RandomSeed"] = ParamsInfo["RandomSeed"] 591 592 ParamsInfoWithUnits["FrictionCoefficient"] = ParamsInfo["FrictionCoefficient"]/mm.unit.picosecond 593 ParamsInfoWithUnits["StepSize"] = ParamsInfo["StepSize"] * mm.unit.femtoseconds 594 ParamsInfoWithUnits["Temperature"] = ParamsInfo["Temperature"] * mm.unit.kelvin 595 596 ParamsInfoWithUnits["Barostat"] = ParamsInfo["Barostat"] 597 598 ParamsInfoWithUnits["Pressure"] = ParamsInfo["Pressure"] * mm.unit.atmospheres 599 ParamsInfoWithUnits["BarostatInterval"] = ParamsInfo["BarostatInterval"] 600 601 SurfaceTensionInAngstroms = ParamsInfo["SurfaceTension"] 602 SurfaceTension = SurfaceTensionInAngstroms * mm.unit.atmospheres * mm.unit.angstroms 603 604 SurfaceTensionInNanometers = SurfaceTension.value_in_unit(mm.unit.atmospheres * mm.unit.nanometer) 605 ParamsInfoWithUnits["SurfaceTension"] = SurfaceTensionInNanometers * mm.unit.atmospheres * mm.unit.nanometers 606 607 XYMode = ParamsInfo["XYMode"] 608 XYModeSpecified = "" 609 if re.match("^Anisotropic$", XYMode, re.I): 610 XYMode = mm.MonteCarloMembraneBarostat.XYAnisotropic 611 XYModeSpecified = "Anisotropic" 612 elif re.match("^Isotropic$", XYMode, re.I): 613 XYMode = mm.MonteCarloMembraneBarostat.XYIsotropic 614 XYModeSpecified = "Isotropic" 615 else: 616 MiscUtil.PrintError("The parameter value specified, %s, for parameter name, xymode, for option \"--integratorParams\" is not a valid value. Supported values: Anisotropic or Isotropic" % XYMode) 617 ParamsInfoWithUnits["XYMode"] = XYMode 618 ParamsInfoWithUnits["XYModeSpecified"] = XYModeSpecified 619 620 ZMode = ParamsInfo["ZMode"] 621 ZModeSpecified = "" 622 if re.match("^Fixed$", ZMode, re.I): 623 ZMode = mm.MonteCarloMembraneBarostat.ZFixed 624 ZModeSpecified = "Fixed" 625 elif re.match("^Free$", ZMode, re.I): 626 ZMode = mm.MonteCarloMembraneBarostat.ZFree 627 ZModeSpecified = "Free" 628 else: 629 MiscUtil.PrintError("The parameter value specified, %s, for parameter name, zmode, for option \"--integratorParams\" is not a valid value. Supported values: Fixed or Free" % ZMode) 630 ParamsInfoWithUnits["ZMode"] = ZMode 631 ParamsInfoWithUnits["ZModeSpecified"] = ZModeSpecified 632 633 return ParamsInfoWithUnits 634 635 def SetupSimulationParameters(ParamsInfo): 636 """Setup simulation parameters for OpenMM API calls. 637 638 The ParamsInfo parameter is a dictionary of name and value pairs for 639 integrator parameters and may be generated by calling the function named 640 ProcessOptionOpenMSimulationParameters(). 641 642 Arguments: 643 ParamsInfo (dict): Parameter name and value pairs. 644 645 Returns: 646 dict: Integrator parameter name and values pairs. 647 648 Examples: 649 650 OptionsInfo["SimulationParams"] = 651 OpenMMUtil.ProcessOptionOpenMMSimulationParameters( 652 "--simulationParams", Options["--simulationParams"]) 653 ... ... ... 654 SimulationParams = SetupSimulationParameters( 655 OptionsInfo["SimulationParams"]) 656 657 """ 658 659 ParamsInfoWithUnits = {} 660 661 ParamsInfoWithUnits["Steps"] = ParamsInfo["Steps"] 662 663 ParamsInfoWithUnits["Minimization"] = ParamsInfo["Minimization"] 664 ParamsInfoWithUnits["MinimizationMaxSteps"] = ParamsInfo["MinimizationMaxSteps"] 665 666 MinimizationToleranceInKcal = ParamsInfo["MinimizationTolerance"] 667 MinimizationTolerance = MinimizationToleranceInKcal * mm.unit.kilocalories_per_mole/mm.unit.angstroms 668 669 MinimizationToleranceInJoules = MinimizationTolerance.value_in_unit(mm.unit.kilojoules_per_mole/mm.unit.nanometer) 670 MinimizationTolerance = MinimizationToleranceInJoules*mm.unit.kilojoules_per_mole/mm.unit.nanometer 671 672 ParamsInfoWithUnits["MinimizationToleranceInKcal"] = MinimizationToleranceInKcal 673 ParamsInfoWithUnits["MinimizationToleranceInJoules"] = MinimizationToleranceInJoules 674 ParamsInfoWithUnits["MinimizationTolerance"] = MinimizationTolerance 675 676 ParamsInfoWithUnits["Equilibration"] = ParamsInfo["Equilibration"] 677 ParamsInfoWithUnits["EquilibrationSteps"] = ParamsInfo["EquilibrationSteps"] 678 679 return ParamsInfoWithUnits 680 681 def ReimageRealignTrajectory(Topology, TrajFile, ReimageFrames = True, RealignFrames = True, Selection = "protein and backbone and name CA"): 682 """Reimage and realign a trajectory file using MDTraj. The trajectory frames 683 are reimaged before realigning to the first frame using the specified atom 684 selection. 685 686 The trajectory file format must a valid format supported by MDTraj. No 687 validation is performed. 688 689 Arguments: 690 Topology (str or object): PDB file name or OpenMM topology object. 691 TrajFile (str): Trajectory file name. 692 ReimageFrames (bool): Reimage trajectory frames. 693 RealignFrames (bool): Realign trajectory frames. 694 Selection (str): MDTraj atom selection for realigning frames. 695 696 Returns: 697 None or object: MDTraj trajectory object. 698 bool: Reimaged status. 699 bool: Realigned status. 700 701 """ 702 703 if isinstance(Topology, str): 704 MiscUtil.PrintInfo("Reading trajectory file %s (TopologyFile: %s)..." % (TrajFile, Topology)) 705 else: 706 MiscUtil.PrintInfo("Reading trajectory file %s..." % (TrajFile)) 707 Topology = mdtraj.Topology.from_openmm(Topology) 708 709 try: 710 Traj = mdtraj.load(TrajFile, top = Topology) 711 except Exception as ErrMsg: 712 MiscUtil.PrintInfo("") 713 MiscUtil.PrintWarning("Failed to read trajectory file: %s" % ErrMsg) 714 MiscUtil.PrintInfo("") 715 return (None, False, False) 716 717 ReimagedStatus, RealignedStatus = [False] * 2 718 719 if ReimageFrames: 720 MiscUtil.PrintInfo("Reimaging frames...") 721 try: 722 Traj.image_molecules(inplace = True) 723 ReimagedStatus = True 724 except Exception as ErrMsg: 725 MiscUtil.PrintInfo("") 726 MiscUtil.PrintWarning("Failed to reimage frames: %s" % ErrMsg) 727 MiscUtil.PrintInfo("") 728 else: 729 MiscUtil.PrintInfo("Skipping reimaging of frames...") 730 731 if RealignFrames: 732 MiscUtil.PrintInfo("Realigning frames to the first frame using selection \"%s\"..." % Selection) 733 try: 734 SelectionAtomIndices = Traj.top.select(Selection) 735 except Exception as ErrMsg: 736 MiscUtil.PrintInfo("") 737 MiscUtil.PrintWarning("Failed to align frames using selection \"%s\": %s" % (Selection, ErrMsg)) 738 MiscUtil.PrintInfo("") 739 return (Traj, ReimagedStatus, RealignedStatus) 740 741 if SelectionAtomIndices.size == 0: 742 MiscUtil.PrintInfo("") 743 MiscUtil.PrintWarning("Failed to align frames using selection \"%s\": No matched atoms found" % (Selection)) 744 MiscUtil.PrintInfo("") 745 return (Traj, ReimagedStatus, RealignedStatus) 746 747 RealignedStatus = True 748 Traj.superpose(Traj, frame = 0, atom_indices = SelectionAtomIndices) 749 else: 750 MiscUtil.PrintInfo("Skipping realignment of frames to the first frame...") 751 752 return (Traj, ReimagedStatus, RealignedStatus) 753 754 def FreezeAtoms(System, AtomList): 755 """Freeze atoms during a simulation. The specified atoms are kept completely 756 fixed by setting their masses to zero. Their positions do not change during 757 local energy minimization and MD simulation, and they do not contribute 758 to the kinetic energy of the system. 759 760 Arguments: 761 System (object): OpenMM system object. 762 AtomList (list): List of OpenMM atom objects. 763 764 Returns: 765 None 766 767 """ 768 769 if AtomList is None: 770 return 771 772 for Atom in AtomList: 773 System.setParticleMass(Atom.index, 0*mm.unit.amu) 774 775 def RestraintAtoms(System, Positions, AtomList, SpringConstantInKcal): 776 """Restraint atoms during a simulation. The motion of specified atoms is 777 restricted by adding a harmonic force that binds them to their starting 778 positions. The atoms are not completely fixed unlike freezing of atoms. 779 Their motion, however, is restricted and they are not able to move far away 780 from their starting positions during local energy minimization and MD 781 simulation. 782 783 The SpringConstantInKcal value must be specified in the units of 784 kcal/mol/A*82. It is automatically converted into the units of 785 kjoules/mol/nm**2 for OpenMM API call. 786 787 Arguments: 788 System (object): OpenMM system object. 789 Positions (object): OpenMM positons object object. 790 AtomList (list): List of OpenMM atom object. 791 SpringConstantInKcal (float): Spring constant value. 792 793 Returns: 794 None 795 796 """ 797 798 if AtomList is None: 799 return 800 801 SpringConstant = SpringConstantInKcal * mm.unit.kilocalories_per_mole/mm.unit.angstroms**2 802 SpringConstantInKjoules = SpringConstant.value_in_unit(mm.unit.kilojoules_per_mole/mm.unit.nanometer**2) 803 804 MiscUtil.PrintInfo("Restraint spring constant: %.2f kcal/mol/A**2 (%.2f kjoules/mol/nm**2)" % (SpringConstantInKcal, SpringConstantInKjoules)) 805 806 if DoesSystemUsesPeriodicBoundaryConditions(System): 807 # For periodic systems... 808 RestraintForce = mm.CustomExternalForce('k*periodicdistance(x, y, z, x0, y0, z0)^2') 809 else: 810 # For non-periodic systems... 811 RestraintForce = mm.CustomExternalForce('k*((x-x0)^2+(y-y0)^2+(z-z0)^2)') 812 813 SpringConstant = SpringConstantInKjoules * mm.unit.kilojoules_per_mole/mm.unit.nanometer**2 814 RestraintForce.addGlobalParameter('k', SpringConstant) 815 816 RestraintForce.addPerParticleParameter('x0') 817 RestraintForce.addPerParticleParameter('y0') 818 RestraintForce.addPerParticleParameter('z0') 819 820 for Atom in AtomList: 821 RestraintForce.addParticle(Atom.index, Positions[Atom.index]) 822 823 def GetAtoms(Topology, CAlphaProteinStatus, ResidueNames, Negate): 824 """Get a list of atoms in the specified residue names. You may set 825 CAlphaProteinStatus flag to True to only retrieve CAlpha atoms from 826 the residues. In addition, you may negate residue name match using 827 Negate flag. 828 829 Arguments: 830 Topology (object): OpenMM topology object. 831 CAlphaProteinStatus (bool): Get CAlpha atoms only. 832 ResidueNames (list): List of residue names. 833 Negate (bool): Negate residue name match. 834 835 Returns: 836 None or List of OpenMM atom objects. 837 838 """ 839 AtomList = [] 840 for Chain in Topology.chains(): 841 for Residue in Chain.residues(): 842 if CAlphaProteinStatus: 843 if Residue.name in ResidueNames: 844 for Atom in Residue.atoms(): 845 if _MatchName(Atom.name, ["CA"], Negate): 846 AtomList.append(Atom) 847 else: 848 if _MatchName(Residue.name, ResidueNames, Negate): 849 AtomList.extend(Residue.atoms()) 850 851 if len(AtomList) == 0: 852 AtomList = None 853 854 return AtomList 855 856 def _MatchName(Name, NamesList, Negate = False): 857 """Match name to the names in a list.""" 858 859 Status = True if Name in NamesList else False 860 if Negate: 861 Status = not Status 862 863 return Status 864 865 def DoesSystemUsesPeriodicBoundaryConditions(System): 866 """Check for the use of periodic boundary conditions in a system. 867 868 Arguments: 869 System (object): OpenMM system object. 870 871 Returns: 872 bool : True - Uses periodic boundary conditions; Otherwise, false. 873 874 """ 875 876 try: 877 Status = True if System.usesPeriodicBoundaryConditions() else False 878 except Exception: 879 Status = False 880 881 return Status 882 883 def DoesAtomListOverlapWithSystemConstraints(System, AtomList): 884 """Check for the overlap of specified atoms with the atoms involved 885 in system constraints. 886 887 Arguments: 888 System (object): OpenMM system object. 889 AtomList (list): List of OpenMM atom objects. 890 891 Returns: 892 bool : True - Overlap with system constraints; Otherwise, false. 893 894 """ 895 896 NumConstraints = System.getNumConstraints() 897 if NumConstraints == 0: 898 return False 899 900 if AtomList is None: 901 return False 902 903 AtomListIndices = [Atom.index for Atom in AtomList] 904 905 for Index in range(NumConstraints): 906 Particle1Index, Particle2Index, Distance = System.getConstraintParameters(Index) 907 if Particle1Index in AtomListIndices or Particle2Index in AtomListIndices: 908 return True 909 910 return False 911 912 def DoAtomListsOverlap(AtomList1, AtomList2): 913 """Check for the overlap of atoms in the specified atom lists. 914 915 Arguments: 916 AtomList1 (list): List of OpenMM atom objects. 917 AtomList2 (list): List of OpenMM atom objects. 918 919 Returns: 920 bool : True - Overlap between atoms lists; Otherwise, false. 921 922 """ 923 924 if AtomList1 is None or AtomList2 is None: 925 return False 926 927 AtomList1Indices = [Atom.index for Atom in AtomList1] 928 929 for Atom in AtomList2: 930 if Atom.index in AtomList1Indices: 931 return True 932 933 return False 934 935 def DoesSystemContainWater(Topology, WaterResidueNames = ['HOH']): 936 """Check for the presence of water residues in a system. 937 938 Arguments: 939 Topology (object): OpenMM modeller topology object. 940 WaterResidueNames (list): List of water residue names. 941 942 Returns: 943 bool : True - Contains water; Otherwise, false. 944 945 """ 946 947 Status = False 948 for Residue in Topology.residues(): 949 if Residue.name in WaterResidueNames: 950 Status = True 951 break 952 953 return Status 954 955 def ReadPDBFile(PDBFile): 956 """Read molecule from a PDB file. 957 958 The supported PDB file formats are pdb and cif. 959 960 Arguments: 961 PDBFile (str): Name of PDB file. 962 963 Returns: 964 object: OpenMM PDBFile or PDBFilex object. 965 966 """ 967 968 FileDir, FileName, FileExt = MiscUtil.ParseFileName(PDBFile) 969 if re.match("^pdb$", FileExt, re.I): 970 PDBHandle = mm.app.PDBFile(PDBFile) 971 elif re.match("^cif$", FileExt, re.I): 972 PDBHandle = mm.app.PDBxFile(PDBFile) 973 else: 974 MiscUti.PrintError("Failed to read PDB file. Invalid PDB file format %s...\n" % PDBFile) 975 976 return PDBHandle 977 978 def WritePDBFile(PDBFile, Topology, Positions, KeepIDs = True): 979 """Write a PDB file. 980 981 The supported PDB file formats are pdb and cif. 982 983 Arguments: 984 PDBFile (str): Name of PDB file. 985 Topology (object): Topology OpenMM object. 986 Positions (object): Positions OpenMM object. 987 KeepIDs (bool): Keep existing residue and chain IDs. 988 989 Returns: 990 None 991 992 """ 993 994 FileDir, FileName, FileExt = MiscUtil.ParseFileName(PDBFile) 995 if re.match("^pdb$", FileExt, re.I): 996 mm.app.PDBFile.writeFile(Topology, Positions, PDBFile, KeepIDs) 997 elif re.match("^cif$", FileExt, re.I): 998 mm.app.PDBxFile.writeFile(Topology, Positions, PDBFile, KeepIDs) 999 else: 1000 MiscUti.PrintError("Failed to write PDB file. Invalid PDB file format %s...\n" % PDBFile) 1001 1002 def WriteSimulationStatePDBFile(Simulation, PDBFile, KeepIDs = True): 1003 """Write a PDB file for current simulation state. 1004 1005 The supported PDB file formats are pdb and cif. 1006 1007 Arguments: 1008 Simulation (object): OpenMM simulation object. 1009 PDBFile (str): Name of PDB fil. 1010 KeepIDs (bool): Keep existing residue and chain IDs. 1011 1012 Returns: 1013 None 1014 1015 """ 1016 1017 CurrentPositions = Simulation.context.getState(getPositions = True).getPositions() 1018 WritePDBFile(PDBFile, Simulation.topology, CurrentPositions, KeepIDs) 1019 1020 def ReadSmallMoleculeFile(FileName): 1021 """Read small molecule file using OpenFF toolkit. 1022 1023 Arguments: 1024 FileName (str): Small molecule file name. 1025 1026 Returns: 1027 None or OpenFF tookit molecule object. 1028 1029 """ 1030 1031 try: 1032 SmallMol = ff.toolkit.Molecule.from_file(FileName) 1033 except Exception as ErrMsg: 1034 SmallMol = None 1035 MiscUtil.PrintInfo("") 1036 MiscUtil.PrintWarning("OpenFF.toolkit.Molecule.from_file() failed: %s" % ErrMsg) 1037 MiscUtil.PrintInfo("") 1038 1039 return SmallMol 1040 1041 def MergeSmallMoleculeWithMacromolecule(ModellerHandle, SmallMol, SmallMolID = "LIG"): 1042 """Merge small molecule with macromolecule data contained in a modeller object and 1043 assign a three letter small molecule residue name to the merged small molecule. 1044 1045 Arguments: 1046 ModellerHandle (object): OpenMM modeller object. 1047 SmallMol (object): OpenFF tookit molecule object. 1048 SmallMolID (str): Three letter residue name for small molecule. 1049 1050 Returns: 1051 None 1052 1053 """ 1054 1055 SmallMolToplogy = SmallMol.to_topology() 1056 SmallMolOpenMMTopology = SmallMolToplogy.to_openmm() 1057 SmallMolOpenMMPositions = SmallMolToplogy.get_positions().to_openmm() 1058 1059 # Set small molecule residue name to LIG... 1060 for Chain in SmallMolOpenMMTopology.chains(): 1061 for Residue in Chain.residues(): 1062 Residue.name = SmallMolID 1063 1064 ModellerHandle.add(SmallMolOpenMMTopology, SmallMolOpenMMPositions) 1065 1066 def GetFormattedTotalSimulationTime(StepSize, Steps): 1067 """Get formatted total simulation time with appropriate time units. 1068 parameter names and values. 1069 1070 Arguments: 1071 StepSize (object): OpenMM quantity object. 1072 Steps (int): Number of steps. 1073 1074 Returns: 1075 str: Total time. 1076 1077 """ 1078 1079 TotalTime = StepSize * Steps 1080 TotalTimeValue = TotalTime.value_in_unit(mm.unit.femtoseconds) 1081 1082 if TotalTimeValue < 1e3: 1083 TotalTimeUnits = "fs" 1084 TotalTime = TotalTime.value_in_unit(mm.unit.femtoseconds) 1085 elif TotalTimeValue < 1e6: 1086 TotalTimeUnits = "ps" 1087 TotalTime = TotalTime.value_in_unit(mm.unit.picoseconds) 1088 elif TotalTimeValue < 1e9: 1089 TotalTimeUnits = "ns" 1090 TotalTime = TotalTime.value_in_unit(mm.unit.nanoseconds) 1091 elif TotalTimeValue < 1e12: 1092 TotalTimeUnits = "us" 1093 TotalTime = TotalTime.value_in_unit(mm.unit.microseconds) 1094 else: 1095 TotalTimeUnits = "ms" 1096 TotalTime = TotalTime.value_in_unit(mm.unit.milliseconds) 1097 1098 TotalTime = "%.2f %s" % (TotalTime, TotalTimeUnits) 1099 1100 return TotalTime 1101 1102 def ProcessOptionOpenMMRestartParameters(ParamsOptionName, ParamsOptionValue, OutfilePrefix, ParamsDefaultInfo = None): 1103 """Process parameters for restart option and return a map containing processed 1104 parameter names and values. 1105 1106 ParamsOptionValue is a comma delimited list of parameter name and value pairs 1107 to setup platform. 1108 1109 The supported parameter names along with their default and possible 1110 values are shown below: 1111 1112 finalStateFile, <OutfilePrefix>_FinalState.<chk> [ Possible values: 1113 Valid final state checkpoint or XML filename ] 1114 dataAppend, yes [ Possible values: yes or no] 1115 1116 A brief description of parameters is provided below: 1117 1118 finalStateFile: Final state checkpoint or XML file 1119 1120 dataAppend: Append data to existing trajectory and data log files during the 1121 restart of a simulation using a previously saved final state checkpoint or 1122 XML file. 1123 1124 Arguments: 1125 ParamsOptionName (str): Command line OpenMM restart option name. 1126 ParamsOptionValues (str): Space delimited list of parameter name and value pairs. 1127 OutfilePrefix (str): Prefix for output files. 1128 ParamsDefaultInfo (dict): Default values to override for selected parameters. 1129 1130 Returns: 1131 dictionary: Processed parameter name and value pairs. 1132 1133 """ 1134 1135 ParamsInfo = {"FinalStateFile": "auto", "DataAppend": True} 1136 1137 (ValidParamNames, CanonicalParamNamesMap, ParamsOptionValue, ParamsOptionValueWords) = _ValidateAndCanonicalizeParameterNames(ParamsOptionName, ParamsOptionValue, ParamsInfo, ParamsDefaultInfo) 1138 1139 if re.match("^auto$", ParamsOptionValue, re.I): 1140 _ProcessOptionOpenMMRestartParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue, OutfilePrefix) 1141 return ParamsInfo 1142 1143 for Index in range(0, len(ParamsOptionValueWords), 2): 1144 Name = ParamsOptionValueWords[Index].strip() 1145 Value = ParamsOptionValueWords[Index + 1].strip() 1146 1147 ParamName = CanonicalParamNamesMap[Name.lower()] 1148 ParamValue = Value 1149 1150 if re.match("^FinalStateFile$", ParamName, re.I): 1151 if not re.match("^auto$", Value, re.I): 1152 if not os.path.exists(Value): 1153 MiscUtil.PrintError("The file name specified, %s, for parameter name, %s, using option \"%s\" doesn't exist.\n." % (Value, Name, ParamsOptionName)) 1154 if not MiscUtil.CheckFileExt(Value, "chk xml"): 1155 MiscUtil.PrintError("The file name specified, %s, for parameter name, %s, using option \"%s\" is not valid file. Supported file formats: chk or xml\n." % (Value, Name, ParamsOptionName)) 1156 ParamValue = Value 1157 elif re.match("^DataAppend$", ParamName, re.I): 1158 if not re.match("^(yes|no|true|false)$", Value, re.I): 1159 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. Supported values: yes or no" % (Value, Name, ParamsOptionName)) 1160 ParamValue = True if re.match("^(yes|true)$", Value, re.I) else False 1161 else: 1162 ParamValue = Value 1163 1164 # Set value... 1165 ParamsInfo[ParamName] = ParamValue 1166 1167 # Handle parameters with possible auto values... 1168 _ProcessOptionOpenMMRestartParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue, OutfilePrefix) 1169 1170 return ParamsInfo 1171 1172 def _ProcessOptionOpenMMRestartParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue, OutfilePrefix): 1173 """Process parameters with possible auto values and perform validation. 1174 """ 1175 1176 FinalStateFileCheckpointMode = False 1177 FinalStateFileXMLMode = False 1178 1179 ParamName = "FinalStateFile" 1180 FinalStateFile = ParamsInfo[ParamName] 1181 if re.match("^auto$", FinalStateFile, re.I): 1182 FinalStateFile = "%s_FinalState.chk" % OutfilePrefix 1183 FinalStateFileCheckpointMode = True 1184 else: 1185 if MiscUtil.CheckFileExt(FinalStateFile, "chk"): 1186 FinalStateFileCheckpointMode = True 1187 elif MiscUtil.CheckFileExt(FinalStateFile, "xml"): 1188 FinalStateFileXMLMode = True 1189 else: 1190 MiscUtil.PrintError("The file name specified, %s, for parameter name, %s, using option \"%s\ is not valid. Supported file formats: chk or xml\n." % (FinalStateFile, ParamName, ParamsOptionName)) 1191 1192 ParamsInfo["FinalStateFile"] = FinalStateFile 1193 ParamsInfo["FinalStateFileCheckpointMode"] = FinalStateFileCheckpointMode 1194 ParamsInfo["FinalStateFileXMLMode"] = FinalStateFileXMLMode 1195 1196 def ProcessOptionOpenMMSystemParameters(ParamsOptionName, ParamsOptionValue, ParamsDefaultInfo = None): 1197 """Process parameters for system option and return a map containing processed 1198 parameter names and values. 1199 1200 ParamsOptionValue is a comma delimited list of parameter name and value pairs 1201 to setup platform. 1202 1203 The supported parameter names along with their default and possible 1204 values are shown below: 1205 1206 constraints, BondsInvolvingHydrogens [ Possible values: None, 1207 WaterOnly, BondsInvolvingHydrogens, AllBonds, or 1208 AnglesInvolvingHydrogens ] 1209 constraintErrorTolerance, 0.000001 1210 ewaldErrorTolerance, 0.0005 1211 1212 nonbondedMethodPeriodic, PME [ Possible values: NoCutoff, 1213 CutoffNonPeriodic, or PME ] 1214 nonbondedMethodNonPeriodic, NoCutoff [ Possible values: 1215 NoCutoff or CutoffNonPeriodic] 1216 nonbondedCutoff, 1.0 [ Units: nm ] 1217 1218 hydrogenMassRepartioning, yes [ Possible values: yes or no ] 1219 hydrogenMass, 1.5 [ Units: amu] 1220 1221 removeCMMotion, yes [ Possible values: yes or no ] 1222 rigidWater, auto [ Possible values: yes or no. Default: 'No' for 1223 'None' value of constraints; Otherwise, yes ] 1224 1225 A brief description of parameters is provided below: 1226 1227 constraints: Type of system constraints to use for simulation. These constraints 1228 are different from freezing and restraining of any atoms in the system. 1229 1230 constraintErrorTolerance: Distance tolerance for constraints as a fraction 1231 of the constrained distance. 1232 1233 ewaldErrorTolerance: Ewald error tolerance for a periodic system. 1234 1235 nonbondedMethodPeriodic: Nonbonded method to use during the calculation of 1236 long range interactions for a periodic system. 1237 1238 nonbondedMethodNonPeriodic: Nonbonded method to use during the calculation 1239 of long range interactions for a non-periodic system. 1240 1241 nonbondedCutoff: Cutoff distance to use for long range interactions in both 1242 perioidic non-periodic systems. 1243 1244 hydrogenMassRepartioning: Use hydrogen mass repartioning. It increases the 1245 mass of the hydrogen atoms attached to the heavy atoms and decreasing the 1246 mass of the bonded heavy atom to maintain constant system mass. This allows 1247 the use of larger integration step size (4 fs) during a simulation. 1248 1249 hydrogenMass: Hydrogen mass to use during repartioning. 1250 1251 removeCMMotion: Remove all center of mass motion at every time step. 1252 1253 rigidWater: Keep water rigid during a simulation. This is determined 1254 automatically based on the value of 'constraints' parameter. 1255 1256 Arguments: 1257 ParamsOptionName (str): Command line OpenMM system option name. 1258 ParamsOptionValues (str): Space delimited list of parameter name and value pairs. 1259 ParamsDefaultInfo (dict): Default values to override for selected parameters. 1260 1261 Returns: 1262 dictionary: Processed parameter name and value pairs. 1263 1264 """ 1265 1266 ParamsInfo = {"Constraints": "BondsInvolvingHydrogens", "ConstraintErrorTolerance": 0.000001, "EwaldErrorTolerance": 0.0005, "NonbondedMethodPeriodic": "PME", "NonbondedMethodNonPeriodic": "NoCutoff", "NonbondedCutoff": 1.0, "HydrogenMassRepartioning": True, "HydrogenMass": 1.5, "RemoveCMMotion": True, "RigidWater": "auto"} 1267 1268 (ValidParamNames, CanonicalParamNamesMap, ParamsOptionValue, ParamsOptionValueWords) = _ValidateAndCanonicalizeParameterNames(ParamsOptionName, ParamsOptionValue, ParamsInfo, ParamsDefaultInfo) 1269 1270 if re.match("^auto$", ParamsOptionValue, re.I): 1271 _ProcessOptionOpenMMSystemParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue) 1272 return ParamsInfo 1273 1274 for Index in range(0, len(ParamsOptionValueWords), 2): 1275 Name = ParamsOptionValueWords[Index].strip() 1276 Value = ParamsOptionValueWords[Index + 1].strip() 1277 1278 ParamName = CanonicalParamNamesMap[Name.lower()] 1279 ParamValue = Value 1280 1281 if re.match("^Constraints$", ParamName, re.I): 1282 if not re.match("^auto$", Value, re.I): 1283 if not re.match("^(None|WaterOnly|BondsInvolvingHydrogens|AllBonds|AnglesInvolvingHydrogens)$", Value, re.I): 1284 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. Supported values: None, WaterOnly, BondsInvolvingHydrogens, AllBonds, or AnglesInvolvingHydrogens." % (Value, Name, ParamsOptionName)) 1285 ParamValue = Value 1286 elif re.match("^(ConstraintErrorTolerance|EwaldErrorTolerance|NonbondedCutoff|HydrogenMass)$", ParamName, re.I): 1287 if not MiscUtil.IsFloat(Value): 1288 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option must be a float.\n" % (Value, ParamName, ParamsOptionName)) 1289 Value = float(Value) 1290 if Value <= 0: 1291 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. Supported values: > 0\n" % (ParamValue, ParamName, ParamsOptionName)) 1292 ParamValue = Value 1293 elif re.match("^NonbondedMethodPeriodic$", ParamName, re.I): 1294 if not re.match("^(NoCutoff|CutoffPeriodic|PME)$", Value, re.I): 1295 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. Supported values: NoCutoff, CutoffPeriodic, or PME" % (Value, Name, ParamsOptionName)) 1296 ParamValue = Value 1297 elif re.match("^NonbondedMethodNonPeriodic$", ParamName, re.I): 1298 if not re.match("^(NoCutoff|CutoffNonPeriodic)$", Value, re.I): 1299 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. Supported values: NoCutoff or CutoffNonPeriodic" % (Value, Name, ParamsOptionName)) 1300 ParamValue = Value 1301 elif re.match("^(HydrogenMassRepartioning|removeCMMotion)$", ParamName, re.I): 1302 if not re.match("^(yes|no|true|false)$", Value, re.I): 1303 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. Supported values: yes or no" % (Value, Name, ParamsOptionName)) 1304 ParamValue = True if re.match("^(yes|true)$", Value, re.I) else False 1305 elif re.match("^RigidWater$", ParamName, re.I): 1306 if not re.match("^auto$", Value, re.I): 1307 if not re.match("^(yes|no|true|false)$", Value, re.I): 1308 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. Supported values: yes or no" % (Value, Name, ParamsOptionName)) 1309 ParamValue = True if re.match("^(yes|true)$", Value, re.I) else False 1310 else: 1311 ParamValue = Value 1312 1313 # Set value... 1314 ParamsInfo[ParamName] = ParamValue 1315 1316 # Handle parameters with possible auto values... 1317 _ProcessOptionOpenMMSystemParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue) 1318 1319 return ParamsInfo 1320 1321 def _ProcessOptionOpenMMSystemParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue): 1322 """Process parameters with possible auto values and perform validation. 1323 """ 1324 1325 for ParamName in ["NonbondedMethodPeriodic", "NonbondedMethodNonPeriodic"]: 1326 ParamValue = ParamsInfo[ParamName] 1327 if re.match("^NoCutoff$", ParamValue, re.I): 1328 ParamValue = mm.app.NoCutoff 1329 elif re.match("^CutoffNonPeriodic$", ParamValue, re.I): 1330 ParamValue = mm.app.CutoffNonPeriodic 1331 elif re.match("^CutoffPeriodic$", ParamValue, re.I): 1332 ParamValue = mm.app.CutoffPeriodic 1333 elif re.match("^PME$", ParamValue, re.I): 1334 ParamValue = mm.app.PME 1335 else: 1336 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. Supported values: NoCutoff, CutoffNonPeriodic, CutoffPeriodic, or PME" % (ParamValue, ParamName, ParamsOptionName)) 1337 ParamsInfo[ParamName] = ParamValue 1338 1339 ParamName = "Constraints" 1340 ParamValue = ParamsInfo[ParamName] 1341 ConstraintsValue = None 1342 RigidWaterValue = False 1343 if re.match("^None$", ParamValue, re.I): 1344 ConstraintsValue = None 1345 RigidWaterValue = False 1346 elif re.match("^WaterOnly$", ParamValue, re.I): 1347 ConstraintsValue = None 1348 RigidWaterValue = True 1349 elif re.match("^BondsInvolvingHydrogens$", ParamValue, re.I): 1350 ConstraintsValue = mm.app.HBonds 1351 RigidWaterValue = True 1352 elif re.match("^AllBonds$", ParamValue, re.I): 1353 ConstraintsValue = mm.app.AllBonds 1354 RigidWaterValue = True 1355 elif re.match("^AnglesInvolvingHydrogens$", ParamValue, re.I): 1356 ConstraintsValue = mm.app.HAngles 1357 RigidWaterValue = True 1358 else: 1359 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. Supported values: None, WaterOnly, BondsInvolvingHydrogens, AllBonds, or AnglesInvolvingHydrogens." % (ParamValue, ParamName, ParamsOptionName)) 1360 1361 ParamsInfo[ParamName] = ConstraintsValue 1362 1363 ParamName = "RigidWater" 1364 ParamValue = "%s" % ParamsInfo[ParamName] 1365 if re.match("^auto$", ParamValue, re.I): 1366 ParamsInfo[ParamName] = RigidWaterValue 1367 1368 def ProcessOptionOpenMMIntegratorParameters(ParamsOptionName, ParamsOptionValue, ParamsDefaultInfo = None, HydrogenMassRepartioningStatus = False): 1369 """Process parameters for integrator option and return a map containing processed 1370 parameter names and values. 1371 1372 ParamsOptionValue is a comma delimited list of parameter name and value pairs 1373 to setup platform. 1374 1375 The supported parameter names along with their default and possible 1376 values are shown below: 1377 1378 integrator, LangevinMiddle [ Possible values: LangevinMiddle, 1379 Langevin, NoseHoover, Brownian ] 1380 1381 randomSeed, auto [ Possible values: > 0 ] 1382 1383 frictionCoefficient, 1.0 [ Units: 1/ps ] 1384 stepSize, auto [ Units: fs; Default value: 4 fs during yes value of 1385 hydrogen mass repartioning with no freezing/restraining of atoms; 1386 otherwsie, 2 fs ] 1387 temperature, 300.0 [ Units: kelvin ] 1388 1389 barostat, MonteCarlo [ Possible values: MonteCarlo or 1390 MonteCarloMembrane ] 1391 barostatInterval, 25 1392 pressure, 1.0 [ Units: atm ] 1393 1394 Parameters used only for MonteCarloMembraneBarostat with default 1395 values corresponding to Amber forcefields: 1396 1397 surfaceTension, 0.0 [ Units: atm*A. It is automatically converted 1398 into OpenMM default units of atm*nm before its usage. ] 1399 xymode, Isotropic [ Possible values: Anisotropic or Isotropic ] 1400 zmode, Free [ Possible values: Free or Fixed ] 1401 1402 A brief description of parameters is provided below: 1403 1404 integrator: Type of integrator 1405 1406 randomSeed: Random number seed for barostat and integrator. Not supported 1407 NoseHoover integrator. 1408 1409 frictionCoefficient: Friction coefficient for coupling the system to the heat 1410 bath. 1411 1412 stepSize: Simulation time step size. 1413 1414 temperature: Simulation temperature. 1415 1416 barostat: Barostat type. 1417 1418 barostatInterval: Barostat interval step size during NPT simulation for 1419 applying Monte Carlo pressure changes. 1420 1421 pressure: Pressure during NPT simulation. 1422 1423 surfaceTension: Surface tension acting on the system. 1424 1425 xymode: Behavior along X and Y axes. You may allow the X and Y axes 1426 to vary independently of each other or always scale them by the same 1427 amount to keep the ratio of their lengths constant. 1428 1429 zmode: Beahvior along Z axis. You may allow the Z axis to vary 1430 independently of the other axes or keep it fixed. 1431 1432 Arguments: 1433 ParamsOptionName (str): Command line OpenMM integrator option name. 1434 ParamsOptionValues (str): Space delimited list of parameter name and value pairs. 1435 ParamsDefaultInfo (dict): Default values to override for selected parameters. 1436 1437 Returns: 1438 dictionary: Processed parameter name and value pairs. 1439 1440 """ 1441 1442 ParamsInfo = {"Integrator": "LangevinMiddle", "RandomSeed": "auto", "FrictionCoefficient": 1.0, "StepSize": "auto", "Temperature": 300.0, "Barostat": "MonteCarlo", "BarostatInterval": 25, "Pressure": 1.0, "SurfaceTension": 0.0, "XYMode": "Isotropic", "ZMode": "Free"} 1443 1444 (ValidParamNames, CanonicalParamNamesMap, ParamsOptionValue, ParamsOptionValueWords) = _ValidateAndCanonicalizeParameterNames(ParamsOptionName, ParamsOptionValue, ParamsInfo, ParamsDefaultInfo) 1445 1446 if re.match("^auto$", ParamsOptionValue, re.I): 1447 _ProcessOptionOpenMMIntegratorParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue, HydrogenMassRepartioningStatus) 1448 return ParamsInfo 1449 1450 for Index in range(0, len(ParamsOptionValueWords), 2): 1451 Name = ParamsOptionValueWords[Index].strip() 1452 Value = ParamsOptionValueWords[Index + 1].strip() 1453 1454 ParamName = CanonicalParamNamesMap[Name.lower()] 1455 ParamValue = Value 1456 1457 if re.match("^Integrator$", ParamName, re.I): 1458 if not re.match("^(LangevinMiddle|Langevin|NoseHoover|Brownian)$", Value, re.I): 1459 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. Supported values: LangevinMiddle,Langevin, NoseHoover, or Brownian." % (Value, Name, ParamsOptionName)) 1460 ParamValue = Value 1461 elif re.match("^(FrictionCoefficient|Pressure)$", ParamName, re.I): 1462 if not MiscUtil.IsFloat(Value): 1463 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option must be a float.\n" % (Value, ParamName, ParamsOptionName)) 1464 Value = float(Value) 1465 if Value <= 0: 1466 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. Supported values: > 0\n" % (ParamValue, ParamName, ParamsOptionName)) 1467 ParamValue = Value 1468 elif re.match("^StepSize$", ParamName, re.I): 1469 if not re.match("^auto$", Value, re.I): 1470 if not MiscUtil.IsFloat(Value): 1471 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option must be a float.\n" % (Value, ParamName, ParamsOptionName)) 1472 Value = float(Value) 1473 if Value <= 0: 1474 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. Supported values: > 0\n" % (ParamValue, ParamName, ParamsOptionName)) 1475 ParamValue = Value 1476 elif re.match("^(Temperature|SurfaceTension)$", ParamName, re.I): 1477 if not MiscUtil.IsFloat(Value): 1478 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option must be a float.\n" % (Value, ParamName, ParamsOptionName)) 1479 Value = float(Value) 1480 if Value < 0: 1481 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. Supported values: >= 0\n" % (ParamValue, ParamName, ParamsOptionName)) 1482 ParamValue = Value 1483 elif re.match("^BarostatInterval$", ParamName, re.I): 1484 if not MiscUtil.IsInteger(Value): 1485 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option must be an integer.\n" % (Value, ParamName, ParamsOptionName)) 1486 Value = int(Value) 1487 if Value <= 0: 1488 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. Supported values: > 0\n" % (ParamValue, ParamName, ParamsOptionName)) 1489 ParamValue = Value 1490 elif re.match("^Barostat$", ParamName, re.I): 1491 if not re.match("^(MonteCarlo|MonteCarloMembrane)$", Value, re.I): 1492 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. Supported values: MonteCarlo or MonteCarloMembrane" % (Value, Name, ParamsOptionName)) 1493 ParamValue = Value 1494 elif re.match("^XYMode$", ParamName, re.I): 1495 if not re.match("^(Anisotropic|Isotropic)$", Value, re.I): 1496 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. Supported values: Anisotropic or Isotropic" % (Value, Name, ParamsOptionName)) 1497 ParamValue = Value 1498 elif re.match("^ZMode$", ParamName, re.I): 1499 if not re.match("^(Free|Fixed)$", Value, re.I): 1500 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. Supported values: Fixed or Free" % (Value, Name, ParamsOptionName)) 1501 ParamValue = Value 1502 elif re.match("^RandomSeed$", ParamName, re.I): 1503 if not re.match("^auto$", Value, re.I): 1504 if not MiscUtil.IsInteger(Value): 1505 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option must be an integer.\n" % (Value, ParamName, ParamsOptionName)) 1506 Value = int(Value) 1507 if Value <= 0: 1508 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. Supported values: > 0\n" % (ParamValue, ParamName, ParamsOptionName)) 1509 ParamValue = Value 1510 else: 1511 ParamValue = Value 1512 1513 # Set value... 1514 ParamsInfo[ParamName] = ParamValue 1515 1516 # Handle parameters with possible auto values... 1517 _ProcessOptionOpenMMIntegratorParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue, HydrogenMassRepartioningStatus) 1518 1519 return ParamsInfo 1520 1521 def _ProcessOptionOpenMMIntegratorParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue, HydrogenMassRepartioningStatus): 1522 """Process parameters with possible auto values and perform validation. 1523 """ 1524 1525 ParamName = "StepSize" 1526 ParamValue = "%s" % ParamsInfo[ParamName] 1527 ParamsInfo["StepSizeSpecified"] = ParamValue 1528 if re.match("^auto$", ParamValue, re.I): 1529 ParamValue = 4.0 if HydrogenMassRepartioningStatus else 2.0 1530 ParamsInfo[ParamName] = ParamValue 1531 1532 ParamName = "RandomSeed" 1533 ParamValue = "%s" % ParamsInfo[ParamName] 1534 ParamsInfo["RandomSeedSpecified"] = ParamValue 1535 if re.match("^auto$", ParamValue, re.I): 1536 ParamsInfo[ParamName] = None 1537 1538 def ProcessOptionOpenMMSimulationParameters(ParamsOptionName, ParamsOptionValue, ParamsDefaultInfo = None): 1539 """Process parameters for simulation option and return a map containing processed 1540 parameter names and values. 1541 1542 ParamsOptionValue is a comma delimited list of parameter name and value pairs 1543 to setup platform. 1544 1545 The supported parameter names along with their default and possible 1546 values are shown below: 1547 1548 steps, 1000000 [ Possible values: > 0 ] 1549 1550 minimization, yes [ Possible values: yes or no ] 1551 minimizationMaxSteps, auto [ Possible values: >= 0. The value of 1552 zero implies until the minimization is converged. ] 1553 minimizationTolerance, 0.25 [ Units: kcal/mol/A. The default value 1554 0.25, corresponds to OpenMM default of value of 10.04 1555 kjoules/mol/nm. It is automatically converted into OpenMM 1556 default units before its usage. ] 1557 1558 equilibration, yes [ Possible values: yes or no ] 1559 equilibrationSteps, 1000 [ Possible values: > 0 ] 1560 1561 A brief description of parameters is provided below: 1562 1563 steps: Number of steps for production run. 1564 1565 equilibration: Perform equilibration before the production run. 1566 1567 equilibrationSteps: Number of steps for equilibration. 1568 1569 minimizationMaxSteps: Maximum number of minimization steps. The value 1570 of zero implies until the minimization is converged. 1571 1572 minimizationTolerance: Energy convergence tolerance during minimization. 1573 1574 minimization: Perform minimization before equilibration and production run. 1575 1576 Arguments: 1577 ParamsOptionName (str): Command line OpenMM simulation option name. 1578 ParamsOptionValues (str): Space delimited list of parameter name and value pairs. 1579 ParamsDefaultInfo (dict): Default values to override for selected parameters. 1580 1581 Returns: 1582 dictionary: Processed parameter name and value pairs. 1583 1584 """ 1585 1586 ParamsInfo = {"Steps": 1000000, "Minimization": True, "MinimizationMaxSteps": "auto", "MinimizationTolerance": 0.24, "Equilibration": True, "EquilibrationSteps": 1000} 1587 1588 (ValidParamNames, CanonicalParamNamesMap, ParamsOptionValue, ParamsOptionValueWords) = _ValidateAndCanonicalizeParameterNames(ParamsOptionName, ParamsOptionValue, ParamsInfo, ParamsDefaultInfo) 1589 1590 if re.match("^auto$", ParamsOptionValue, re.I): 1591 _ProcessOptionOpenMMSimulationParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue) 1592 return ParamsInfo 1593 1594 for Index in range(0, len(ParamsOptionValueWords), 2): 1595 Name = ParamsOptionValueWords[Index].strip() 1596 Value = ParamsOptionValueWords[Index + 1].strip() 1597 1598 ParamName = CanonicalParamNamesMap[Name.lower()] 1599 ParamValue = Value 1600 1601 if re.match("^(Steps|EquilibrationSteps)$", ParamName, re.I): 1602 if not MiscUtil.IsInteger(Value): 1603 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option must be an integer.\n" % (Value, ParamName, ParamsOptionName)) 1604 Value = int(Value) 1605 if Value <= 0: 1606 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. Supported values: > 0\n" % (ParamValue, ParamName, ParamsOptionName)) 1607 ParamValue = Value 1608 elif re.match("^(Minimization|Equilibration)$", ParamName, re.I): 1609 if not re.match("^(yes|no|true|false)$", Value, re.I): 1610 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. Supported values: yes or no" % (Value, Name, ParamsOptionName)) 1611 ParamValue = True if re.match("^(yes|true)$", Value, re.I) else False 1612 elif re.match("^MinimizationMaxSteps$", ParamName, re.I): 1613 if not re.match("^auto$", Value, re.I): 1614 if not MiscUtil.IsInteger(Value): 1615 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option must be an integer.\n" % (Value, ParamName, ParamsOptionName)) 1616 Value = int(Value) 1617 if Value < 0: 1618 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. Supported values: >= 0\n" % (ParamValue, ParamName, ParamsOptionName)) 1619 ParamValue = Value 1620 elif re.match("^MinimizationTolerance$", ParamName, re.I): 1621 if not MiscUtil.IsFloat(Value): 1622 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option must be a float.\n" % (Value, ParamName, ParamsOptionName)) 1623 Value = float(Value) 1624 if Value <= 0: 1625 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. Supported values: > 0\n" % (ParamValue, ParamName, ParamsOptionName)) 1626 ParamValue = Value 1627 else: 1628 ParamValue = Value 1629 1630 # Set value... 1631 ParamsInfo[ParamName] = ParamValue 1632 1633 # Handle parameters with possible auto values... 1634 _ProcessOptionOpenMMSimulationParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue) 1635 1636 return ParamsInfo 1637 1638 def _ProcessOptionOpenMMSimulationParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue): 1639 """Process parameters with possible auto values and perform validation. 1640 """ 1641 1642 ParamName = "MinimizationMaxSteps" 1643 ParamValue = "%s" % ParamsInfo[ParamName] 1644 if re.match("^auto$", ParamValue, re.I): 1645 ParamsInfo[ParamName] = 0 1646 1647 def ProcessOptionOpenMMOutputParameters(ParamsOptionName, ParamsOptionValue, OutfilePrefix, ParamsDefaultInfo = None): 1648 """Process parameters for output option and return a map containing processed 1649 parameter names and values. 1650 1651 ParamsOptionValue is a comma delimited list of parameter name and value pairs 1652 to setup platform. 1653 1654 The supported parameter names along with their default and possible 1655 values are shown below: 1656 1657 checkpoint, no [ Possible values: yes or no ] 1658 checkpointFile, auto [ Default: <OutfilePrefix>.chk ] 1659 checkpointSteps, 10000 1660 1661 dataOutType, auto [ Possible values: A space delimited list of valid 1662 parameter names. 1663 NPT simulation default: Density Step Speed Progress 1664 PotentialEnergy Temperature Time. 1665 NVT simulation default: Step Speed Progress PotentialEnergy 1666 Temperature Time Volumne 1667 Other valid names: ElapsedTime RemainingTime KineticEnergy 1668 TotalEnergy ] 1669 1670 dataLog, yes [ Possible values: yes or no ] 1671 dataLogFile, auto [ Default: <OutfilePrefix>.csv ] 1672 dataLogSteps, 1000 1673 1674 dataStdout, no [ Possible values: yes or no ] 1675 dataStdoutSteps, 1000 1676 1677 minimizationDataSteps, 100 1678 minimizationDataStdout, no [ Possible values: yes or no ] 1679 minimizationDataLog, no [ Possible values: yes or no ] 1680 minimizationDataLogFile, auto [ Default: 1681 <OutfilePrefix>_MinimizationOut.csv ] 1682 minimizationDataOutType, auto [ Possible values: A space delimited 1683 list of valid parameter names. Default: SystemEnergy 1684 RestraintEnergy MaxConstraintError. 1685 Other valid names: RestraintStrength ] 1686 1687 pdbOutFormat, PDB [ Possible values: PDB or CIF ] 1688 pdbOutKeepIDs, yes [ Possible values: yes or no ] 1689 1690 pdbOutMinimized, no [ Possible values: yes or no ] 1691 pdbOutEquilibrated, no [ Possible values: yes or no ] 1692 pdbOutFinal, no [ Possible values: yes or no ] 1693 1694 saveFinalStateCheckpoint, yes [ Possible values: yes or no ] 1695 saveFinalStateCheckpointFile, auto [ Default: 1696 <OutfilePrefix>_FinalState.chk ] 1697 saveFinalStateXML, no [ Possible values: yes or no ] 1698 saveFinalStateXMLFile, auto [ Default: 1699 <OutfilePrefix>_FinalState.xml] 1700 1701 traj, yes [ Possible values: yes or no ] 1702 trajFile, auto [ Default: <OutfilePrefix>.<TrajFormat> ] 1703 trajFormat, DCD [ Possible values: DCD or XTC ] 1704 trajSteps, 10000 1705 1706 xmlSystemOut, no [ Possible values: yes or no ] 1707 xmlSystemFile, auto [ Default: <OutfilePrefix>_System.xml ] 1708 xmlIntegratorOut, no [ Possible values: yes or no ] 1709 xmlIntegratorFile, auto [ Default: <OutfilePrefix>_Integrator.xml ] 1710 1711 A brief description of parameters is provided below: 1712 1713 checkpoint: Write intermediate checkpoint file. 1714 checkpointFile: Intermediate checkpoint file name. 1715 checkpointSteps: Frequency of writing intermediate checkpoint file. 1716 1717 dataOutType: Type of data to write to stdout and log file. 1718 1719 dataLog: Write data to log file. 1720 dataLogFile: Data log file name. 1721 dataLogSteps: Frequency of writing data to log file. 1722 1723 dataStdout: Write data to stdout. 1724 dataStdoutSteps: Frequency of writing data to stdout. 1725 1726 minimizationDataSteps: Frequency of writing data to stdout and log file. 1727 minimizationDataStdout: Write data to stdout. 1728 minimizationDataLog: Write data to log file. 1729 minimizationDataLogFile: Data log fie name. 1730 minimizationDataOutType: Type of data to write to stdout and log file. 1731 1732 pdbOutFormat: Format of output PDB files. 1733 pdbOutKeepIDs: Keep existing chain and residue IDs. 1734 1735 pdbOutMinimized: Write PDB file after minimization. 1736 pdbOutEquilibrated: Write PDB file after equilibration. 1737 pdbOutFinal: Write final PDB file after production run. 1738 1739 saveFinalStateCheckpoint: Save final state checkpoint file. 1740 saveFinalStateCheckpointFile: Name of final state checkpoint file. 1741 saveFinalStateXML: Save final state XML file. 1742 saveFinalStateXMLFile: Name of final state XML file. 1743 1744 traj: Write out trajectory file. 1745 trajFile: Trajectory file name. 1746 trajFormat: Trajectory file format. 1747 trajSteps: Frequency of writing trajectory file. 1748 1749 xmlSystemOut: Write system XML file. 1750 xmlSystemFile: System XML file name. 1751 xmlIntegratorOut: Write integrator XML file. 1752 xmlIntegratorFile: Integrator XML file name. 1753 1754 Arguments: 1755 ParamsOptionName (str): Command line OpenMM system option name. 1756 ParamsOptionValues (str): Space delimited list of parameter name and value pairs. 1757 ParamsDefaultInfo (dict): Default values to override for selected parameters. 1758 1759 Returns: 1760 dictionary: Processed parameter name and value pairs. 1761 1762 """ 1763 1764 ParamsInfo = {"Checkpoint": False, "CheckpointFile": "auto", "CheckpointSteps": 10000, 1765 "DataOutType": "auto", 1766 "DataLog": True, "DataLogFile": "auto", "DataLogSteps": 1000, 1767 "DataStdout": False, "DataStdoutSteps": 1000, 1768 "MinimizationDataSteps": 100, "MinimizationDataStdout": False, "MinimizationDataLog": False, "MinimizationDataLogFile": "auto", "MinimizationDataOutType": "auto", 1769 "PDBOutFormat": "PDB", "PDBOutKeepIDs": True, "PDBOutMinimized": False, "PDBOutEquilibrated": False, "PDBOutFinal": False, 1770 "SaveFinalStateCheckpoint": True, "SaveFinalStateCheckpointFile": "auto", "SaveFinalStateXML": False, "SaveFinalStateXMLFile": "auto", 1771 "Traj": True, "TrajFile": "auto", "TrajFormat": "DCD", "TrajSteps": 10000, 1772 "XmlSystemOut": False, "XmlSystemFile": "auto", "XmlIntegratorOut": False, "XmlIntegratorFile": "auto"} 1773 1774 (ValidParamNames, CanonicalParamNamesMap, ParamsOptionValue, ParamsOptionValueWords) = _ValidateAndCanonicalizeParameterNames(ParamsOptionName, ParamsOptionValue, ParamsInfo, ParamsDefaultInfo) 1775 1776 if re.match("^auto$", ParamsOptionValue, re.I): 1777 _ProcessOptionOpenMMOutputParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue, OutfilePrefix) 1778 return ParamsInfo 1779 1780 for Index in range(0, len(ParamsOptionValueWords), 2): 1781 Name = ParamsOptionValueWords[Index].strip() 1782 Value = ParamsOptionValueWords[Index + 1].strip() 1783 1784 ParamName = CanonicalParamNamesMap[Name.lower()] 1785 ParamValue = Value 1786 1787 if re.match("^(Checkpoint|DataLog|DataStdout|MinimizationDataStdout|MinimizationDataLog|PDBOutKeepIDs|SaveFinalStateCheckpoint|SaveFinalStateXML|Traj|XmlSystemOut|XmlIntegratorOut|PDBOutMinimized|PDBOutEquilibrated|PDBOutFinal)$", ParamName, re.I): 1788 if not re.match("^(yes|no|true|false)$", Value, re.I): 1789 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. Supported values: yes or no" % (Value, Name, ParamsOptionName)) 1790 ParamValue = True if re.match("^(yes|true)$", Value, re.I) else False 1791 elif re.match("^(CheckpointFile|SaveFinalStateCheckpointFile)$", ParamName, re.I): 1792 if not re.match("^auto$", Value, re.I): 1793 if not MiscUtil.CheckFileExt(Value, "chk"): 1794 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. Supported file format: chk" % (Value, Name, ParamsOptionName)) 1795 ParamValue = Value 1796 elif re.match("^(DataLogFile|MinimizationDataLogFile)$", ParamName, re.I): 1797 if not re.match("^auto$", Value, re.I): 1798 if not MiscUtil.CheckFileExt(Value, "csv"): 1799 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. Supported file formats: csv" % (Value, Name, ParamsOptionName)) 1800 ParamValue = Value 1801 elif re.match("^(SaveFinalStateXMLFile|XmlSystemFile|XmlIntegratorFile)$", ParamName, re.I): 1802 if not re.match("^auto$", Value, re.I): 1803 if not MiscUtil.CheckFileExt(Value, "xml"): 1804 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. Supported file format: xml" % (Value, Name, ParamsOptionName)) 1805 ParamValue = Value 1806 elif re.match("^TrajFile$", ParamName, re.I): 1807 if not re.match("^auto$", Value, re.I): 1808 if not MiscUtil.CheckFileExt(Value, "dcd xtc"): 1809 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. Supported file formats: dcd xtc" % (Value, Name, ParamsOptionName)) 1810 ParamValue = Value 1811 elif re.match("^(CheckpointSteps|DataLogSteps|DataStdoutSteps|MinimizationDataSteps|TrajSteps)$", ParamName, re.I): 1812 if not MiscUtil.IsInteger(Value): 1813 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option must be an integer.\n" % (Value, ParamName, ParamsOptionName)) 1814 Value = int(Value) 1815 if Value <= 0: 1816 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. Supported values: > 0\n" % (ParamValue, ParamName, ParamsOptionName)) 1817 ParamValue = Value 1818 elif re.match("^DataOutType$", ParamName, re.I): 1819 if not re.match("^auto$", Value, re.I): 1820 ValueTypes = Value.split() 1821 if len(ValueTypes) == 0: 1822 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. It must contain a space delimited list of valid values.\n" % (Value, ParamName, ParamsOptionName)) 1823 ValueTypesSpecified = [] 1824 for ValueType in ValueTypes: 1825 if not re.match("^(Step|Speed|Progress|PotentialEnergy|Temperature|ElapsedTime|RemainingTime|Time|KineticEnergy|TotalEnergy|Volume|Density)$", ValueType, re.I): 1826 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. Supported values: Step, Speed, Progress, PotentialEnergy, Temperature, ElapsedTime, RemainingTime, Time, KineticEnergy, TotalEnergy, Volume, or Density" % (ValueType, Name, ParamsOptionName)) 1827 if ValueType in ValueTypesSpecified: 1828 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. It has already been specified." % (ValueType, Name, ParamsOptionName)) 1829 ValueTypesSpecified.append(ValueType) 1830 ParamsInfo["DataOutTypeList"] = ValueTypes 1831 elif re.match("^MinimizationDataOutType$", ParamName, re.I): 1832 if not re.match("^auto$", Value, re.I): 1833 ValueTypes = Value.split() 1834 if len(ValueTypes) == 0: 1835 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. It must contain a space delimited list of valid values.\n" % (Value, ParamName, ParamsOptionName)) 1836 ValueTypesSpecified = [] 1837 for ValueType in ValueTypes: 1838 if not re.match("^(SystemEnergy|RestraintEnergy|RestraintStrength|MaxConstraintError)$", ValueType, re.I): 1839 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. Supported values: SystemEnergy, RestraintEnergy, RestraintStrength, or MaxConstraintError" % (ValueType, Name, ParamsOptionName)) 1840 if ValueType in ValueTypesSpecified: 1841 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. It has already been specified." % (ValueType, Name, ParamsOptionName)) 1842 ValueTypesSpecified.append(ValueType) 1843 ParamsInfo["MinimizationDataOutTypeList"] = ValueTypes 1844 elif re.match("^PDBOutFormat$", ParamName, re.I): 1845 if not re.match("^(PDB|CIF)$", Value, re.I): 1846 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. Supported values: PDB or CIF" % (Value, Name, ParamsOptionName)) 1847 ParamValue = Value 1848 elif re.match("^TrajFormat$", ParamName, re.I): 1849 if not re.match("^(DCD|XTC)$", Value, re.I): 1850 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. Supported values: DCD or XTC" % (Value, Name, ParamsOptionName)) 1851 ParamValue = Value 1852 else: 1853 ParamValue = Value 1854 1855 # Set value... 1856 ParamsInfo[ParamName] = ParamValue 1857 1858 # Handle parameters with possible auto values... 1859 _ProcessOptionOpenMMOutputParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue, OutfilePrefix) 1860 1861 return ParamsInfo 1862 1863 def _ProcessOptionOpenMMOutputParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue, OutfilePrefix): 1864 """Process parameters with possible auto values and perform validation. 1865 """ 1866 1867 # Use comma as a delimiter... 1868 ParamsInfo["DataOutDelimiter"] = "," 1869 ParamsInfo["DataOutfileExt"] = "csv" 1870 1871 ParamName = "TrajFormat" 1872 ParamValue = ParamsInfo[ParamName] 1873 if re.match("^DCD$", ParamValue, re.I): 1874 TrajFileExt = "dcd" 1875 elif re.match("^XTC$", ParamValue, re.I): 1876 TrajFileExt = "xtc" 1877 else: 1878 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. Supported values: DCD or XTC" % (ParamValue, ParamName, ParamsOptionName)) 1879 ParamsInfo["TrajFileExt"] = TrajFileExt 1880 1881 ParamName = "PDBOutFormat" 1882 ParamValue = ParamsInfo[ParamName] 1883 if re.match("^PDB$", ParamValue, re.I): 1884 PDBOutfileExt = "pdb" 1885 elif re.match("^CIF$", ParamValue, re.I): 1886 PDBOutfileExt = "cif" 1887 else: 1888 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. Supported values: PDB or CIF" % (ParamValue, ParamName, ParamsOptionName)) 1889 ParamsInfo["PDBOutfileExt"] = PDBOutfileExt 1890 1891 _ProcessFileNamesOutputPatramaters(ParamsInfo, ParamsOptionName, ParamsOptionValue, OutfilePrefix) 1892 _ProcessDataOutTypeOutputParameter(ParamsInfo, ParamsOptionName, ParamsOptionValue, OutfilePrefix) 1893 _ProcessMinimizationDataOutTypeOutputParameter(ParamsInfo, ParamsOptionName, ParamsOptionValue, OutfilePrefix) 1894 1895 def _ProcessFileNamesOutputPatramaters(ParamsInfo, ParamsOptionName, ParamsOptionValue, OutfilePrefix): 1896 """Process output parameters corresponding to file names.""" 1897 1898 OutfileExt = ParamsInfo["DataOutfileExt"] 1899 TrajFileExt = ParamsInfo["TrajFileExt"] 1900 OutfilesSuffixAndExtMap = {"CheckpointFile": ["", "chk"], "DataLogFile": ["", OutfileExt], "MinimizationDataLogFile": ["Minimization", OutfileExt], "SaveFinalStateCheckpointFile": ["FinalState", "chk"], "SaveFinalStateXMLFile": ["FinalState", "xml"], "TrajFile": ["", TrajFileExt], "XmlSystemFile": ["System", "xml"], "XmlIntegratorFile": ["Integrator", "xml"]} 1901 OutfileNames = [] 1902 for ParamName in OutfilesSuffixAndExtMap: 1903 ParamValue = ParamsInfo[ParamName] 1904 if re.match("^auto$", ParamValue, re.I): 1905 DataOutfileSuffix, DataOutfileExt = OutfilesSuffixAndExtMap[ParamName] 1906 if len(DataOutfileSuffix): 1907 DataOutfileSuffix = "_%s" % DataOutfileSuffix 1908 ParamValue = "%s%s.%s" % (OutfilePrefix, DataOutfileSuffix, DataOutfileExt) 1909 ParamsInfo[ParamName] = ParamValue 1910 else: 1911 # Check for duplicate output file names... 1912 if ParamValue not in OutfileNames: 1913 OutfileNames.append(ParamValue) 1914 else: 1915 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. It's a duplicate file name." % (ParamValue, ParamName, ParamsOptionName)) 1916 1917 # Validate specified traj file extension... 1918 if re.match("^TrajFile$", ParamName, re.I): 1919 TrajFormat = ParamsInfo["TrajFormat"] 1920 if not MiscUtil.CheckFileExt(ParamValue, TrajFileExt): 1921 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. The file extension must match must match the extenstion, %s, corresponding to trajectory format, %s, speecified using \"--trajFormat\" option." % (ParamValue, ParamName, ParamsOptionName, TrajFileExt, TrajFormat)) 1922 1923 def _ProcessDataOutTypeOutputParameter(ParamsInfo, ParamsOptionName, ParamsOptionValue, OutfilePrefix): 1924 """Process output parameter corresponding to data out type.""" 1925 1926 # Setup data out types... 1927 DataOutTypeStatusMap = {"Step": False, "Speed": False, "Progress": False, "PotentialEnergy": False, "Temperature": False, "ElapsedTime": False, "RemainingTime": False, "Time": False, "KineticEnergy": False, "TotalEnergy": False, "Volume": False, "Density": False} 1928 CanonicalDataOutTypeMap = {} 1929 ValidDataOutTypes = [] 1930 for DataOutType in DataOutTypeStatusMap: 1931 ValidDataOutTypes.append(DataOutType) 1932 CanonicalDataOutTypeMap[DataOutType.lower()] = DataOutType 1933 1934 # Process data out types... 1935 ParamName = "DataOutType" 1936 ParamValue = ParamsInfo[ParamName] 1937 DataOutTypeList = [] 1938 if re.match("^auto$", ParamValue, re.I): 1939 DataOutTypeList = ["Step", "Speed", "Progress", "PotentialEnergy", "Temperature"] 1940 else: 1941 if "DataOutTypeList" in ParamsInfo: 1942 DataOutTypeList = ParamsInfo["DataOutTypeList"] 1943 else: 1944 DataOutTypeList = ParamsInfo["DataOutType"].split() 1945 ParamsInfo["DataOutTypeList"] = DataOutTypeList 1946 1947 for DataOutType in DataOutTypeList: 1948 CanonicalDataOutType = DataOutType.lower() 1949 if CanonicalDataOutType not in CanonicalDataOutTypeMap: 1950 MiscUtil.PrintError("The parameter value, %s specified for paramaer name, %s, specified using \"%s\" is not a valid name. Supported parameter names: %s" % (DataOutType, ParamName, ParamsOptionName, " ".join(ValidDataOutTypes))) 1951 1952 DataOutType = CanonicalDataOutTypeMap[CanonicalDataOutType] 1953 DataOutTypeStatusMap[DataOutType] = True 1954 1955 ParamsInfo["DataOutTypeList"] = DataOutTypeList 1956 ParamsInfo["DataOutTypeStatusMap"] = DataOutTypeStatusMap 1957 1958 def _ProcessMinimizationDataOutTypeOutputParameter(ParamsInfo, ParamsOptionName, ParamsOptionValue, OutfilePrefix): 1959 """Process output parameter corresponding to minimization data out type.""" 1960 1961 # Setup mimimization data out types... 1962 DataOutTypeOpenMMNameMap = {"SystemEnergy": "system energy", "RestraintEnergy": "restraint energy", "RestraintStrength": "restraint strength", "MaxConstraintError": "max constraint error"} 1963 1964 CanonicalDataOutTypeMap = {} 1965 ValidDataOutTypes = [] 1966 for DataOutType in DataOutTypeOpenMMNameMap: 1967 ValidDataOutTypes.append(DataOutType) 1968 CanonicalDataOutTypeMap[DataOutType.lower()] = DataOutType 1969 1970 # Process minimization data out types... 1971 ParamName = "MinimizationDataOutType" 1972 ParamValue = ParamsInfo[ParamName] 1973 DataOutTypeList = [] 1974 if re.match("^auto$", ParamValue, re.I): 1975 DataOutTypeList = ["SystemEnergy", "RestraintEnergy", "MaxConstraintError"] 1976 else: 1977 if "MinimizationDataOutTypeList" in ParamsInfo: 1978 DataOutTypeList = ParamsInfo["MinimizationDataOutTypeList"] 1979 else: 1980 DataOutTypeList = ParamsInfo["MinimizationDataOutType"].split() 1981 ParamsInfo["MinimizationDataOutTypeList"] = DataOutTypeList 1982 1983 # Set up a list containing OpenMM names for minimization reporter... 1984 DataOutTypeOpenMMNameList = [] 1985 for DataOutType in DataOutTypeList: 1986 CanonicalDataOutType = DataOutType.lower() 1987 if CanonicalDataOutType not in CanonicalDataOutTypeMap: 1988 MiscUtil.PrintError("The parameter value, %s specified for paramaer name, %s, specified using \"%s\" is not a valid name. Supported parameter names: %s" % (DataOutType, ParamName, ParamsOptionName, " ".join(ValidDataOutTypes))) 1989 1990 DataOutType = CanonicalDataOutTypeMap[CanonicalDataOutType] 1991 1992 DataOutTypeOpenMMName = DataOutTypeOpenMMNameMap[DataOutType] 1993 DataOutTypeOpenMMNameList.append(DataOutTypeOpenMMName) 1994 1995 ParamsInfo["MinimizationDataOutTypeList"] = DataOutTypeList 1996 ParamsInfo["MinimizationDataOutTypeOpenMMNameList"] = DataOutTypeOpenMMNameList 1997 1998 def ProcessOptionOpenMMAtomsSelectionParameters(ParamsOptionName, ParamsOptionValue, ParamsDefaultInfo = None): 1999 """Process parameters for selecting atoms and return a map containing 2000 processed parameter names and values. 2001 2002 ParamsOptionValue is a comma delimited list of parameter name and value pairs 2003 to select atoms. 2004 2005 The supported parameter names along with their default and possible 2006 values are shown below: 2007 2008 selection, none [ Possible values: CAlphaProtein, Ions, Ligand, 2009 Protein, Residues, or Water ] 2010 selectionSpec, auto [ Possible values: A space delimited list of 2011 residue names ] 2012 negate, no [ Possible values: yes or no ] 2013 2014 A brief description of parameters is provided below: 2015 2016 selection: Atom selection to freeze. 2017 2018 selectionSpec: A space delimited list of residue names for selecting atoms. 2019 You must specify its value during 'Ligand' and 'Protein' value for 'selection'. 2020 The default values are automatically set for 'CAlphaProtein', 'Ions', 'Protein', 2021 and 'Water' values of 'selection' as shown below: 2022 2023 CAlphaProtein: List of stadard protein residues from pdbfixer 2024 for selecting CAlpha atoms. 2025 Ions: Li Na K Rb Cs Cl Br F I 2026 Water: HOH 2027 Protein: List of standard protein residues from pdbfixer. 2028 2029 negate: Negate atom selection match to select atoms for freezing. 2030 2031 In addition, you may specify an explicit space delimited list of residue 2032 names using 'selectionSpec' for any 'selection". The specified residue 2033 names are appended to the appropriate default values during the 2034 selection of atoms for freezing. 2035 2036 Arguments: 2037 ParamsOptionName (str): Command line OpenMM selection option name. 2038 ParamsOptionValues (str): Space delimited list of parameter name and value pairs. 2039 ParamsDefaultInfo (dict): Default values to override for selected parameters. 2040 2041 Returns: 2042 dictionary: Processed parameter name and value pairs. 2043 2044 """ 2045 2046 ParamsInfo = {"Selection": None, "SelectionSpec": "auto", "Negate": False} 2047 2048 if ParamsOptionValue is None: 2049 return ParamsInfo 2050 2051 (ValidParamNames, CanonicalParamNamesMap, ParamsOptionValue, ParamsOptionValueWords) = _ValidateAndCanonicalizeParameterNames(ParamsOptionName, ParamsOptionValue, ParamsInfo, ParamsDefaultInfo) 2052 2053 if re.match("^auto$", ParamsOptionValue, re.I): 2054 _ProcessOptionOpenMMAtomsSelectionParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue) 2055 return ParamsInfo 2056 2057 for Index in range(0, len(ParamsOptionValueWords), 2): 2058 Name = ParamsOptionValueWords[Index].strip() 2059 Value = ParamsOptionValueWords[Index + 1].strip() 2060 2061 ParamName = CanonicalParamNamesMap[Name.lower()] 2062 ParamValue = Value 2063 2064 # Set value... 2065 ParamsInfo[ParamName] = ParamValue 2066 if re.match("^Selection$", ParamName, re.I): 2067 if not re.match("^(CAlphaProtein|Ions|Ligand|Protein|Residues|Water)$", Value, re.I): 2068 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. Supported values: CAlphaProtein, Ions, Ligand, Protein, Residues, or Water" % (Value, Name, ParamsOptionName)) 2069 ParamValue = Value 2070 elif re.match("^SelectionSpec$", ParamName, re.I): 2071 if not re.match("^(auto|none)$", Value, re.I): 2072 Values = Value.split() 2073 if len(Values) == 0: 2074 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. It must contain space delimited list of residue names.\n" % (Value, ParamName, ParamsOptionName)) 2075 # Set residues list... 2076 ParamsInfo["SelectionSpecList"] = Values 2077 elif re.match("^Negate$", ParamName, re.I): 2078 if not re.match("^(yes|no|true|false)$", Value, re.I): 2079 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. Supported values: yes or no" % (Value, Name, ParamsOptionName)) 2080 ParamValue = True if re.match("^(yes|true)$", Value, re.I) else False 2081 else: 2082 ParamValue = Value 2083 2084 # Set value... 2085 ParamsInfo[ParamName] = ParamValue 2086 2087 # Handle parameters with possible auto values... 2088 _ProcessOptionOpenMMAtomsSelectionParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue) 2089 2090 return ParamsInfo 2091 2092 def _ProcessOptionOpenMMAtomsSelectionParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue): 2093 """Process parameters with possible auto values and perform validation. 2094 """ 2095 2096 SelectionParamName = "Selection" 2097 SelectionParamValue = ParamsInfo[SelectionParamName] 2098 2099 SelectionSpecParamName = "SelectionSpec" 2100 SelectionSpecParamValue = ParamsInfo[SelectionSpecParamName] 2101 2102 SelectionSpecList = None if re.match("^(auto|none)$", SelectionSpecParamValue, re.I) else ParamsInfo["SelectionSpecList"] 2103 2104 ResidueNames = None 2105 if re.match("^(CAlphaProtein|Protein)$", SelectionParamValue, re.I): 2106 ResidueNames = pdbfixer.pdbfixer.proteinResidues 2107 if SelectionSpecList is not None: 2108 ResidueNames.extend(SelectionSpecList) 2109 elif re.match("^Ions$", SelectionParamValue, re.I): 2110 ResidueNames = ["Li", "Na", "K", "Rb", "Cs", "Cl", "Br", "F", "I"] 2111 if SelectionSpecList is not None: 2112 ResidueNames.extend(SelectionSpecList) 2113 elif re.match("^Ligand$", SelectionParamValue, re.I): 2114 if SelectionSpecList is None: 2115 MiscUtil.PrintError("No value specified for parameter name, %s, using \"%s\" option is not a valid value. It must contain a ligand residue name.\n" % (SelectionSpecParamName, ParamsOptionName)) 2116 elif len(SelectionSpecList) != 1: 2117 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. It must contain a single ligand residue name.\n" % (SelectionSpecParamValue, SelectionSpecParamName, ParamsOptionName)) 2118 ResidueNames = SelectionSpecList 2119 elif re.match("^Residues$", SelectionParamValue, re.I): 2120 if SelectionSpecList is None: 2121 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. It must contain a space delimited list of residue names.\n" % (SelectionSpecParamValue, SelectionSpecParamName, ParamsOptionName)) 2122 ResidueNames = SelectionSpecList 2123 elif re.match("^Water$", SelectionParamValue, re.I): 2124 ResidueNames = ["HOH"] 2125 if SelectionSpecList is not None: 2126 ResidueNames.extend(SelectionSpecList) 2127 2128 ParamsInfo["ResidueNames"] = [ResidueName.upper() for ResidueName in ResidueNames] 2129 ParamsInfo["CAlphaProteinStatus"] = True if re.match("^CAlphaProtein$", SelectionParamValue, re.I) else False 2130 2131 def ProcessOptionOpenMMForcefieldParameters(ParamsOptionName, ParamsOptionValue, ParamsDefaultInfo = None): 2132 """Process parameters for biopolymer, small molecule, and water forcefields and 2133 return a map containing processed parameter names and values. 2134 2135 ParamsOptionValue is a comma delimited list of parameter name and value pairs 2136 for forcefields. 2137 2138 The supported parameter names along with their default and possible 2139 values are shown below: 2140 2141 biopolymer, amber14-all.xml [ Possible values: Any Valid value ] 2142 smallMolecule, OpenFF_2.2.0 [ Possible values: Any Valid value ] 2143 water, auto [ Possible values: Any Valid value ] 2144 2145 Possible biopolymer forcefield values: 2146 2147 amber14-all.xml, amber99sb.xml, amber99sbildn.xml, amber03.xml, 2148 amber10.xml 2149 charmm36.xml, charmm_polar_2019.xml 2150 amoeba2018.xml 2151 2152 Possible small molecule forcefield values: 2153 2154 openff_2.2.0, openff_2.0.0, openff_1.3.1, openff_1.2.1, openff_1.1.1, 2155 smirnoff99frosst 2156 gaff-2.11, gaff-2.1, gaff-1.81, gaff-1.8, gaff-1.4 2157 2158 The default water forcefield valus is dependent on the type of the 2159 biopolymer forcefield as shown below: 2160 2161 Amber: amber14/tip3pfb.xml 2162 CHARMM: charmm36/water.xml or None for charmm_polar_2019.xml 2163 Amoeba: None (Explicit) 2164 2165 Possible water forcefield values: 2166 2167 amber14/tip3p.xml, amber14/tip3pfb.xml, amber14/spce.xml, 2168 amber14/tip4pew.xml, amber14/tip4pfb.xml, 2169 implicit/obc2.xml, implicit/GBn.xml, implicit/GBn2.xml 2170 charmm36/water.xml, charmm36/tip3p-pme-b.xml, 2171 charmm36/tip3p-pme-f.xml, charmm36/spce.xml, 2172 charmm36/tip4pew.xml, charmm36/tip4p2005.xml, 2173 charmm36/tip5p.xml, charmm36/tip5pew.xml, 2174 implicit/obc2.xml, implicit/GBn.xml, implicit/GBn2.xml 2175 amoeba2018_gk.xml (Implict water), None (Explicit water for amoeba) 2176 2177 You may specify any valid forcefield name supported by OpenMM. No 2178 explicit validation is performed. 2179 2180 Arguments: 2181 ParamsOptionName (str): Command line OpenMM forcefield option name. 2182 ParamsOptionValues (str): Space delimited list of parameter name and value pairs. 2183 ParamsDefaultInfo (dict): Default values to override for selected parameters. 2184 2185 Returns: 2186 dictionary: Processed parameter name and value pairs. 2187 2188 """ 2189 2190 ParamsInfo = {"Biopolymer": "amber14-all.xml", "SmallMolecule": "openff-2.2.1", "Water": "auto", "Additional" : "None"} 2191 2192 (ValidParamNames, CanonicalParamNamesMap, ParamsOptionValue, ParamsOptionValueWords) = _ValidateAndCanonicalizeParameterNames(ParamsOptionName, ParamsOptionValue, ParamsInfo, ParamsDefaultInfo) 2193 2194 if re.match("^auto$", ParamsOptionValue, re.I): 2195 _ProcessOptionOpenMMForcefieldParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue) 2196 return ParamsInfo 2197 2198 for Index in range(0, len(ParamsOptionValueWords), 2): 2199 Name = ParamsOptionValueWords[Index].strip() 2200 Value = ParamsOptionValueWords[Index + 1].strip() 2201 2202 ParamName = CanonicalParamNamesMap[Name.lower()] 2203 ParamValue = Value 2204 2205 # Set value... 2206 ParamsInfo[ParamName] = ParamValue 2207 2208 # Handle parameters with possible auto values... 2209 _ProcessOptionOpenMMForcefieldParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue) 2210 2211 return ParamsInfo 2212 2213 def _ProcessOptionOpenMMForcefieldParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue): 2214 """Process parameters with possible auto values and perform validation. 2215 """ 2216 WaterForcefield = ParamsInfo["Water"] 2217 if re.match("^None$", WaterForcefield, re.I): 2218 WaterForcefield = None 2219 ParamsInfo["Water"] = WaterForcefield 2220 elif re.match("^auto$", WaterForcefield, re.I): 2221 BiopolymerForcefield = ParamsInfo["Biopolymer"] 2222 if re.search("amber", BiopolymerForcefield, re.I): 2223 WaterForcefield = "amber14/tip3pfb.xml" 2224 elif re.search("charmm", BiopolymerForcefield, re.I): 2225 if re.search("charmm_polar_2019", BiopolymerForcefield, re.I): 2226 WaterForcefield = None 2227 else: 2228 WaterForcefield = "charmm36/water.xml" 2229 elif re.search("amoeba", BiopolymerForcefield, re.I): 2230 # Explicit water... 2231 WaterForcefield = None 2232 else: 2233 WaterForcefield = None 2234 ParamsInfo["Water"] = WaterForcefield 2235 2236 # Set status of implicit water forcefield... 2237 BiopolymerForcefield = ParamsInfo["Biopolymer"] 2238 ParamsInfo["ImplicitWater"] = True if _IsImplicitWaterForcefield(BiopolymerForcefield, WaterForcefield) else False 2239 2240 # Process additional forcefields... 2241 ParamName = "Additional" 2242 ParamValue = ParamsInfo[ParamName] 2243 ParamValuesList = None 2244 if not re.match("^None$", ParamValue, re.I): 2245 ParamValuesList = ParamValue.split() 2246 if len(ParamValuesList) == 0: 2247 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. It must contain a space delimited list of valid values.\n" % (ParamValue, ParamName, ParamsOptionName)) 2248 ParamsInfo["AdditionalList"] = ParamValuesList 2249 2250 def _IsImplicitWaterForcefield(BiopolymerForcefield, WaterForcefield): 2251 """Check the nature of the water forcefield.""" 2252 2253 Status = False 2254 if WaterForcefield is None: 2255 if re.search("charmm_polar_2019", BiopolymerForcefield, re.I): 2256 Status = True 2257 else: 2258 Status = False 2259 else: 2260 if re.search("amber", BiopolymerForcefield, re.I): 2261 if re.search("implicit", WaterForcefield, re.I): 2262 Status = True 2263 elif re.search("charmm", BiopolymerForcefield, re.I): 2264 if re.search("implicit", WaterForcefield, re.I): 2265 Status = True 2266 elif re.search("amoeba", BiopolymerForcefield, re.I): 2267 Status = True 2268 2269 return Status 2270 2271 def ProcessOptionOpenMMPlatformParameters(ParamsOptionName, ParamsOptionValue, ParamsDefaultInfo = None): 2272 """Process parameters for platform option and return a map containing processed 2273 parameter names and values. 2274 2275 ParamsOptionValue is a comma delimited list of parameter name and value pairs 2276 to setup platform. 2277 2278 The supported parameter names along with their default values for 2279 different platforms are shown below: 2280 2281 CPU: 2282 2283 threads, 1 [ Possible value: >= 0 or auto. The value of 'auto' 2284 or zero implies the use of all available CPUs for threading. ] 2285 2286 CUDA: 2287 2288 deviceIndex, auto [ Possible values: 0, '0 1' etc. ] 2289 deterministicForces, auto [ Possible values: yes or no ] 2290 precision, single [ Possible values: single, double, or mix ] 2291 tempDirectory, auto [ Possible value: DirName ] 2292 useBlockingSync, auto [ Possible values: yes or no ] 2293 useCpuPme, auto [ Possible values: yes or no ] 2294 2295 OpenCL: 2296 2297 deviceIndex, auto [ Possible values: 0, '0 1' etc. ] 2298 openCLPlatformIndex, auto [ Possible value: Number] 2299 precision, single [ Possible values: single, double, or mix ] 2300 useCpuPme, auto [ Possible values: yes or no ] 2301 2302 A brief description of parameters is provided below: 2303 2304 CPU: 2305 2306 threads: Number of threads to use for simulation. 2307 2308 CUDA: 2309 2310 deviceIndex: Space delimited list of device indices to use for 2311 calculations. 2312 deterministicForces: Generate reproducible results at the cost of a 2313 small decrease in performance. 2314 precision: Number precision to use for calculations. 2315 tempDirectory: Directory name for storing temporary files. 2316 useBlockingSync: Control run-time synchronization between CPU and 2317 GPU. 2318 useCpuPme: Use CPU-based PME implementation. 2319 2320 OpenCL: 2321 2322 deviceIndex: Space delimited list of device indices to use for 2323 simulation. 2324 openCLPlatformIndex: Platform index to use for calculations. 2325 precision: Number precision to use for calculations. 2326 useCpuPme: Use CPU-based PME implementation. 2327 2328 Arguments: 2329 ParamsOptionName (str): Command line OpenMM platform option name. 2330 ParamsOptionValues (str): Space delimited list of parameter name and value pairs. 2331 ParamsDefaultInfo (dict): Default values to override for selected parameters. 2332 2333 Returns: 2334 dictionary: Processed parameter name and value pairs. 2335 2336 """ 2337 2338 ParamsInfo = {"Name": "CPU", "Threads": "auto", "DeviceIndex": "auto", "DeterministicForces": "auto", "Precision": "single", "TempDirectory": "auto", "UseBlockingSync": "auto", "UseCpuPme": "auto", "OpenCLPlatformIndex": "auto"} 2339 2340 (ValidParamNames, CanonicalParamNamesMap, ParamsOptionValue, ParamsOptionValueWords) = _ValidateAndCanonicalizeParameterNames(ParamsOptionName, ParamsOptionValue, ParamsInfo, ParamsDefaultInfo) 2341 2342 if re.match("^auto$", ParamsOptionValue, re.I): 2343 _ProcessOptionOpenMMPlatformParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue) 2344 return ParamsInfo 2345 2346 for Index in range(0, len(ParamsOptionValueWords), 2): 2347 Name = ParamsOptionValueWords[Index].strip() 2348 Value = ParamsOptionValueWords[Index + 1].strip() 2349 2350 ParamName = CanonicalParamNamesMap[Name.lower()] 2351 ParamValue = Value 2352 2353 if re.match("^Name$", ParamName, re.I): 2354 if not re.match("^(CPU|CUDA|OpenCL|Reference)$", Value, re.I): 2355 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. Supported values: CPU, GPU, OpenCL, or Reference" % (Value, Name, ParamsOptionName)) 2356 ParamValue = Value 2357 elif re.match("^Threads$", ParamName, re.I): 2358 if not re.match("^auto$", Value, re.I): 2359 if not MiscUtil.IsInteger(Value): 2360 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option must be an integer.\n" % (Value, ParamName, ParamsOptionName)) 2361 Value = int(Value) 2362 if Value < 0: 2363 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. Supported values: >=0 \n" % (ParamValue, ParamName, ParamsOptionName)) 2364 if Value > mp.cpu_count(): 2365 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is greater than number of CPUs, %s, returned by mp.cpu_count().\n" % (ParamValue, ParamName, ParamsOptionName, mp.cpu_count())) 2366 ParamValue = "%s" % Value 2367 elif re.match("^Precision$", ParamName, re.I): 2368 if not re.match("^(Single|Double|Mix)$", Value, re.I): 2369 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. Supported values: single, double or mix" % (Value, Name, ParamsOptionName)) 2370 ParamValue = Value.lower() 2371 elif re.match("^(DeterministicForces|UseBlockingSync|UseCpuPme)$", ParamName, re.I): 2372 if not re.match("^auto$", Value, re.I): 2373 if not re.match("^(yes|no|true|false)$", Value, re.I): 2374 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. Supported values: yes or no" % (Value, Name, ParamsOptionName)) 2375 ParamValue = "true" if re.match("^(yes|true)$", Value, re.I) else "false" 2376 elif re.match("^(DeviceIndex|openCLPlatformIndex)$", ParamName, re.I): 2377 if not re.match("^auto$", Value, re.I): 2378 DeviceIndices = Value.split() 2379 if len(DeviceIndices) == 0: 2380 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. It must contain space delimited list of device indices.\n" % (Value, ParamName, ParamsOptionName)) 2381 for DeviceIndex in DeviceIndices: 2382 if not MiscUtil.IsInteger(DeviceIndex): 2383 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option must be an integer.\n" % (DeviceIndex, ParamName, ParamsOptionName)) 2384 ParamValue = ",".join(DeviceIndices) 2385 elif re.match("^TempDirectory$", ParamName, re.I): 2386 if not re.match("^auto$", Value, re.I): 2387 if not os.path.isdir(Value): 2388 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. The specified directory doesn't exists." % (Value, Name, ParamsOptionName)) 2389 ParamValue = Value 2390 else: 2391 ParamValue = Value 2392 2393 # Set value... 2394 ParamsInfo[ParamName] = ParamValue 2395 2396 # Handle parameters with possible auto values... 2397 _ProcessOptionOpenMMPlatformParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue) 2398 2399 return ParamsInfo 2400 2401 def _ProcessOptionOpenMMPlatformParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue): 2402 """Process parameters with possible auto values and perform validation. 2403 """ 2404 2405 ParamValueMap = {"cpu": "CPU", "cuda": "CUDA", "opencl": "OpenCL", "reference": "Reference"} 2406 ParamName = "Name" 2407 ParamValue = ParamsInfo[ParamName].lower() 2408 if ParamValue in ParamValueMap: 2409 ParamsInfo[ParamName] = ParamValueMap[ParamValue] 2410 2411 ParamsInfo["Precision"] = ParamsInfo["Precision"].lower() 2412 2413 # Set "auto" values to None and treat all other values as strings... 2414 for ParamName in ParamsInfo: 2415 ParamValue = "%s" % ParamsInfo[ParamName] 2416 if re.match("^auto$", ParamValue, re.I): 2417 ParamsInfo[ParamName] = None 2418 else: 2419 ParamsInfo[ParamName] = ParamValue 2420 2421 def ProcessOptionOpenMMWaterBoxParameters(ParamsOptionName, ParamsOptionValue, ParamsDefaultInfo = None): 2422 """Process parameters for adding a water box option and return a map containing 2423 processed parameter names and values. 2424 2425 ParamsOptionValue is a comma delimited list of parameter name and value pairs 2426 for adding a water box. 2427 2428 The supported parameter names along with their default and possible 2429 values are shown below: 2430 2431 model, tip3p [ Possible values: tip3p, spce, tip4pew, tip5p or swm4ndp ] 2432 mode, Padding [ Possible values: Size or Padding ] 2433 size, None [ Possible values: xsize ysize zsize ] 2434 padding, 1.0 2435 shape, cube [ Possible values: cube, dodecahedron, or octahedron ] 2436 ionPositive, Na+ [ Possible values: Li+, Na+, K+, Rb+, or Cs+ ] 2437 ionNegative, Cl- [ Possible values: Cl-, Br-, F-, or I- ] 2438 ionicStrength, 0.0 2439 2440 A brief description of parameters is provided below: 2441 2442 model: Water model to use for adding water box. 2443 2444 mode: Specify the size of the waterbox explicitly or calculate it automatically 2445 for a macromolecule along with adding padding around macromolecule. 2446 Possible values: Size or Padding. 2447 2448 size: A space delimited triplet of values corresponding to water size in 2449 nanometers. It must be specified during 'Size' value of 'mode' parameter. 2450 2451 padding: Padding around macromolecule in nanometers for filling box with 2452 water. It must be specified during 'Padding' value of 'mode' parameter. 2453 2454 ionPositive: Type of positive ion to add during the addition of a water box. 2455 2456 ionNegative: Type of negative ion to add during the addition of a water box. 2457 2458 ionicStrength: Total concentration (molar) of both positive and negative ions 2459 to add excluding he ions added to neutralize the system during the addition 2460 of a water box. 2461 2462 Arguments: 2463 ParamsOptionName (str): Command line OpenMM water box option name. 2464 ParamsOptionValues (str): Space delimited list of parameter name and value pairs. 2465 ParamsDefaultInfo (dict): Default values to override for selected parameters. 2466 2467 Returns: 2468 dictionary: Processed parameter name and value pairs. 2469 2470 """ 2471 2472 ParamsInfo = {"Model": "tip3p", "Mode": "Padding", "Size": None, "Padding": 1.0, "Shape": "cube", "IonPositive": "Na+", "IonNegative": "Cl-", "IonicStrength": 0.0} 2473 2474 (ValidParamNames, CanonicalParamNamesMap, ParamsOptionValue, ParamsOptionValueWords) = _ValidateAndCanonicalizeParameterNames(ParamsOptionName, ParamsOptionValue, ParamsInfo, ParamsDefaultInfo) 2475 2476 if re.match("^auto$", ParamsOptionValue, re.I): 2477 _ProcessOptionOpenMMWaterBoxParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue) 2478 return ParamsInfo 2479 2480 for Index in range(0, len(ParamsOptionValueWords), 2): 2481 Name = ParamsOptionValueWords[Index].strip() 2482 Value = ParamsOptionValueWords[Index + 1].strip() 2483 2484 ParamName = CanonicalParamNamesMap[Name.lower()] 2485 ParamValue = Value 2486 2487 if re.match("^Model$", ParamName, re.I): 2488 if not re.match("^(tip3p|spce|tip4pew|tip5p|swm4ndp)$", Value, re.I): 2489 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. Supported values: tip3p, spce, tip4pew, tip5p, or swm4ndp" % (Value, Name, ParamsOptionName)) 2490 ParamValue = Value.lower() 2491 elif re.match("^Mode$", ParamName, re.I): 2492 if not re.match("^(Padding|Size)$", Value, re.I): 2493 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. Supported values: Padding or Size" % (Value, Name, ParamsOptionName)) 2494 ParamValue = Value 2495 elif re.match("^Size$", ParamName, re.I): 2496 if Value is not None and not re.match("^None$", Value, re.I): 2497 SizeValues = Value.split() 2498 if len(SizeValues) != 3: 2499 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. It must contain 3 float values separated by spaces.\n" % (Value, ParamName, ParamsOptionName)) 2500 2501 SizeValueList = [] 2502 for SizeValue in SizeValues: 2503 if not MiscUtil.IsFloat(SizeValue): 2504 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option must be a float.\n" % (SizeValue, ParamName, ParamsOptionName)) 2505 SizeValue = float(SizeValue) 2506 if SizeValue <= 0: 2507 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. Supported values: > 0\n" % (SizeValue, ParamName, ParamsOptionName)) 2508 SizeValueList.append(SizeValue) 2509 2510 # Set size values... 2511 ParamsInfo["SizeList"] = SizeValueList 2512 2513 ParamValue = Value 2514 elif re.match("^Padding$", ParamName, re.I): 2515 if not MiscUtil.IsFloat(Value): 2516 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option must be a float.\n" % (Value, ParamName, ParamsOptionName)) 2517 Value = float(Value) 2518 if Value <= 0: 2519 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. Supported values: > 0\n" % (ParamValue, ParamName, ParamsOptionName)) 2520 ParamValue = Value 2521 elif re.match("^Shape$", ParamName, re.I): 2522 if not re.match("^(cube|dodecahedron|octahedron)$", Value, re.I): 2523 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. Supported values: cube, dodecahedron, or octahedron" % (Value, Name, ParamsOptionName)) 2524 ParamValue = Value.lower() 2525 elif re.match("^IonPositive$", ParamName, re.I): 2526 ValidValues = "Li+ Na+ K+ Rb+ Cs+" 2527 EscapedValidValuesPattern = "Li\+|Na\+|K\+|Rb\+|Cs\+" 2528 if not re.match("^(%s)$" % EscapedValidValuesPattern, Value): 2529 MiscUtil.PrintError("The value specified, %s, for parameter name, %s, using \"%s\" option is not a valid. Supported value(s): %s" % (ParamValue, ParamName, ParamsOptionName, ValidValues)) 2530 ParamValue = Value 2531 elif re.match("^IonNegative$", ParamName, re.I): 2532 ValidValues = "F- Cl- Br- I-" 2533 ValidValuesPattern = "F-|Cl-|Br-|I-" 2534 if not re.match("^(%s)$" % ValidValuesPattern, Value): 2535 MiscUtil.PrintError("The value specified, %s, for parameter name, %s, using \"%s\" option is not a valid. Supported value(s): %s" % (ParamValue, ParamName, ParamsOptionName, ValidValues)) 2536 ParamValue = Value 2537 elif re.match("^IonicStrength$", ParamName, re.I): 2538 if not MiscUtil.IsFloat(Value): 2539 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option must be a float.\n" % (Value, ParamName, ParamsOptionName)) 2540 Value = float(Value) 2541 if Value < 0: 2542 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. Supported values: >= 0\n" % (ParamValue, ParamName, ParamsOptionName)) 2543 ParamValue = Value 2544 else: 2545 ParamValue = Value 2546 2547 # Set value... 2548 ParamsInfo[ParamName] = ParamValue 2549 2550 # Handle parameters with possible auto values... 2551 _ProcessOptionOpenMMWaterBoxParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue) 2552 2553 return ParamsInfo 2554 2555 def _ProcessOptionOpenMMWaterBoxParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue): 2556 """Process parameters with possible auto values and perform validation. 2557 """ 2558 2559 ParamsInfo["ModeSize"] = True if re.match("^Size$", ParamsInfo["Mode"], re.I) else False 2560 ParamsInfo["ModePadding"] = True if re.match("^Padding$", ParamsInfo["Mode"], re.I) else False 2561 2562 if ParamsInfo["ModeSize"]: 2563 ParamName = "Size" 2564 ParamValue = ParamsInfo[ParamName] 2565 if ParamValue is None: 2566 MiscUtil.PrintError("The parameter value, %s, specified for parameter name, %s, using \"%s\" option is not a valid value. Supported values: x y z\n" % (ParamValue, ParamName, ParamsOptionName)) 2567 else: 2568 ParamsInfo["SizeList"] = None 2569 2570 def _ValidateAndCanonicalizeParameterNames(ParamsOptionName, ParamsOptionValue, ParamsInfo, ParamsDefaultInfo): 2571 """Validate and canonicalize parameter names.""" 2572 2573 # Setup a canonical paramater names... 2574 ValidParamNames = [] 2575 CanonicalParamNamesMap = {} 2576 for ParamName in sorted(ParamsInfo): 2577 ValidParamNames.append(ParamName) 2578 CanonicalParamNamesMap[ParamName.lower()] = ParamName 2579 2580 # Update default values... 2581 if ParamsDefaultInfo is not None: 2582 for ParamName in ParamsDefaultInfo: 2583 if ParamName not in ParamsInfo: 2584 MiscUtil.PrintError("The default parameter name, %s, specified using \"%s\" option is not a valid name. Supported parameter names: %s" % (ParamName, ParamsDefaultInfo, " ".join(ValidParamNames))) 2585 ParamsInfo[ParamName] = ParamsDefaultInfo[ParamName] 2586 2587 ParamsOptionValue = ParamsOptionValue.strip() 2588 if not ParamsOptionValue: 2589 MiscUtil.PrintError("No valid parameter name and value pairs specified using \"%s\" option" % ParamsOptionName) 2590 2591 ParamsOptionValueWords = None 2592 if not re.match("^auto$", ParamsOptionValue, re.I): 2593 ParamsOptionValueWords = ParamsOptionValue.split(",") 2594 if len(ParamsOptionValueWords) % 2: 2595 MiscUtil.PrintError("The number of comma delimited paramater names and values, %d, specified using \"%s\" option must be an even number." % (len(ParamsOptionValueWords), ParamsOptionName)) 2596 2597 if ParamsOptionValueWords is not None: 2598 for Index in range(0, len(ParamsOptionValueWords), 2): 2599 Name = ParamsOptionValueWords[Index].strip() 2600 CanonicalName = Name.lower() 2601 if not CanonicalName in CanonicalParamNamesMap: 2602 MiscUtil.PrintError("The parameter name, %s, specified using \"%s\" is not a valid name. Supported parameter names: %s" % (Name, ParamsOptionName, " ".join(ValidParamNames))) 2603 2604 return (ValidParamNames, CanonicalParamNamesMap, ParamsOptionValue, ParamsOptionValueWords)