1 #
2 # File: OpenMMUtil.py
3 # Author: Manish Sud <msud@san.rr.com>
4 #
5 # Copyright (C) 2026 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 shutil
34 import multiprocessing as mp
35 import numpy as np
36
37 import openmm as mm
38 import openmm.app
39
40 import openmmforcefields as mmff
41 import openmmforcefields.generators
42 import openff as ff
43 import openff.toolkit
44
45 import pdbfixer
46 import mdtraj
47
48 import MiscUtil
49
50 __all__ = [
51 "AddWaterBox",
52 "DoAtomListsOverlap",
53 "DoesAtomListOverlapWithSystemConstraints",
54 "DoesSystemContainWater",
55 "FixColumNamesLineInDataLogFile",
56 "FreezeAtoms",
57 "GenerateReimagedRealignedTrajectoryFiles",
58 "GetAtoms",
59 "GetFormattedTotalSimulationTime",
60 "InitializeBarostat",
61 "InitializeIntegrator",
62 "InitializeReporters",
63 "InitializeSimulation",
64 "InitializeSystem",
65 "InitializeSystemGenerator",
66 "MapDataOutTypePlotToDataLogColumnNames",
67 "MergeSmallMoleculeWithMacromolecule",
68 "PerformAnnealing",
69 "ProcessOptionOpenMMRestartParameters",
70 "ProcessOptionOpenMMAtomsSelectionParameters",
71 "ProcessOptionOpenMMAnnealingParameters",
72 "ProcessOptionOpenMMForcefieldParameters",
73 "ProcessOptionOpenMMIntegratorParameters",
74 "ProcessOptionOpenMMMDProtocolParameters",
75 "ProcessOptionOpenMMPlatformParameters",
76 "ProcessOptionOpenMMOutputParameters",
77 "ProcessOptionOpenMMSimulationParameters",
78 "ProcessOptionOpenMMSystemParameters",
79 "ProcessOptionOpenMMWaterBoxParameters",
80 "ReadPDBFile",
81 "ReadSmallMoleculeFile",
82 "RestraintAtoms",
83 "SetupAnnealingParameters",
84 "SetupIntegratorParameters",
85 "SetupMDProtocolParameters",
86 "SetupSimulationParameters",
87 "SetupSystemGeneratorForcefieldsParameters",
88 "ValidateAndFreezeRestraintAtoms",
89 "WritePDBFile",
90 "WriteSimulationStatePDBFile",
91 ]
92
93
94 def InitializeSystem(
95 PDBFile,
96 ForcefieldParamsInfo,
97 SystemParamsInfo,
98 WaterBoxAdd=False,
99 WaterBoxParamsInfo=None,
100 SmallMolFile=None,
101 SmallMolID="LIG",
102 ):
103 """Initialize OpenMM system using specified forcefields, system and water box
104 parameters along with a small molecule file and ID.
105
106 The ForcefieldParamsInfo parameter is a dictionary of name and value pairs for
107 system parameters and may be generated by calling the function named
108 ProcessOptionOpenMMForcefieldParameters().
109
110 The SystemParamsInfo parameter is a dictionary of name and value pairs for
111 system parameters and may be generated by calling the function named
112 ProcessOptionOpenMMSystemParameters().
113
114 The WaterBoxParamsInfo parameter is a dictionary of name and value pairs for
115 system parameters and may be generated by calling the function named
116 ProcessOptionOpenMMWaterBoxParameters().
117
118 Arguments:
119 PDBFile (str): PDB file name..
120 ForcefieldParamsInfo (dict): Parameter name and value pairs.
121 SystemParamsInfo (dict): Parameter name and value pairs.
122 WaterBoxAdd (bool): Add water box.
123 WaterBoxParamsInfo (dict): Parameter name and value pairs.
124 SmallMolFile (str): Small molecule file name.
125 SmallMolID (str): Three letter small molecule ID.
126
127 Returns:
128 Object: OpenMM system object.
129 Object: OpenMM topology object.
130 Object: OpenMM positions object.
131
132 Examples:
133
134 ... ... ...
135 OptionsInfo["ForcefieldParams"] =
136 OpenMMUtil.ProcessOptionOpenMMForcefieldParameters(
137 "--forcefieldParams", Options["--forcefieldParams"])
138 ... ... ...
139 OptionsInfo["SystemParams"] =
140 OpenMMUtil.ProcessOptionOpenMMSystemParameters("--systemParams",
141 Options["--systemParams"])
142 ... ... ...
143 OptionsInfo["WaterBoxParams"] =
144 OpenMMUtil.ProcessOptionOpenMMWaterBoxParameters(
145 "--waterBoxParams", Options["--waterBoxParams"])
146 ... ... ...
147 System, Topology, Positions = OpenMMUtil.InitializeSystem(
148 OptionsInfo["Infile"], OptionsInfo["ForcefieldParams"],
149 OptionsInfo["SystemParams"], OptionsInfo["WaterBox"],
150 OptionsInfo["WaterBoxParams"], OptionsInfo["SmallMolFile"],
151 OptionsInfo["SmallMolID"])
152
153 """
154
155 # Read PDB file...
156 MiscUtil.PrintInfo("\nReading PDB file %s..." % PDBFile)
157 PDBHandle = ReadPDBFile(PDBFile)
158
159 ModellerHandle = mm.app.Modeller(PDBHandle.topology, PDBHandle.positions)
160 MiscUtil.PrintInfo(
161 "Number of residues: %s; Number of atoms: %s"
162 % (ModellerHandle.topology.getNumResidues(), ModellerHandle.topology.getNumAtoms())
163 )
164
165 # Read small molecule file...
166 SmallMols = None
167 if SmallMolFile is not None:
168 MiscUtil.PrintInfo("\nReading small molecule file %s..." % SmallMolFile)
169 SmallMol = ReadSmallMoleculeFile(SmallMolFile)
170 if SmallMol is None:
171 MiscUtil.PrintError("Failed to read small molecule file: %s" % SmallMolFile)
172 SmallMols = [SmallMol]
173
174 MiscUtil.PrintInfo("\nGenerating macromolecule and small molecule complex...")
175 MergeSmallMoleculeWithMacromolecule(ModellerHandle, SmallMol, SmallMolID)
176 MiscUtil.PrintInfo(
177 "Number of residues: %s; Number of atoms: %s"
178 % (ModellerHandle.topology.getNumResidues(), ModellerHandle.topology.getNumAtoms())
179 )
180
181 # Initialize system generator...
182 BiopolymerForcefield = ForcefieldParamsInfo["Biopolymer"]
183 SmallMoleculeForcefield = ForcefieldParamsInfo["SmallMolecule"]
184 WaterForcefield = ForcefieldParamsInfo["Water"]
185 AdditionalForcefiedsList = ForcefieldParamsInfo["AdditionalList"]
186 SystemGeneratorHandle = InitializeSystemGenerator(
187 BiopolymerForcefield,
188 SmallMoleculeForcefield,
189 WaterForcefield,
190 SystemParamsInfo,
191 SmallMols,
192 AdditionalForcefiedsList,
193 )
194
195 if WaterBoxAdd:
196 AddWaterBox(ModellerHandle, SystemGeneratorHandle, WaterBoxParamsInfo)
197 MiscUtil.PrintInfo(
198 "Number of residues: %s; Number of atoms: %s"
199 % (ModellerHandle.topology.getNumResidues(), ModellerHandle.topology.getNumAtoms())
200 )
201 else:
202 MiscUtil.PrintInfo("\nSkipping addition of a water box...")
203 if DoesSystemContainWater(ModellerHandle.topology):
204 if ForcefieldParamsInfo["ImplicitWater"]:
205 MiscUtil.PrintInfo(
206 '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.'
207 % (ForcefieldParamsInfo["Biopolymer"], ForcefieldParamsInfo["Water"])
208 )
209
210 MiscUtil.PrintInfo("\nBuilding system...")
211 SystemHandle = SystemGeneratorHandle.create_system(ModellerHandle.topology, molecules=SmallMols)
212
213 MiscUtil.PrintInfo(
214 "Periodic boundary conditions: %s" % ("Yes" if DoesSystemUsesPeriodicBoundaryConditions(SystemHandle) else "No")
215 )
216
217 return (SystemHandle, ModellerHandle.topology, ModellerHandle.positions)
218
219
220 def InitializeSystemGenerator(
221 BiopolymerForcefield,
222 SmallMoleculeForcefield,
223 WaterForcefield,
224 SystemParamsInfo,
225 SmallMols,
226 AdditionalForcefieldsList=None,
227 ):
228 """Initialize MMFF system generator using specified forcefields and system parameters
229 along with a list of molecules.
230
231 The SystemParamsInfo parameter is a dictionary of name and value pairs for
232 system parameters and may be generated by calling the function named
233 ProcessOptionOpenMMSystemParameters().
234
235 Arguments:
236 BiopolymerForcefield (str): Biopolymer force field name.
237 SmallMoleculeForcefield (str): Small molecule force field name.
238 WaterForcefield (str): Water force field name.
239 SystemParamsInfo (dict): Parameter name and value pairs.
240 SmallMols (list): List of OpenFF toolkit molecule objects.
241 AdditionalForcefieldsList (list): List of any additional forcefield
242 names
243
244 Returns:
245 Object: MMFF system generator object.
246
247 Examples:
248
249 OptionsInfo["SystemParams"] =
250 OpenMMUtil.ProcessOptionOpenMMSystemParameters("--systemParams",
251 Options["--systemParams"])
252 ... ... ...
253 SystemGeneratorHandle = OpenMMUtil.InitializeSystemGenerator(
254 BiopolymerForcefield, SmallMoleculeForcefield, WaterForcefield,
255 OptionsInfo["SystemParams"], SmallMols, AdditionalForcefiedsList)
256
257 """
258
259 (ForcefieldParams, PeriodicForcefieldParams, NonPeriodicForcefieldParams) = (
260 SetupSystemGeneratorForcefieldsParameters(SystemParamsInfo)
261 )
262
263 AdditionalForcefieldMsg = ""
264 if AdditionalForcefieldsList is not None:
265 AdditionalForcefieldMsg = "; Additional forcefield(s): %s" % ", ".join(AdditionalForcefieldsList)
266
267 MiscUtil.PrintInfo(
268 "\nInitializing system generator (Biopolymer forcefield: %s; Small molecule forcefield: %s; Water forcefield: %s%s)..."
269 % (BiopolymerForcefield, SmallMoleculeForcefield, WaterForcefield, AdditionalForcefieldMsg)
270 )
271
272 ForcefieldsList = [BiopolymerForcefield, WaterForcefield]
273 if AdditionalForcefieldsList is not None:
274 ForcefieldsList.extend(AdditionalForcefieldsList)
275
276 SystemGeneratorHandle = mmff.generators.SystemGenerator(
277 forcefields=ForcefieldsList,
278 small_molecule_forcefield=SmallMoleculeForcefield,
279 molecules=SmallMols,
280 forcefield_kwargs=ForcefieldParams,
281 periodic_forcefield_kwargs=PeriodicForcefieldParams,
282 nonperiodic_forcefield_kwargs=NonPeriodicForcefieldParams,
283 )
284
285 return SystemGeneratorHandle
286
287
288 def InitializeIntegrator(ParamsInfo, ConstraintErrorTolerance):
289 """Initialize integrator.
290
291 The ParamsInfo parameter is a dictionary of name and value pairs for
292 integrator parameters and may be generated by calling the function named
293 ProcessOptionOpenMMIntegratorParameters().
294
295 Arguments:
296 ParamsInfo (dict): Parameter name and value pairs.
297 ConstraintErrorTolerance (float): Distance tolerance for
298 constraints as a fraction of the constrained distance.
299
300 Returns:
301 Object: OpenMM integrator object.
302
303 Examples:
304
305 OptionsInfo["IntegratorParams"] =
306 OpenMMUtil.ProcessOptionOpenMMIntegratorParameters(
307 "--integratorParams", Options["--integratorParams"],
308 HydrogenMassRepartioningStatus =
309 OptionsInfo["SystemParams"]["HydrogenMassRepartioning"])
310 ... ... ...
311 Integrator = OpenMMUtil.InitializeIntegrator(
312 OptionsInfo["IntegratorParams"],
313 OptionsInfo["SystemParams"]["ConstraintErrorTolerance"])
314
315 """
316
317 IntegratorParamsInfo = SetupIntegratorParameters(ParamsInfo)
318
319 IntegratorName = IntegratorParamsInfo["Integrator"]
320 RandomSeed = IntegratorParamsInfo["RandomSeed"]
321 StepSize = IntegratorParamsInfo["StepSize"]
322 Temperature = IntegratorParamsInfo["Temperature"]
323 FrictionCoefficient = IntegratorParamsInfo["FrictionCoefficient"]
324
325 MiscUtil.PrintInfo(
326 "\nIntializing integrator (Name: %s; StepSize: %s; Temperature: %s)..."
327 % (IntegratorName, StepSize, Temperature)
328 )
329
330 if re.match("^LangevinMiddle$", IntegratorName, re.I):
331 Integrator = mm.LangevinMiddleIntegrator(Temperature, FrictionCoefficient, StepSize)
332 elif re.match("^Langevin$", IntegratorName, re.I):
333 Integrator = mm.LangevinIntegrator(Temperature, FrictionCoefficient, StepSize)
334 elif re.match("^NoseHoover$", IntegratorName, re.I):
335 Integrator = mm.NoseHooverIntegrator(Temperature, FrictionCoefficient, StepSize)
336 elif re.match("^Brownian$", IntegratorName, re.I):
337 Integrator = mm.BrownianIntegrator(Temperature, FrictionCoefficient, StepSize)
338 else:
339 MiscUtil.PrintError(
340 'The parameter value specified, %s, for parameter name, integrator, for option "--integratorParams" is not a valid value. Supported values: LangevinMiddle, Langevin, NoseHoover, or Brownian'
341 % IntegratorName
342 )
343
344 Integrator.setConstraintTolerance(ConstraintErrorTolerance)
345
346 if RandomSeed is not None:
347 if re.match("^(LangevinMiddle|Langevin|Brownian)$", IntegratorName, re.I):
348 MiscUtil.PrintInfo("Setting random number seed for integrator to %s..." % RandomSeed)
349 Integrator.setRandomNumberSeed(RandomSeed)
350 else:
351 MiscUtil.PrintInfo(
352 "Skipping setting of random number seed. Not supported for integrator %s..." % IntegratorName
353 )
354
355 return Integrator
356
357
358 def InitializeBarostat(ParamsInfo):
359 """Initialize barostat.
360
361 The ParamsInfo parameter is a dictionary of name and value pairs for
362 integrator parameters and may be generated by calling the function named
363 ProcessOptionOpenMMIntegratorParameters().
364
365 Arguments:
366 ParamsInfo (dict): Parameter name and value pairs.
367
368 Returns:
369 Object: OpenMM barostat object.
370
371 Examples:
372
373 OptionsInfo["IntegratorParams"] =
374 OpenMMUtil.ProcessOptionOpenMMIntegratorParameters(
375 "--integratorParams", Options["--integratorParams"],
376 HydrogenMassRepartioningStatus =
377 OptionsInfo["SystemParams"]["HydrogenMassRepartioning"])
378 ... ... ...
379 Barostat = OpenMMUtil.InitializeBarostat(
380 OptionsInfo["IntegratorParams"])
381
382 """
383 IntegratorParamsInfo = SetupIntegratorParameters(ParamsInfo)
384
385 BarostatName = IntegratorParamsInfo["Barostat"]
386 if re.match("^MonteCarlo$", BarostatName, re.I):
387 MiscUtil.PrintInfo(
388 "\nInitializing Monte Carlo barostat (Pressure: %s)... " % (IntegratorParamsInfo["Pressure"])
389 )
390 Barostat = mm.MonteCarloBarostat(
391 IntegratorParamsInfo["Pressure"],
392 IntegratorParamsInfo["Temperature"],
393 IntegratorParamsInfo["BarostatInterval"],
394 )
395 elif re.match("^MonteCarloMembrane$", BarostatName, re.I):
396 MiscUtil.PrintInfo(
397 "\nInitializing Monte Carlo membrane barostat (Pressure: %s; SurfaceTension: %s; XYMode: %s; ZMode: %s)... "
398 % (
399 IntegratorParamsInfo["Pressure"],
400 IntegratorParamsInfo["SurfaceTension"],
401 IntegratorParamsInfo["XYModeSpecified"],
402 IntegratorParamsInfo["ZModeSpecified"],
403 )
404 )
405 Barostat = mm.MonteCarloMembraneBarostat(
406 IntegratorParamsInfo["Pressure"],
407 IntegratorParamsInfo["SurfaceTension"],
408 IntegratorParamsInfo["Temperature"],
409 IntegratorParamsInfo["XYMode"],
410 IntegratorParamsInfo["ZMode"],
411 IntegratorParamsInfo["BarostatInterval"],
412 )
413 else:
414 MiscUtil.PrintError(
415 'The parameter value specified, %s, for parameter name, barostat, for option "--integratorParams" is not a valid value. Supported values: MonteCarlo or MonteCarloMembrane'
416 % BarostatName
417 )
418
419 if IntegratorParamsInfo["RandomSeed"] is not None:
420 RandomSeed = IntegratorParamsInfo["RandomSeed"]
421 MiscUtil.PrintInfo("Setting random number seed for barostat to %s..." % RandomSeed)
422 Barostat.setRandomNumberSeed(RandomSeed)
423
424 return Barostat
425
426
427 def InitializeSimulation(System, Integrator, Topology, Positions, PlatformParamsInfo):
428 """Initialize simulation.
429
430 The PlatformParamsInfo parameter is a dictionary of name and value pairs for
431 platform parameters and may be generated by calling the function named
432 ProcessOptionOpenMMPlatformParameters().
433
434 Arguments:
435 System (object): OpenMM system object.
436 Integrator (object): OpenMM integrator object.
437 Topology (object): OpenMM topology object.
438 Positons (object): OpenMM Positions object.
439 PlatformParamsInfo (dict): Parameter name and value pairs.
440
441 Returns:
442 Object: OpenMM simulation object.
443
444 Examples:
445
446 ParamsDefaultInfoOverride = {"Name": Options["--platform"],
447 "Threads": 1}
448 OptionsInfo["PlatformParams"] =
449 OpenMMUtil.ProcessOptionOpenMMPlatformParameters("--platformParams",
450 Options["--platformParams"], ParamsDefaultInfoOverride)
451 ... ... ...
452 Simulation = OpenMMUtil.InitializeSimulation(System, Integrator, Topology,
453 Positions, OptionsInfo["PlatformParams"])
454
455 """
456
457 PlatformName, PlatformProperties, PlatformMsg = SetupPlatformParameters(PlatformParamsInfo)
458 MiscUtil.PrintInfo("\nInitializing simulation (%s)..." % PlatformMsg)
459
460 try:
461 PlatformHandle = mm.Platform.getPlatformByName(PlatformName)
462 except Exception as ErrMsg:
463 MiscUtil.PrintInfo("")
464 MiscUtil.PrintError("Failed to get platform %s:\n%s\n" % (PlatformName, ErrMsg))
465
466 try:
467 SimulationHandle = mm.app.Simulation(Topology, System, Integrator, PlatformHandle, PlatformProperties)
468 except Exception as ErrMsg:
469 MiscUtil.PrintInfo("")
470 MiscUtil.PrintError("Failed to initialize simulation: %s\n" % (ErrMsg))
471
472 SimulationHandle.context.setPositions(Positions)
473
474 return SimulationHandle
475
476
477 def InitializeReporters(OutputParamsInfo, TotalSteps, DataOutAppendStatus):
478 """Initialize reporters for writing data to trajectory, log, and checkpoint
479 files along with reporting to the stdout.
480
481 The OutputParamsInfo parameter is a dictionary of name and value pairs for
482 output parameters and may be generated by calling the function named
483 ProcessOptionOpenMMOutputParameters().
484
485 Arguments:
486 OutputParamsInfo (dict): Parameter name and value pairs.
487 TotalSteps (int): Total number of simulation steps.
488 DataOutAppendStatus (bool): Append data to trajectory and log file.
489
490 Returns:
491 Object: OpenMM trajectory reporter object.
492 Object: OpenMM data log file reporter object.
493 Object: OpenMM stodut reporter object.
494 Object: OpenMM checkpoint reporter object.
495
496 Examples:
497
498 if OptionsInfo["NVTMode"]:
499 ParamsDefaultInfoOverride = {"DataOutType": "Step Speed Progress
500 PotentialEnergy Temperature Time Volume"}
501 else:
502 ParamsDefaultInfoOverride = {"DataOutType": "Step Speed Progress
503 PotentialEnergy Temperature Time Density"}
504 OptionsInfo["OutputParams"] =
505 OpenMMUtil.ProcessOptionOpenMMOutputParameters("--outputParams",
506 Options["--outputParams"], OptionsInfo["OutfilePrefix"],
507 ParamsDefaultInfoOverride)
508 ProcessOutfileNames()
509 ... ... ...
510 (TrajReporter, DataLogReporter, DataStdoutReporter, CheckpointReporter)
511 = OpenMMUtil.InitializeReporters(OptionsInfo["OutputParams"],
512 OptionsInfo["SimulationParams"]["Steps"], OptionsInfo["DataOutAppendMode"])
513
514 """
515
516 (TrajReporter, DataLogReporter, DataStdoutReporter, CheckpointReporter) = [None] * 4
517 if OutputParamsInfo["Traj"]:
518 if re.match("^DCD$", OutputParamsInfo["TrajFormat"], re.I):
519 TrajReporter = mm.app.DCDReporter(
520 OutputParamsInfo["TrajFile"], OutputParamsInfo["TrajSteps"], append=DataOutAppendStatus
521 )
522 elif re.match("^XTC$", OutputParamsInfo["TrajFormat"], re.I):
523 if not DataOutAppendStatus:
524 # Remove existing traj file; otherwise, XTCReporter fails...
525 if os.path.isfile(OutputParamsInfo["TrajFile"]):
526 os.remove(OutputParamsInfo["TrajFile"])
527 TrajReporter = mm.app.XTCReporter(
528 OutputParamsInfo["TrajFile"], OutputParamsInfo["TrajSteps"], append=DataOutAppendStatus
529 )
530 else:
531 MiscUtil.PrintError(
532 'The parameter value specified, %s, for parameter name, trajFormat, for option "--outputParams" is not a valid value. Supported format: DCD or XTC'
533 )
534
535 if OutputParamsInfo["Checkpoint"]:
536 CheckpointReporter = mm.app.CheckpointReporter(
537 OutputParamsInfo["CheckpointFile"], OutputParamsInfo["CheckpointSteps"]
538 )
539
540 DataOutTypeStatusMap = OutputParamsInfo["DataOutTypeStatusMap"]
541 if OutputParamsInfo["DataLog"]:
542 DataLogReporter = mm.app.StateDataReporter(
543 OutputParamsInfo["DataLogFile"],
544 OutputParamsInfo["DataLogSteps"],
545 totalSteps=TotalSteps,
546 step=DataOutTypeStatusMap["Step"],
547 time=DataOutTypeStatusMap["Time"],
548 speed=DataOutTypeStatusMap["Speed"],
549 progress=DataOutTypeStatusMap["Progress"],
550 elapsedTime=DataOutTypeStatusMap["ElapsedTime"],
551 remainingTime=DataOutTypeStatusMap["RemainingTime"],
552 potentialEnergy=DataOutTypeStatusMap["PotentialEnergy"],
553 kineticEnergy=DataOutTypeStatusMap["KineticEnergy"],
554 totalEnergy=DataOutTypeStatusMap["TotalEnergy"],
555 temperature=DataOutTypeStatusMap["Temperature"],
556 volume=DataOutTypeStatusMap["Volume"],
557 density=DataOutTypeStatusMap["Density"],
558 separator=OutputParamsInfo["DataOutDelimiter"],
559 append=DataOutAppendStatus,
560 )
561
562 if OutputParamsInfo["DataStdout"]:
563 DataStdoutReporter = mm.app.StateDataReporter(
564 sys.stdout,
565 OutputParamsInfo["DataStdoutSteps"],
566 totalSteps=TotalSteps,
567 step=DataOutTypeStatusMap["Step"],
568 time=DataOutTypeStatusMap["Time"],
569 speed=DataOutTypeStatusMap["Speed"],
570 progress=DataOutTypeStatusMap["Progress"],
571 elapsedTime=DataOutTypeStatusMap["ElapsedTime"],
572 remainingTime=DataOutTypeStatusMap["RemainingTime"],
573 potentialEnergy=DataOutTypeStatusMap["PotentialEnergy"],
574 kineticEnergy=DataOutTypeStatusMap["KineticEnergy"],
575 totalEnergy=DataOutTypeStatusMap["TotalEnergy"],
576 temperature=DataOutTypeStatusMap["Temperature"],
577 volume=DataOutTypeStatusMap["Volume"],
578 density=DataOutTypeStatusMap["Density"],
579 separator=OutputParamsInfo["DataOutDelimiter"],
580 )
581
582 return (TrajReporter, DataLogReporter, DataStdoutReporter, CheckpointReporter)
583
584
585 def PerformAnnealing(
586 Simulation, Integrator, Barostat, TemperatureStart, TemperatureEnd, TemperatureChange, SimulationSteps
587 ):
588 """Perform annealing by heating or cooling the system from start to end
589 temperature.
590
591 The temperature is increased or decreased from start to end temperature by
592 temperature to perform annealing following by performing simulations for a
593 specified number of steps after each temperature step.
594
595 Arguments:
596 System (object): OpenMM system object.
597 Integrator (object): OpenMM integrator object.
598 Barostat (object): OpenMM integrator object.
599 TemperatureStart (float): Start temperature.
600 TemperatureEnd (float): End temperature.
601 TemperatureChange (int): Temperature step size to heat or cool the
602 system from start to end temperature.
603 SimulationSteps (fint): Number of simulations steps to perform after
604 each temperature step.
605
606 Returns:
607 int: Total number of simulation steps.
608
609 Examples:
610
611 ... ... ...
612 TotalInitialSimulationSteps = OpenMMUtil.PerformAnnealing(Simulation,
613 Integrator, Barostat, InitialStart, InitialEnd, InitialChange, InitialSteps)
614
615 """
616
617 if TemperatureStart < TemperatureEnd:
618 TemperatureRange = np.arange(TemperatureStart, TemperatureEnd, TemperatureChange)
619 else:
620 TemperatureRange = np.arange(TemperatureStart, TemperatureEnd, -TemperatureChange)
621
622 TemperatureRange = TemperatureRange.tolist()
623 TemperatureRange.append(TemperatureEnd)
624
625 TotalSimulationSteps = 0
626 for Temperature in TemperatureRange:
627 Temperature = Temperature * mm.unit.kelvin
628
629 Integrator.setTemperature(Temperature)
630 if Barostat is not None:
631 try:
632 Simulation.context.setParameter(Barostat.Temperature(), Temperature)
633 except Exception as ErrMsg:
634 MiscUtil.PrintInfo("")
635 MiscUtil.PrintError("Failed to set barostat temperature:\n%s\n" % (ErrMsg))
636
637 Simulation.step(SimulationSteps)
638 TotalSimulationSteps += SimulationSteps
639
640 return TotalSimulationSteps
641
642
643 def AddWaterBox(ModellerHandle, SystemGeneratorHandle, WaterBoxParamsInfo):
644 """Add a water box.
645
646 The WaterBoxParamsInfo parameter is a dictionary of name and value pairs for
647 waterbox parameters and may be generated by calling the function named
648 ProcessOptionOpenMMWaterBoxParameters().
649
650 Arguments:
651 ModellerHandle (object): OpenMM modeller object.
652 SystemGeneratorHandle (object): OpenMM system generator object.
653 WaterBoxParamsInfo (dict): Parameter name and value pairs.
654
655 Returns:
656 None.
657
658 Examples:
659
660 OptionsInfo["WaterBoxParams"] =
661 OpenMMUtil.ProcessOptionOpenMMWaterBoxParameters("--waterBoxParams",
662 Options["--waterBoxParams"])
663 ... ... ...
664 OpenMMUtil.AddWaterBox(ModellerHandle, SystemGeneratorHandle,
665 OptionsInfo["WaterBoxParams"])
666
667 """
668
669 MiscUtil.PrintInfo("\nRemoving any existing waters...")
670 ModellerHandle.deleteWater()
671
672 MiscUtil.PrintInfo("\nAdding a water box...")
673
674 Size, Padding, Shape = [None] * 3
675 if WaterBoxParamsInfo["ModeSize"]:
676 SizeList = WaterBoxParamsInfo["SizeList"]
677 Size = mm.Vec3(SizeList[0], SizeList[1], SizeList[2]) * mm.unit.nanometer
678 elif WaterBoxParamsInfo["ModePadding"]:
679 Padding = WaterBoxParamsInfo["Padding"] * mm.unit.nanometer
680 Shape = WaterBoxParamsInfo["Shape"]
681 else:
682 MiscUtil.PrintError(
683 'The parameter value, %s, specified for parameter name, mode, using "--waterBoxParams" option is not a valid value. Supported values: Size Padding \n'
684 % (WaterBoxParamsInfo["Mode"])
685 )
686
687 IonicStrength = WaterBoxParamsInfo["IonicStrength"] * mm.unit.molar
688
689 ModellerHandle.addSolvent(
690 SystemGeneratorHandle.forcefield,
691 model=WaterBoxParamsInfo["Model"],
692 boxSize=Size,
693 boxVectors=None,
694 padding=Padding,
695 numAdded=None,
696 boxShape=Shape,
697 positiveIon=WaterBoxParamsInfo["IonPositive"],
698 negativeIon=WaterBoxParamsInfo["IonNegative"],
699 ionicStrength=IonicStrength,
700 neutralize=True,
701 )
702
703
704 def SetupSystemGeneratorForcefieldsParameters(SystemParamsInfo):
705 """Setup forcefied parameters for OpenMM API calls.
706
707 The SystemParamsInfo parameter is a dictionary of name and value pairs for
708 system parameters and may be generated by calling the function named
709 ProcessOptionOpenMMSystemParameters().
710
711 Arguments:
712 SystemParamsInfo (dict): Parameter name and value pairs.
713
714 Returns:
715 dict: Forcefield parameter name and value pairs.
716 dictionary2: Periodic forcefield parameter name and value pairs.
717 dictionary3: Non-periodic parameter name and value pairs.
718
719 Examples:
720
721 OptionsInfo["SystemParams"] =
722 OpenMMUtil.ProcessOptionOpenMMSystemParameters("--systemParams",
723 Options["--systemParams"])
724 ... ... ...
725 (ForcefieldParams, PeriodicForcefieldParams, NonPeriodicForcefieldParams)
726 = SetupSystemGeneratorForcefieldsParameters(OptionsInfo["SystemParams"])
727
728 """
729
730 ForcefieldParams = {
731 "constraints": SystemParamsInfo["Constraints"],
732 "rigidWater": SystemParamsInfo["RigidWater"],
733 "removeCMMotion": SystemParamsInfo["RemoveCMMotion"],
734 }
735 if SystemParamsInfo["HydrogenMassRepartioning"]:
736 ForcefieldParams["hydrogenMass"] = SystemParamsInfo["HydrogenMass"] * mm.unit.amu
737
738 NonbondedCutoff = SystemParamsInfo["NonbondedCutoff"] * mm.unit.nanometers
739 PeriodicForcefieldParams = {
740 "nonbondedMethod": SystemParamsInfo["NonbondedMethodPeriodic"],
741 "nonbondedCutoff": NonbondedCutoff,
742 "ewaldErrorTolerance": SystemParamsInfo["EwaldErrorTolerance"],
743 }
744 NonPeriodicForcefieldParams = {
745 "nonbondedMethod": SystemParamsInfo["NonbondedMethodNonPeriodic"],
746 "nonbondedCutoff": NonbondedCutoff,
747 }
748
749 return (ForcefieldParams, PeriodicForcefieldParams, NonPeriodicForcefieldParams)
750
751
752 def SetupPlatformParameters(ParamsInfo):
753 """Setup platform parameters for OpenMM calls.
754
755 The ParamsInfo parameter is a dictionary of name and value pairs for
756 platform parameters and may be generated by calling the function named
757 ProcessOptionOpenMMPlatformParameters().
758
759 Arguments:
760 ParamsInfo (dict): Parameter name and value pairs.
761
762 Returns:
763 str: PlatformName.
764 dict: Platform properities parameter name and values pairs.
765 str: Text message describing platform.
766
767 Examples:
768
769 ParamsDefaultInfoOverride = {"Name": Options["--platform"],
770 "Threads": 1}
771 OptionsInfo["PlatformParams"] =
772 OpenMMUtil.ProcessOptionOpenMMPlatformParameters("--platformParams",
773 Options["--platformParams"], ParamsDefaultInfoOverride)
774 ... ... ...
775 PlatformName, PlatformProperties, PlatformMsg =
776 SetupPlatformParameters(PlatformParamsInfo)
777
778 """
779
780 PlatformName = ParamsInfo["Name"]
781 ParamNames = None
782
783 if re.match("^CPU$", PlatformName, re.I):
784 ParamNames = ["Threads"]
785 elif re.match("^CUDA$", PlatformName, re.I):
786 ParamNames = [
787 "DeviceIndex",
788 "DeterministicForces",
789 "Precision",
790 "TempDirectory",
791 "UseBlockingSync",
792 "UseCpuPme",
793 ]
794 elif re.match("^OpenCL$", PlatformName, re.I):
795 ParamNames = ["DeviceIndex", "OpenCLPlatformIndex", "Precision", "UseCpuPme"]
796 elif re.match("^Reference$", PlatformName, re.I):
797 ParamNames = None
798 else:
799 MiscUtil.PrintError(
800 'The parameter value specified, %s, for parameter name, name, for option "--platformParams" is not a valid value. Supported values: CPU, CUDA, OpenCL, or Reference'
801 )
802
803 PlatformProperties = None
804 if ParamNames is not None:
805 FirstValue = True
806 for ParamName in ParamNames:
807 ParamValue = ParamsInfo[ParamName]
808 if ParamValue is not None:
809 if FirstValue:
810 FirstValue = False
811 PlatformProperties = {}
812 PlatformProperties[ParamName] = ParamValue
813
814 PlatformMsg = "Platform: %s" % PlatformName
815 if re.match("^CPU$", PlatformName, re.I):
816 Threads = ParamsInfo["Threads"]
817 if Threads is None or Threads == "0":
818 Threads = "auto"
819 PlatformMsg = "Platform: %s; Threads: %s" % (PlatformName, Threads)
820 elif re.match("^(CUDA|OpenCL)$", PlatformName, re.I):
821 DeviceIndex = "auto" if ParamsInfo["DeviceIndex"] is None else ParamsInfo["DeviceIndex"]
822 Precision = "auto" if ParamsInfo["Precision"] is None else ParamsInfo["Precision"]
823 PlatformMsg = "Platform: %s; DeviceIndex: %s; Precision: %s" % (PlatformName, DeviceIndex, Precision)
824
825 return (PlatformName, PlatformProperties, PlatformMsg)
826
827
828 def SetupAnnealingParameters(ParamsInfo):
829 """Setup annealing parameters for OpenMM API calls.
830
831 The ParamsInfo parameter is a dictionary of name and value pairs for
832 annealing parameters and may be generated by calling the function named
833 ProcessOptionOpenMMAnnealingParameters().
834
835 Arguments:
836 ParamsInfo (dict): Parameter name and value pairs.
837
838 Returns:
839 dict: Annealing parameter name and values pairs.
840
841 Examples:
842
843 OptionsInfo["AnnealingParams"] =
844 OpenMMUtil.ProcessOptionOpenMMAnnealingParameters(
845 "--annealingParams", Options["--annealingParams"],
846 ... ... ...
847 AnnealingParams = SetupAnnealingParams(
848 OptionsInfo["AnnealingParams"])
849
850 """
851
852 ParamsInfoWithUnits = {}
853
854 ParamsInfoWithUnits["InitialStart"] = ParamsInfo["InitialStart"] * mm.unit.kelvin
855 ParamsInfoWithUnits["InitialEnd"] = ParamsInfo["InitialEnd"] * mm.unit.kelvin
856 ParamsInfoWithUnits["InitialChange"] = ParamsInfo["InitialChange"] * mm.unit.kelvin
857 ParamsInfoWithUnits["InitialSteps"] = ParamsInfo["InitialSteps"]
858
859 ParamsInfoWithUnits["InitialEquilibrationSteps"] = ParamsInfo["InitialEquilibrationSteps"]
860
861 ParamsInfoWithUnits["Cycles"] = ParamsInfo["Cycles"]
862 ParamsInfoWithUnits["CycleStart"] = ParamsInfo["CycleStart"] * mm.unit.kelvin
863 ParamsInfoWithUnits["CycleEnd"] = ParamsInfo["CycleEnd"] * mm.unit.kelvin
864 ParamsInfoWithUnits["CycleChange"] = ParamsInfo["CycleChange"] * mm.unit.kelvin
865 ParamsInfoWithUnits["CycleSteps"] = ParamsInfo["CycleSteps"]
866
867 ParamsInfoWithUnits["CycleEquilibrationSteps"] = ParamsInfo["CycleEquilibrationSteps"]
868
869 ParamsInfoWithUnits["FinalEquilibrationSteps"] = ParamsInfo["FinalEquilibrationSteps"]
870
871 return ParamsInfoWithUnits
872
873
874 def SetupMDProtocolParameters(ParamsInfo):
875 """Setup MD protocol parameters for OpenMM API calls.
876
877 The ParamsInfo parameter is a dictionary of name and value pairs for
878 annealing parameters and may be generated by calling the function named
879 ProcessOptionOpenMMMDProtocolParameters().
880
881 Arguments:
882 ParamsInfo (dict): Parameter name and value pairs.
883
884 Returns:
885 dict: MD protocol parameter name and values pairs.
886
887 Examples:
888
889 OptionsInfo["ProtocolParams"] =
890 OpenMMUtil.ProcessOptionOpenMMMDProtocolParameters(
891 "--protocolParams", Options["--protocolParams"],
892 ... ... ...
893 ProtocolParams = SetupMDProtocolParameters(
894 OptionsInfo["ProtocolParams"])
895
896 """
897
898 ParamsInfoWithUnits = {}
899
900 ParamsInfoWithUnits["Phase1"] = ParamsInfo["Phase1"]
901 ParamsInfoWithUnits["Phase1InitialStart"] = ParamsInfo["Phase1InitialStart"] * mm.unit.kelvin
902 ParamsInfoWithUnits["Phase1InitialEnd"] = ParamsInfo["Phase1InitialEnd"] * mm.unit.kelvin
903 ParamsInfoWithUnits["Phase1InitialChange"] = ParamsInfo["Phase1InitialChange"] * mm.unit.kelvin
904 ParamsInfoWithUnits["Phase1InitialSteps"] = ParamsInfo["Phase1InitialSteps"]
905
906 ParamsInfoWithUnits["Phase1InitialEquilibrationSteps"] = ParamsInfo["Phase1InitialEquilibrationSteps"]
907
908 ParamsInfoWithUnits["Phase2"] = ParamsInfo["Phase2"]
909 ParamsInfoWithUnits["Phase2Cycles"] = ParamsInfo["Phase2Cycles"]
910 ParamsInfoWithUnits["Phase2CycleStart"] = ParamsInfo["Phase2CycleStart"] * mm.unit.kelvin
911 ParamsInfoWithUnits["Phase2CycleEnd"] = ParamsInfo["Phase2CycleEnd"] * mm.unit.kelvin
912 ParamsInfoWithUnits["Phase2CycleChange"] = ParamsInfo["Phase2CycleChange"] * mm.unit.kelvin
913 ParamsInfoWithUnits["Phase2CycleSteps"] = ParamsInfo["Phase2CycleSteps"]
914
915 ParamsInfoWithUnits["Phase2CycleEquilibrationSteps"] = ParamsInfo["Phase2CycleEquilibrationSteps"]
916
917 ParamsInfoWithUnits["Phase3"] = ParamsInfo["Phase3"]
918 ParamsInfoWithUnits["Phase3Steps"] = ParamsInfo["Phase3Steps"]
919
920 ParamsInfoWithUnits["Phase4"] = ParamsInfo["Phase4"]
921 ParamsInfoWithUnits["Phase4Steps"] = ParamsInfo["Phase4Steps"]
922
923 ParamsInfoWithUnits["Phase5"] = ParamsInfo["Phase5"]
924 ParamsInfoWithUnits["Phase5Steps"] = ParamsInfo["Phase5Steps"]
925 if ParamsInfo["Phase5StepSize"] is None:
926 ParamsInfoWithUnits["Phase5StepSize"] = None
927 else:
928 ParamsInfoWithUnits["Phase5StepSize"] = ParamsInfo["Phase5StepSize"] * mm.unit.femtoseconds
929
930 return ParamsInfoWithUnits
931
932
933 def SetupIntegratorParameters(ParamsInfo):
934 """Setup integrator parameters for OpenMM API calls.
935
936 The ParamsInfo parameter is a dictionary of name and value pairs for
937 integrator parameters and may be generated by calling the function named
938 ProcessOptionOpenMMIntegratorParameters().
939
940 Arguments:
941 ParamsInfo (dict): Parameter name and value pairs.
942
943 Returns:
944 dict: Integrator parameter name and values pairs.
945
946 Examples:
947
948 OptionsInfo["IntegratorParams"] =
949 OpenMMUtil.ProcessOptionOpenMMIntegratorParameters(
950 "--integratorParams", Options["--integratorParams"],
951 HydrogenMassRepartioningStatus =
952 OptionsInfo["SystemParams"]["HydrogenMassRepartioning"])
953 ... ... ...
954 IntegratorParams = SetupIntegratorParameters(
955 OptionsInfo["IntegratorParams"])
956
957 """
958
959 ParamsInfoWithUnits = {}
960
961 ParamsInfoWithUnits["Integrator"] = ParamsInfo["Integrator"]
962
963 ParamsInfoWithUnits["RandomSeed"] = ParamsInfo["RandomSeed"]
964
965 ParamsInfoWithUnits["FrictionCoefficient"] = ParamsInfo["FrictionCoefficient"] / mm.unit.picosecond
966 ParamsInfoWithUnits["StepSize"] = ParamsInfo["StepSize"] * mm.unit.femtoseconds
967 ParamsInfoWithUnits["Temperature"] = ParamsInfo["Temperature"] * mm.unit.kelvin
968
969 ParamsInfoWithUnits["Barostat"] = ParamsInfo["Barostat"]
970
971 ParamsInfoWithUnits["Pressure"] = ParamsInfo["Pressure"] * mm.unit.atmospheres
972 ParamsInfoWithUnits["BarostatInterval"] = ParamsInfo["BarostatInterval"]
973
974 SurfaceTensionInAngstroms = ParamsInfo["SurfaceTension"]
975 SurfaceTension = SurfaceTensionInAngstroms * mm.unit.atmospheres * mm.unit.angstroms
976
977 SurfaceTensionInNanometers = SurfaceTension.value_in_unit(mm.unit.atmospheres * mm.unit.nanometer)
978 ParamsInfoWithUnits["SurfaceTension"] = SurfaceTensionInNanometers * mm.unit.atmospheres * mm.unit.nanometers
979
980 XYMode = ParamsInfo["XYMode"]
981 XYModeSpecified = ""
982 if re.match("^Anisotropic$", XYMode, re.I):
983 XYMode = mm.MonteCarloMembraneBarostat.XYAnisotropic
984 XYModeSpecified = "Anisotropic"
985 elif re.match("^Isotropic$", XYMode, re.I):
986 XYMode = mm.MonteCarloMembraneBarostat.XYIsotropic
987 XYModeSpecified = "Isotropic"
988 else:
989 MiscUtil.PrintError(
990 'The parameter value specified, %s, for parameter name, xymode, for option "--integratorParams" is not a valid value. Supported values: Anisotropic or Isotropic'
991 % XYMode
992 )
993 ParamsInfoWithUnits["XYMode"] = XYMode
994 ParamsInfoWithUnits["XYModeSpecified"] = XYModeSpecified
995
996 ZMode = ParamsInfo["ZMode"]
997 ZModeSpecified = ""
998 if re.match("^Fixed$", ZMode, re.I):
999 ZMode = mm.MonteCarloMembraneBarostat.ZFixed
1000 ZModeSpecified = "Fixed"
1001 elif re.match("^Free$", ZMode, re.I):
1002 ZMode = mm.MonteCarloMembraneBarostat.ZFree
1003 ZModeSpecified = "Free"
1004 else:
1005 MiscUtil.PrintError(
1006 'The parameter value specified, %s, for parameter name, zmode, for option "--integratorParams" is not a valid value. Supported values: Fixed or Free'
1007 % ZMode
1008 )
1009 ParamsInfoWithUnits["ZMode"] = ZMode
1010 ParamsInfoWithUnits["ZModeSpecified"] = ZModeSpecified
1011
1012 return ParamsInfoWithUnits
1013
1014
1015 def SetupSimulationParameters(ParamsInfo):
1016 """Setup simulation parameters for OpenMM API calls.
1017
1018 The ParamsInfo parameter is a dictionary of name and value pairs for
1019 integrator parameters and may be generated by calling the function named
1020 ProcessOptionOpenMSimulationParameters().
1021
1022 Arguments:
1023 ParamsInfo (dict): Parameter name and value pairs.
1024
1025 Returns:
1026 dict: Integrator parameter name and values pairs.
1027
1028 Examples:
1029
1030 OptionsInfo["SimulationParams"] =
1031 OpenMMUtil.ProcessOptionOpenMMSimulationParameters(
1032 "--simulationParams", Options["--simulationParams"])
1033 ... ... ...
1034 SimulationParams = SetupSimulationParameters(
1035 OptionsInfo["SimulationParams"])
1036
1037 """
1038
1039 ParamsInfoWithUnits = {}
1040
1041 ParamsInfoWithUnits["Steps"] = ParamsInfo["Steps"]
1042
1043 ParamsInfoWithUnits["Minimization"] = ParamsInfo["Minimization"]
1044 ParamsInfoWithUnits["MinimizationMaxSteps"] = ParamsInfo["MinimizationMaxSteps"]
1045
1046 MinimizationToleranceInKcal = ParamsInfo["MinimizationTolerance"]
1047 MinimizationTolerance = MinimizationToleranceInKcal * mm.unit.kilocalories_per_mole / mm.unit.angstroms
1048
1049 MinimizationToleranceInJoules = MinimizationTolerance.value_in_unit(mm.unit.kilojoules_per_mole / mm.unit.nanometer)
1050 MinimizationTolerance = MinimizationToleranceInJoules * mm.unit.kilojoules_per_mole / mm.unit.nanometer
1051
1052 ParamsInfoWithUnits["MinimizationToleranceInKcal"] = MinimizationToleranceInKcal
1053 ParamsInfoWithUnits["MinimizationToleranceInJoules"] = MinimizationToleranceInJoules
1054 ParamsInfoWithUnits["MinimizationTolerance"] = MinimizationTolerance
1055
1056 ParamsInfoWithUnits["Equilibration"] = ParamsInfo["Equilibration"]
1057 ParamsInfoWithUnits["EquilibrationSteps"] = ParamsInfo["EquilibrationSteps"]
1058
1059 return ParamsInfoWithUnits
1060
1061
1062 def GenerateReimagedRealignedTrajectoryFiles(
1063 System, Topology, TrajTopologyFile, ReimagedPDBOutfile, ReimagedTrajOutfile, OutputParamsInfo, RealignFrames=True
1064 ):
1065 """Reimage and realign a trajectory file using MDTraj. The trajectory frames
1066 are reimaged before realigning to the first frame using the specified atom
1067 selection.
1068
1069 The trajectory file format must a valid format supported by MDTraj. No
1070 validation is performed.
1071
1072 The OutputParamsInfo is a dictionary of name and value pairs for output
1073 parameters and may be generated by calling the function named
1074 ProcessOptionOpenMMOutputParameters().
1075
1076 Arguments:
1077 System (object): OpenMM system object.
1078 Topology (object): OpenMM topology object.
1079 TrajTopologyFile (str): Trajectory PDB topology file name.
1080 ReimagedPDBOutfile (str): Trajectory PDB out file name.
1081 ReimagedTrajOutfile (str): Trajectory out file name.
1082 OutputParamsInfo (dict): Parameter name and value pairs.
1083 RealignFrames (bool): Realign trajectory frames.
1084
1085 Returns:
1086 None
1087
1088 """
1089
1090 if not OutputParamsInfo["Traj"] or not os.path.exists(OutputParamsInfo["TrajFile"]):
1091 return
1092
1093 ReimageFrames = True if DoesSystemUsesPeriodicBoundaryConditions(System) else False
1094 if not ReimageFrames:
1095 MiscUtil.PrintInfo(
1096 "\nSkipping reimaging and realigning of trajectory for a system not using periodic boundary conditions..."
1097 )
1098 return
1099
1100 MiscUtil.PrintInfo("\nReimaging and realigning trajectory for a system using periodic boundary conditions...")
1101
1102 # Reimage and realign trajectory file...
1103 TrajFile = OutputParamsInfo["TrajFile"]
1104 Traj, ReimagedStatus, RealignedStatus = ReimageRealignTrajectory(Topology, TrajFile, ReimageFrames, RealignFrames)
1105
1106 PDBOutFormat = OutputParamsInfo["PDBOutFormat"]
1107
1108 if (Traj is None) or (not ReimagedStatus and not RealignedStatus):
1109 MiscUtil.PrintInfo("Skipping writing first frame to PDB file %s..." % ReimagedPDBOutfile)
1110 MiscUtil.PrintInfo("Skippig writing trajectory file %s..." % ReimagedTrajOutfile)
1111 return
1112
1113 # Write out first frame...
1114 MiscUtil.PrintInfo("Writing first frame to PDB file %s..." % ReimagedPDBOutfile)
1115 if re.match("^CIF$", PDBOutFormat, re.I):
1116 # MDTraj doesn't appear to support CIF format. Write it out as a temporary
1117 # PDB file and convert it using OpenMM...
1118 FileDir, FileRoot, FileExt = MiscUtil.ParseFileName(ReimagedPDBOutfile)
1119 TmpReimagedPDBOutfile = "%s_PID%s.pdb" % (FileRoot, os.getpid())
1120 Traj[0].save(TmpReimagedPDBOutfile)
1121
1122 PDBHandle = ReadPDBFile(TmpReimagedPDBOutfile)
1123 WritePDBFile(ReimagedPDBOutfile, PDBHandle.topology, PDBHandle.positions, OutputParamsInfo["PDBOutKeepIDs"])
1124
1125 os.remove(TmpReimagedPDBOutfile)
1126 else:
1127 Traj[0].save(ReimagedPDBOutfile)
1128
1129 # Write out reimaged and realinged trajectory...
1130 MiscUtil.PrintInfo("Writing trajectory file %s..." % ReimagedTrajOutfile)
1131 Traj.save(ReimagedTrajOutfile)
1132
1133
1134 def ReimageRealignTrajectory(
1135 Topology, TrajFile, ReimageFrames=True, RealignFrames=True, Selection="protein and backbone and name CA"
1136 ):
1137 """Reimage and realign a trajectory file using MDTraj. The trajectory frames
1138 are reimaged before realigning to the first frame using the specified atom
1139 selection.
1140
1141 The trajectory file format must a valid format supported by MDTraj. No
1142 validation is performed.
1143
1144 Arguments:
1145 Topology (str or object): PDB file name or OpenMM topology object.
1146 TrajFile (str): Trajectory file name.
1147 ReimageFrames (bool): Reimage trajectory frames.
1148 RealignFrames (bool): Realign trajectory frames.
1149 Selection (str): MDTraj atom selection for realigning frames.
1150
1151 Returns:
1152 None or object: MDTraj trajectory object.
1153 bool: Reimaged status.
1154 bool: Realigned status.
1155
1156 """
1157
1158 if isinstance(Topology, str):
1159 MiscUtil.PrintInfo("Reading trajectory file %s (TopologyFile: %s)..." % (TrajFile, Topology))
1160 else:
1161 MiscUtil.PrintInfo("Reading trajectory file %s..." % (TrajFile))
1162 Topology = mdtraj.Topology.from_openmm(Topology)
1163
1164 try:
1165 Traj = mdtraj.load(TrajFile, top=Topology)
1166 except Exception as ErrMsg:
1167 MiscUtil.PrintInfo("")
1168 MiscUtil.PrintWarning("Failed to read trajectory file: %s" % ErrMsg)
1169 MiscUtil.PrintInfo("")
1170 return (None, False, False)
1171
1172 ReimagedStatus, RealignedStatus = [False] * 2
1173
1174 if ReimageFrames:
1175 MiscUtil.PrintInfo("Reimaging frames...")
1176 try:
1177 Traj.image_molecules(inplace=True)
1178 ReimagedStatus = True
1179 except Exception as ErrMsg:
1180 MiscUtil.PrintInfo("")
1181 MiscUtil.PrintWarning("Failed to reimage frames: %s" % ErrMsg)
1182 MiscUtil.PrintInfo("")
1183 else:
1184 MiscUtil.PrintInfo("Skipping reimaging of frames...")
1185
1186 if RealignFrames:
1187 MiscUtil.PrintInfo('Realigning frames to the first frame using selection "%s"...' % Selection)
1188 try:
1189 SelectionAtomIndices = Traj.top.select(Selection)
1190 except Exception as ErrMsg:
1191 MiscUtil.PrintInfo("")
1192 MiscUtil.PrintWarning('Failed to align frames using selection "%s": %s' % (Selection, ErrMsg))
1193 MiscUtil.PrintInfo("")
1194 return (Traj, ReimagedStatus, RealignedStatus)
1195
1196 if SelectionAtomIndices.size == 0:
1197 MiscUtil.PrintInfo("")
1198 MiscUtil.PrintWarning('Failed to align frames using selection "%s": No matched atoms found' % (Selection))
1199 MiscUtil.PrintInfo("")
1200 return (Traj, ReimagedStatus, RealignedStatus)
1201
1202 RealignedStatus = True
1203 Traj.superpose(Traj, frame=0, atom_indices=SelectionAtomIndices)
1204 else:
1205 MiscUtil.PrintInfo("Skipping realignment of frames to the first frame...")
1206
1207 return (Traj, ReimagedStatus, RealignedStatus)
1208
1209
1210 def ValidateAndFreezeRestraintAtoms(
1211 FreezeAtomsStatus,
1212 FreezeAtomsParamsInfo,
1213 RestraintAtomsStatus,
1214 RestraintAtomsParamsInfo,
1215 RestraintSpringConstantInKcal,
1216 SystemParamsInfo,
1217 System,
1218 Topology,
1219 Positions,
1220 ):
1221 """Handle freezing and restraining of atoms along with validation of atoms
1222 to be frozen/restrained.
1223
1224 The FreezeAtomsParamsInfo and RestraintAtomsParamsInfo parameters are dictionaries
1225 of name and value pairs for system parameters and may be generated by calling the
1226 function named ProcessOptionOpenMMAtomsSelectionParameters().
1227
1228 The SystemParamsInfo parameter is a dictionary of name and value pairs for
1229 system parameters and may be generated by calling the function named
1230 ProcessOptionOpenMMSystemParameters().
1231
1232 Arguments:
1233 FreezeAtomsStatus (bool): Freeze atoms.
1234 FreezeAtomsParamsInfo (dict): Parameter name and value pairs.
1235 RestraintAtomsStatus (bool): Restraint atoms.
1236 RestraintAtomsParamsInfo (dict): Parameter name and value pairs.
1237 RestraintSpringConstantInKcal (float): Restraint spring constant.
1238 SystemParamsInfo (dict): Parameter name and value pairs.
1239 Topology (object): OpenMM topology object.
1240 Positions (object): OpenMM positions object.
1241
1242 Returns:
1243 None or List: OpenMM atom objects.
1244 None or List: OpenMM atom objects.
1245
1246 """
1247
1248 # Get atoms for freezing...
1249 FreezeAtomList = None
1250 if FreezeAtomsStatus:
1251 FreezeAtomList = GetAtoms(
1252 Topology,
1253 FreezeAtomsParamsInfo["CAlphaProteinStatus"],
1254 FreezeAtomsParamsInfo["ResidueNames"],
1255 FreezeAtomsParamsInfo["Negate"],
1256 )
1257 if FreezeAtomList is None:
1258 MiscUtil.PrintError(
1259 'The freeze atoms parameters specified, "selection, %s, selectionSpec, %s, negate, %s", using "--freezeAtomsParams" option didn\'t match any atoms in the system. You must specify a valid set of parameters for freezing atoms or disable freezing using "No" value for "--freezeAtoms" option..'
1260 % (
1261 FreezeAtomsParamsInfo["Selection"],
1262 FreezeAtomsParamsInfo["SelectionSpec"],
1263 FreezeAtomsParamsInfo["Negate"],
1264 )
1265 )
1266
1267 # Get atoms for restraining...
1268 RestraintAtomList = None
1269 if RestraintAtomsStatus:
1270 RestraintAtomList = GetAtoms(
1271 Topology,
1272 RestraintAtomsParamsInfo["CAlphaProteinStatus"],
1273 RestraintAtomsParamsInfo["ResidueNames"],
1274 RestraintAtomsParamsInfo["Negate"],
1275 )
1276 if RestraintAtomList is None:
1277 MiscUtil.PrintError(
1278 'The restraint atoms parameters specified, "selection, %s, selectionSpec, %s, negate, %s", using "--restraintAtomsParams" option didn\'t match any atoms in the system. You must specify a valid set of parameters for restraining atoms or disable restraining using "No" value for "--restraintAtoms" option.'
1279 % (
1280 RestraintAtomsParamsInfo["Selection"],
1281 RestraintAtomsParamsInfo["SelectionSpec"],
1282 RestraintAtomsParamsInfo["Negate"],
1283 )
1284 )
1285
1286 # Check for atoms to freeze or restraint...
1287 if FreezeAtomList is None and RestraintAtomList is None:
1288 return (FreezeAtomList, RestraintAtomList)
1289
1290 # Check for overlap between freeze and restraint atoms...
1291 if DoAtomListsOverlap(FreezeAtomList, RestraintAtomList):
1292 MiscUtil.PrintError(
1293 'The atoms specified using "--freezeAtomsParams" and "--restraintAtomsParams" options appear to overlap. You must specify unique sets of atoms to freeze and restraint.'
1294 )
1295
1296 # Check overlap of freeze atoms with system constraints...
1297 if DoesAtomListOverlapWithSystemConstraints(System, FreezeAtomList):
1298 MiscUtil.PrintError(
1299 'The atoms specified using "--freezeAtomsParams" appear to overlap with atoms being constrained corresponding to the value specified, %s, for paramater name "constraints" using "--systemParams" option.\n\nYou must specify a unique set of atoms to freeze or turn off system constaints by specifying value, None, for "constraints" parameter using option "--systemsParams".\n\nIn addtion, you may want specify, no, value for "rigidWater" option.\n\nThe atoms are frozen by setting their particle mass to zero. OpenMM doesn\'t allow to both constraint atoms and set their mass to zero.'
1300 % (SystemParamsInfo["Constraints"])
1301 )
1302
1303 # Check overlap of restraint atoms with system constraints...
1304 if DoesAtomListOverlapWithSystemConstraints(System, RestraintAtomList):
1305 MiscUtil.PrintInfo("")
1306 MiscUtil.PrintWarning(
1307 'The atoms specified using "--restraintAtomsParams" appear to overlap with atoms being constrained corresponding to the value specified, %s, for paramater name "constraints" using "--systemParams" option. You may want to specify a unique set of atoms to restraints or turn off system constaints by specifying value, None, for "constraints" parameter using option "--systemsParams".'
1308 % (SystemParamsInfo["Constraints"])
1309 )
1310
1311 # Freeze atoms...
1312 if FreezeAtomList is None:
1313 MiscUtil.PrintInfo("\nSkipping freezing of atoms...")
1314 else:
1315 MiscUtil.PrintInfo("\nFreezing atoms (Selection: %s)..." % FreezeAtomsParamsInfo["Selection"])
1316 FreezeAtoms(System, FreezeAtomList)
1317
1318 # Restraint atoms...
1319 if RestraintAtomList is None:
1320 MiscUtil.PrintInfo("\nSkipping restraining of atoms...")
1321 else:
1322 MiscUtil.PrintInfo("\nRestraining atoms (Selection: %s)..." % RestraintAtomsParamsInfo["Selection"])
1323 RestraintAtoms(System, Positions, RestraintAtomList, RestraintSpringConstantInKcal)
1324
1325 return (FreezeAtomList, RestraintAtomList)
1326
1327
1328 def FreezeAtoms(System, AtomList):
1329 """Freeze atoms during a simulation. The specified atoms are kept completely
1330 fixed by setting their masses to zero. Their positions do not change during
1331 local energy minimization and MD simulation, and they do not contribute
1332 to the kinetic energy of the system.
1333
1334 Arguments:
1335 System (object): OpenMM system object.
1336 AtomList (list): List of OpenMM atom objects.
1337
1338 Returns:
1339 None
1340
1341 """
1342
1343 if AtomList is None:
1344 return
1345
1346 for Atom in AtomList:
1347 System.setParticleMass(Atom.index, 0 * mm.unit.amu)
1348
1349
1350 def RestraintAtoms(System, Positions, AtomList, SpringConstantInKcal):
1351 """Restraint atoms during a simulation. The motion of specified atoms is
1352 restricted by adding a harmonic force that binds them to their starting
1353 positions. The atoms are not completely fixed unlike freezing of atoms.
1354 Their motion, however, is restricted and they are not able to move far away
1355 from their starting positions during local energy minimization and MD
1356 simulation.
1357
1358 The SpringConstantInKcal value must be specified in the units of
1359 kcal/mol/A*82. It is automatically converted into the units of
1360 kjoules/mol/nm**2 for OpenMM API call.
1361
1362 Arguments:
1363 System (object): OpenMM system object.
1364 Positions (object): OpenMM positons object object.
1365 AtomList (list): List of OpenMM atom object.
1366 SpringConstantInKcal (float): Spring constant value.
1367
1368 Returns:
1369 None
1370
1371 """
1372
1373 if AtomList is None:
1374 return
1375
1376 SpringConstant = SpringConstantInKcal * mm.unit.kilocalories_per_mole / mm.unit.angstroms**2
1377 SpringConstantInKjoules = SpringConstant.value_in_unit(mm.unit.kilojoules_per_mole / mm.unit.nanometer**2)
1378
1379 MiscUtil.PrintInfo(
1380 "Restraint spring constant: %.2f kcal/mol/A**2 (%.2f kjoules/mol/nm**2)"
1381 % (SpringConstantInKcal, SpringConstantInKjoules)
1382 )
1383
1384 if DoesSystemUsesPeriodicBoundaryConditions(System):
1385 # For periodic systems...
1386 RestraintForce = mm.CustomExternalForce("k*periodicdistance(x, y, z, x0, y0, z0)^2")
1387 else:
1388 # For non-periodic systems...
1389 RestraintForce = mm.CustomExternalForce("k*((x-x0)^2+(y-y0)^2+(z-z0)^2)")
1390
1391 SpringConstant = SpringConstantInKjoules * mm.unit.kilojoules_per_mole / mm.unit.nanometer**2
1392 RestraintForce.addGlobalParameter("k", SpringConstant)
1393
1394 RestraintForce.addPerParticleParameter("x0")
1395 RestraintForce.addPerParticleParameter("y0")
1396 RestraintForce.addPerParticleParameter("z0")
1397
1398 for Atom in AtomList:
1399 RestraintForce.addParticle(Atom.index, Positions[Atom.index])
1400
1401
1402 def GetAtoms(Topology, CAlphaProteinStatus, ResidueNames, Negate):
1403 """Get a list of atoms in the specified residue names. You may set
1404 CAlphaProteinStatus flag to True to only retrieve CAlpha atoms from
1405 the residues. In addition, you may negate residue name match using
1406 Negate flag.
1407
1408 Arguments:
1409 Topology (object): OpenMM topology object.
1410 CAlphaProteinStatus (bool): Get CAlpha atoms only.
1411 ResidueNames (list): List of residue names.
1412 Negate (bool): Negate residue name match.
1413
1414 Returns:
1415 None or List of OpenMM atom objects.
1416
1417 """
1418 AtomList = []
1419 for Chain in Topology.chains():
1420 for Residue in Chain.residues():
1421 if CAlphaProteinStatus:
1422 if Residue.name in ResidueNames:
1423 for Atom in Residue.atoms():
1424 if _MatchName(Atom.name, ["CA"], Negate):
1425 AtomList.append(Atom)
1426 else:
1427 if _MatchName(Residue.name, ResidueNames, Negate):
1428 AtomList.extend(Residue.atoms())
1429
1430 if len(AtomList) == 0:
1431 AtomList = None
1432
1433 return AtomList
1434
1435
1436 def _MatchName(Name, NamesList, Negate=False):
1437 """Match name to the names in a list."""
1438
1439 Status = True if Name in NamesList else False
1440 if Negate:
1441 Status = not Status
1442
1443 return Status
1444
1445
1446 def DoesSystemUsesPeriodicBoundaryConditions(System):
1447 """Check for the use of periodic boundary conditions in a system.
1448
1449 Arguments:
1450 System (object): OpenMM system object.
1451
1452 Returns:
1453 bool : True - Uses periodic boundary conditions; Otherwise, false.
1454
1455 """
1456
1457 try:
1458 Status = True if System.usesPeriodicBoundaryConditions() else False
1459 except Exception:
1460 Status = False
1461
1462 return Status
1463
1464
1465 def DoesAtomListOverlapWithSystemConstraints(System, AtomList):
1466 """Check for the overlap of specified atoms with the atoms involved
1467 in system constraints.
1468
1469 Arguments:
1470 System (object): OpenMM system object.
1471 AtomList (list): List of OpenMM atom objects.
1472
1473 Returns:
1474 bool : True - Overlap with system constraints; Otherwise, false.
1475
1476 """
1477
1478 NumConstraints = System.getNumConstraints()
1479 if NumConstraints == 0:
1480 return False
1481
1482 if AtomList is None:
1483 return False
1484
1485 AtomListIndices = [Atom.index for Atom in AtomList]
1486
1487 for Index in range(NumConstraints):
1488 Particle1Index, Particle2Index, Distance = System.getConstraintParameters(Index)
1489 if Particle1Index in AtomListIndices or Particle2Index in AtomListIndices:
1490 return True
1491
1492 return False
1493
1494
1495 def DoAtomListsOverlap(AtomList1, AtomList2):
1496 """Check for the overlap of atoms in the specified atom lists.
1497
1498 Arguments:
1499 AtomList1 (list): List of OpenMM atom objects.
1500 AtomList2 (list): List of OpenMM atom objects.
1501
1502 Returns:
1503 bool : True - Overlap between atoms lists; Otherwise, false.
1504
1505 """
1506
1507 if AtomList1 is None or AtomList2 is None:
1508 return False
1509
1510 AtomList1Indices = [Atom.index for Atom in AtomList1]
1511
1512 for Atom in AtomList2:
1513 if Atom.index in AtomList1Indices:
1514 return True
1515
1516 return False
1517
1518
1519 def DoesSystemContainWater(Topology, WaterResidueNames=["HOH"]):
1520 """Check for the presence of water residues in a system.
1521
1522 Arguments:
1523 Topology (object): OpenMM modeller topology object.
1524 WaterResidueNames (list): List of water residue names.
1525
1526 Returns:
1527 bool : True - Contains water; Otherwise, false.
1528
1529 """
1530
1531 Status = False
1532 for Residue in Topology.residues():
1533 if Residue.name in WaterResidueNames:
1534 Status = True
1535 break
1536
1537 return Status
1538
1539
1540 def FixColumNamesLineInDataLogFile(DataLogFile):
1541 """Fix column name line in data log file by removing the # character
1542 written by OpenMM at the start of the first line.
1543
1544 Arguments:
1545 DataLogFile (str): Data log file name.
1546
1547 Returns:
1548 None
1549
1550 """
1551
1552 # Remove the "#" character written out by OpenMM at the start of the first
1553 # line corresponding to column names...
1554 #
1555
1556 FileDir, FileRoot, FileExt = MiscUtil.ParseFileName(DataLogFile)
1557 TmpDataLogFile = "Tmp%s_PID%s.%s" % (FileRoot, os.getpid(), FileExt)
1558
1559 DataLogFH = open(DataLogFile, "r")
1560 TmpDataLogFH = open(TmpDataLogFile, "w")
1561
1562 FirstLine = True
1563 for Line in DataLogFH:
1564 if FirstLine:
1565 FirstLine = False
1566 if re.match(r"^\#", Line, re.I):
1567 Line = re.sub(r"^\#", "", Line)
1568 TmpDataLogFH.write(Line)
1569
1570 DataLogFH.close()
1571 TmpDataLogFH.close()
1572
1573 shutil.move(TmpDataLogFile, DataLogFile)
1574
1575
1576 def MapDataOutTypePlotToDataLogColumnNames(DataOutTypePlotList, DataLogColNames):
1577 """Map data out type to be plotted to column names in data log file.
1578
1579 Arguments:
1580 DataOutTypePlotList (list): List of data out types.
1581 DataLogColNames (list): List of data log file column names.
1582
1583 Returns:
1584 dict: Data out type and column name value pairs.
1585
1586 """
1587
1588 DataOutTypePlotColNames = {}
1589 for DataType in DataOutTypePlotList:
1590 DataTypeColName = None
1591 for ColName in DataLogColNames:
1592 MatchDataType = DataType
1593 if re.search("Energy", MatchDataType, re.I):
1594 MatchDataType = re.sub("Energy", " Energy", MatchDataType)
1595
1596 if re.search(MatchDataType, ColName, re.I):
1597 DataTypeColName = ColName
1598 break
1599
1600 DataOutTypePlotColNames[DataType] = DataTypeColName
1601
1602 return DataOutTypePlotColNames
1603
1604
1605 def ReadPDBFile(PDBFile):
1606 """Read molecule from a PDB file.
1607
1608 The supported PDB file formats are pdb and cif.
1609
1610 Arguments:
1611 PDBFile (str): Name of PDB file.
1612
1613 Returns:
1614 object: OpenMM PDBFile or PDBFilex object.
1615
1616 """
1617
1618 FileDir, FileName, FileExt = MiscUtil.ParseFileName(PDBFile)
1619 if re.match("^pdb$", FileExt, re.I):
1620 PDBHandle = mm.app.PDBFile(PDBFile)
1621 elif re.match("^cif$", FileExt, re.I):
1622 PDBHandle = mm.app.PDBxFile(PDBFile)
1623 else:
1624 MiscUtil.PrintError("Failed to read PDB file. Invalid PDB file format %s...\n" % PDBFile)
1625
1626 return PDBHandle
1627
1628
1629 def WritePDBFile(PDBFile, Topology, Positions, KeepIDs=True):
1630 """Write a PDB file.
1631
1632 The supported PDB file formats are pdb and cif.
1633
1634 Arguments:
1635 PDBFile (str): Name of PDB file.
1636 Topology (object): Topology OpenMM object.
1637 Positions (object): Positions OpenMM object.
1638 KeepIDs (bool): Keep existing residue and chain IDs.
1639
1640 Returns:
1641 None
1642
1643 """
1644
1645 FileDir, FileName, FileExt = MiscUtil.ParseFileName(PDBFile)
1646 if re.match("^pdb$", FileExt, re.I):
1647 mm.app.PDBFile.writeFile(Topology, Positions, PDBFile, KeepIDs)
1648 elif re.match("^cif$", FileExt, re.I):
1649 mm.app.PDBxFile.writeFile(Topology, Positions, PDBFile, KeepIDs)
1650 else:
1651 MiscUtil.PrintError("Failed to write PDB file. Invalid PDB file format %s...\n" % PDBFile)
1652
1653
1654 def WriteSimulationStatePDBFile(Simulation, PDBFile, KeepIDs=True):
1655 """Write a PDB file for current simulation state.
1656
1657 The supported PDB file formats are pdb and cif.
1658
1659 Arguments:
1660 Simulation (object): OpenMM simulation object.
1661 PDBFile (str): Name of PDB fil.
1662 KeepIDs (bool): Keep existing residue and chain IDs.
1663
1664 Returns:
1665 None
1666
1667 """
1668
1669 CurrentPositions = Simulation.context.getState(getPositions=True).getPositions()
1670 WritePDBFile(PDBFile, Simulation.topology, CurrentPositions, KeepIDs)
1671
1672
1673 def ReadSmallMoleculeFile(FileName):
1674 """Read small molecule file using OpenFF toolkit.
1675
1676 Arguments:
1677 FileName (str): Small molecule file name.
1678
1679 Returns:
1680 None or OpenFF tookit molecule object.
1681
1682 """
1683
1684 try:
1685 SmallMol = ff.toolkit.Molecule.from_file(FileName)
1686 except Exception as ErrMsg:
1687 SmallMol = None
1688 MiscUtil.PrintInfo("")
1689 MiscUtil.PrintWarning("OpenFF.toolkit.Molecule.from_file() failed: %s" % ErrMsg)
1690 MiscUtil.PrintInfo("")
1691
1692 return SmallMol
1693
1694
1695 def MergeSmallMoleculeWithMacromolecule(ModellerHandle, SmallMol, SmallMolID="LIG"):
1696 """Merge small molecule with macromolecule data contained in a modeller object and
1697 assign a three letter small molecule residue name to the merged small molecule.
1698
1699 Arguments:
1700 ModellerHandle (object): OpenMM modeller object.
1701 SmallMol (object): OpenFF tookit molecule object.
1702 SmallMolID (str): Three letter residue name for small molecule.
1703
1704 Returns:
1705 None
1706
1707 """
1708
1709 SmallMolToplogy = SmallMol.to_topology()
1710 SmallMolOpenMMTopology = SmallMolToplogy.to_openmm()
1711 SmallMolOpenMMPositions = SmallMolToplogy.get_positions().to_openmm()
1712
1713 # Set small molecule residue name to LIG...
1714 for Chain in SmallMolOpenMMTopology.chains():
1715 for Residue in Chain.residues():
1716 Residue.name = SmallMolID
1717
1718 ModellerHandle.add(SmallMolOpenMMTopology, SmallMolOpenMMPositions)
1719
1720
1721 def GetFormattedTotalSimulationTime(StepSize, Steps):
1722 """Get formatted total simulation time with appropriate time units.
1723 parameter names and values.
1724
1725 Arguments:
1726 StepSize (object): OpenMM quantity object.
1727 Steps (int): Number of steps.
1728
1729 Returns:
1730 str: Total time.
1731
1732 """
1733
1734 TotalTime = StepSize * Steps
1735 TotalTimeValue = TotalTime.value_in_unit(mm.unit.femtoseconds)
1736
1737 if TotalTimeValue < 1e3:
1738 TotalTimeUnits = "fs"
1739 TotalTime = TotalTime.value_in_unit(mm.unit.femtoseconds)
1740 elif TotalTimeValue < 1e6:
1741 TotalTimeUnits = "ps"
1742 TotalTime = TotalTime.value_in_unit(mm.unit.picoseconds)
1743 elif TotalTimeValue < 1e9:
1744 TotalTimeUnits = "ns"
1745 TotalTime = TotalTime.value_in_unit(mm.unit.nanoseconds)
1746 elif TotalTimeValue < 1e12:
1747 TotalTimeUnits = "us"
1748 TotalTime = TotalTime.value_in_unit(mm.unit.microseconds)
1749 else:
1750 TotalTimeUnits = "ms"
1751 TotalTime = TotalTime.value_in_unit(mm.unit.milliseconds)
1752
1753 TotalTime = "%.2f %s" % (TotalTime, TotalTimeUnits)
1754
1755 return TotalTime
1756
1757
1758 def ProcessOptionOpenMMRestartParameters(ParamsOptionName, ParamsOptionValue, OutfilePrefix, ParamsDefaultInfo=None):
1759 """Process parameters for restart option and return a map containing processed
1760 parameter names and values.
1761
1762 ParamsOptionValue is a comma delimited list of parameter name and value pairs
1763 to setup platform.
1764
1765 The supported parameter names along with their default and possible
1766 values are shown below:
1767
1768 finalStateFile, <OutfilePrefix>_FinalState.<chk> [ Possible values:
1769 Valid final state checkpoint or XML filename ]
1770 dataAppend, yes [ Possible values: yes or no]
1771
1772 A brief description of parameters is provided below:
1773
1774 finalStateFile: Final state checkpoint or XML file
1775
1776 dataAppend: Append data to existing trajectory and data log files during the
1777 restart of a simulation using a previously saved final state checkpoint or
1778 XML file.
1779
1780 Arguments:
1781 ParamsOptionName (str): Command line OpenMM restart option name.
1782 ParamsOptionValues (str): Space delimited list of parameter name and value pairs.
1783 OutfilePrefix (str): Prefix for output files.
1784 ParamsDefaultInfo (dict): Default values to override for selected parameters.
1785
1786 Returns:
1787 dictionary: Processed parameter name and value pairs.
1788
1789 """
1790
1791 ParamsInfo = {"FinalStateFile": "auto", "DataAppend": True}
1792
1793 (ValidParamNames, CanonicalParamNamesMap, ParamsOptionValue, ParamsOptionValueWords) = (
1794 _ValidateAndCanonicalizeParameterNames(ParamsOptionName, ParamsOptionValue, ParamsInfo, ParamsDefaultInfo)
1795 )
1796
1797 if re.match("^auto$", ParamsOptionValue, re.I):
1798 _ProcessOptionOpenMMRestartParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue, OutfilePrefix)
1799 return ParamsInfo
1800
1801 for Index in range(0, len(ParamsOptionValueWords), 2):
1802 Name = ParamsOptionValueWords[Index].strip()
1803 Value = ParamsOptionValueWords[Index + 1].strip()
1804
1805 ParamName = CanonicalParamNamesMap[Name.lower()]
1806 ParamValue = Value
1807
1808 if re.match("^FinalStateFile$", ParamName, re.I):
1809 if not re.match("^auto$", Value, re.I):
1810 if not os.path.exists(Value):
1811 MiscUtil.PrintError(
1812 'The file name specified, %s, for parameter name, %s, using option "%s" doesn\'t exist.\n.'
1813 % (Value, Name, ParamsOptionName)
1814 )
1815 if not MiscUtil.CheckFileExt(Value, "chk xml"):
1816 MiscUtil.PrintError(
1817 'The file name specified, %s, for parameter name, %s, using option "%s" is not valid file. Supported file formats: chk or xml\n.'
1818 % (Value, Name, ParamsOptionName)
1819 )
1820 ParamValue = Value
1821 elif re.match("^DataAppend$", ParamName, re.I):
1822 if not re.match("^(yes|no|true|false)$", Value, re.I):
1823 MiscUtil.PrintError(
1824 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. Supported values: yes or no'
1825 % (Value, Name, ParamsOptionName)
1826 )
1827 ParamValue = True if re.match("^(yes|true)$", Value, re.I) else False
1828 else:
1829 ParamValue = Value
1830
1831 # Set value...
1832 ParamsInfo[ParamName] = ParamValue
1833
1834 # Handle parameters with possible auto values...
1835 _ProcessOptionOpenMMRestartParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue, OutfilePrefix)
1836
1837 return ParamsInfo
1838
1839
1840 def _ProcessOptionOpenMMRestartParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue, OutfilePrefix):
1841 """Process parameters with possible auto values and perform validation."""
1842
1843 FinalStateFileCheckpointMode = False
1844 FinalStateFileXMLMode = False
1845
1846 ParamName = "FinalStateFile"
1847 FinalStateFile = ParamsInfo[ParamName]
1848 if re.match("^auto$", FinalStateFile, re.I):
1849 FinalStateFile = "%s_FinalState.chk" % OutfilePrefix
1850 FinalStateFileCheckpointMode = True
1851 else:
1852 if MiscUtil.CheckFileExt(FinalStateFile, "chk"):
1853 FinalStateFileCheckpointMode = True
1854 elif MiscUtil.CheckFileExt(FinalStateFile, "xml"):
1855 FinalStateFileXMLMode = True
1856 else:
1857 MiscUtil.PrintError(
1858 'The file name specified, %s, for parameter name, %s, using option "%s" is not valid. Supported file formats: chk or xml\n.'
1859 % (FinalStateFile, ParamName, ParamsOptionName)
1860 )
1861
1862 ParamsInfo["FinalStateFile"] = FinalStateFile
1863 ParamsInfo["FinalStateFileCheckpointMode"] = FinalStateFileCheckpointMode
1864 ParamsInfo["FinalStateFileXMLMode"] = FinalStateFileXMLMode
1865
1866
1867 def ProcessOptionOpenMMSystemParameters(ParamsOptionName, ParamsOptionValue, ParamsDefaultInfo=None):
1868 """Process parameters for system option and return a map containing processed
1869 parameter names and values.
1870
1871 ParamsOptionValue is a comma delimited list of parameter name and value pairs
1872 to setup platform.
1873
1874 The supported parameter names along with their default and possible
1875 values are shown below:
1876
1877 constraints, BondsInvolvingHydrogens [ Possible values: None,
1878 WaterOnly, BondsInvolvingHydrogens, AllBonds, or
1879 AnglesInvolvingHydrogens ]
1880 constraintErrorTolerance, 0.000001
1881 ewaldErrorTolerance, 0.0005
1882
1883 nonbondedMethodPeriodic, PME [ Possible values: NoCutoff,
1884 CutoffNonPeriodic, or PME ]
1885 nonbondedMethodNonPeriodic, NoCutoff [ Possible values:
1886 NoCutoff or CutoffNonPeriodic]
1887 nonbondedCutoff, 1.0 [ Units: nm ]
1888
1889 hydrogenMassRepartioning, yes [ Possible values: yes or no ]
1890 hydrogenMass, 1.5 [ Units: amu]
1891
1892 removeCMMotion, yes [ Possible values: yes or no ]
1893 rigidWater, auto [ Possible values: yes or no. Default: 'No' for
1894 'None' value of constraints; Otherwise, yes ]
1895
1896 A brief description of parameters is provided below:
1897
1898 constraints: Type of system constraints to use for simulation. These constraints
1899 are different from freezing and restraining of any atoms in the system.
1900
1901 constraintErrorTolerance: Distance tolerance for constraints as a fraction
1902 of the constrained distance.
1903
1904 ewaldErrorTolerance: Ewald error tolerance for a periodic system.
1905
1906 nonbondedMethodPeriodic: Nonbonded method to use during the calculation of
1907 long range interactions for a periodic system.
1908
1909 nonbondedMethodNonPeriodic: Nonbonded method to use during the calculation
1910 of long range interactions for a non-periodic system.
1911
1912 nonbondedCutoff: Cutoff distance to use for long range interactions in both
1913 perioidic non-periodic systems.
1914
1915 hydrogenMassRepartioning: Use hydrogen mass repartioning. It increases the
1916 mass of the hydrogen atoms attached to the heavy atoms and decreasing the
1917 mass of the bonded heavy atom to maintain constant system mass. This allows
1918 the use of larger integration step size (4 fs) during a simulation.
1919
1920 hydrogenMass: Hydrogen mass to use during repartioning.
1921
1922 removeCMMotion: Remove all center of mass motion at every time step.
1923
1924 rigidWater: Keep water rigid during a simulation. This is determined
1925 automatically based on the value of 'constraints' parameter.
1926
1927 Arguments:
1928 ParamsOptionName (str): Command line OpenMM system option name.
1929 ParamsOptionValues (str): Space delimited list of parameter name and value pairs.
1930 ParamsDefaultInfo (dict): Default values to override for selected parameters.
1931
1932 Returns:
1933 dictionary: Processed parameter name and value pairs.
1934
1935 """
1936
1937 ParamsInfo = {
1938 "Constraints": "BondsInvolvingHydrogens",
1939 "ConstraintErrorTolerance": 0.000001,
1940 "EwaldErrorTolerance": 0.0005,
1941 "NonbondedMethodPeriodic": "PME",
1942 "NonbondedMethodNonPeriodic": "NoCutoff",
1943 "NonbondedCutoff": 1.0,
1944 "HydrogenMassRepartioning": True,
1945 "HydrogenMass": 1.5,
1946 "RemoveCMMotion": True,
1947 "RigidWater": "auto",
1948 }
1949
1950 (ValidParamNames, CanonicalParamNamesMap, ParamsOptionValue, ParamsOptionValueWords) = (
1951 _ValidateAndCanonicalizeParameterNames(ParamsOptionName, ParamsOptionValue, ParamsInfo, ParamsDefaultInfo)
1952 )
1953
1954 if re.match("^auto$", ParamsOptionValue, re.I):
1955 _ProcessOptionOpenMMSystemParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue)
1956 return ParamsInfo
1957
1958 for Index in range(0, len(ParamsOptionValueWords), 2):
1959 Name = ParamsOptionValueWords[Index].strip()
1960 Value = ParamsOptionValueWords[Index + 1].strip()
1961
1962 ParamName = CanonicalParamNamesMap[Name.lower()]
1963 ParamValue = Value
1964
1965 if re.match("^Constraints$", ParamName, re.I):
1966 if not re.match("^auto$", Value, re.I):
1967 if not re.match(
1968 "^(None|WaterOnly|BondsInvolvingHydrogens|AllBonds|AnglesInvolvingHydrogens)$", Value, re.I
1969 ):
1970 MiscUtil.PrintError(
1971 '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.'
1972 % (Value, Name, ParamsOptionName)
1973 )
1974 ParamValue = Value
1975 elif re.match("^(ConstraintErrorTolerance|EwaldErrorTolerance|NonbondedCutoff|HydrogenMass)$", ParamName, re.I):
1976 if not MiscUtil.IsFloat(Value):
1977 MiscUtil.PrintError(
1978 'The parameter value, %s, specified for parameter name, %s, using "%s" option must be a float.\n'
1979 % (Value, ParamName, ParamsOptionName)
1980 )
1981 Value = float(Value)
1982 if Value <= 0:
1983 MiscUtil.PrintError(
1984 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. Supported values: > 0\n'
1985 % (ParamValue, ParamName, ParamsOptionName)
1986 )
1987 ParamValue = Value
1988 elif re.match("^NonbondedMethodPeriodic$", ParamName, re.I):
1989 if not re.match("^(NoCutoff|CutoffPeriodic|PME)$", Value, re.I):
1990 MiscUtil.PrintError(
1991 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. Supported values: NoCutoff, CutoffPeriodic, or PME'
1992 % (Value, Name, ParamsOptionName)
1993 )
1994 ParamValue = Value
1995 elif re.match("^NonbondedMethodNonPeriodic$", ParamName, re.I):
1996 if not re.match("^(NoCutoff|CutoffNonPeriodic)$", Value, re.I):
1997 MiscUtil.PrintError(
1998 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. Supported values: NoCutoff or CutoffNonPeriodic'
1999 % (Value, Name, ParamsOptionName)
2000 )
2001 ParamValue = Value
2002 elif re.match("^(HydrogenMassRepartioning|removeCMMotion)$", ParamName, re.I):
2003 if not re.match("^(yes|no|true|false)$", Value, re.I):
2004 MiscUtil.PrintError(
2005 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. Supported values: yes or no'
2006 % (Value, Name, ParamsOptionName)
2007 )
2008 ParamValue = True if re.match("^(yes|true)$", Value, re.I) else False
2009 elif re.match("^RigidWater$", ParamName, re.I):
2010 if not re.match("^auto$", Value, re.I):
2011 if not re.match("^(yes|no|true|false)$", Value, re.I):
2012 MiscUtil.PrintError(
2013 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. Supported values: yes or no'
2014 % (Value, Name, ParamsOptionName)
2015 )
2016 ParamValue = True if re.match("^(yes|true)$", Value, re.I) else False
2017 else:
2018 ParamValue = Value
2019
2020 # Set value...
2021 ParamsInfo[ParamName] = ParamValue
2022
2023 # Handle parameters with possible auto values...
2024 _ProcessOptionOpenMMSystemParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue)
2025
2026 return ParamsInfo
2027
2028
2029 def _ProcessOptionOpenMMSystemParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue):
2030 """Process parameters with possible auto values and perform validation."""
2031
2032 for ParamName in ["NonbondedMethodPeriodic", "NonbondedMethodNonPeriodic"]:
2033 ParamValue = ParamsInfo[ParamName]
2034 if re.match("^NoCutoff$", ParamValue, re.I):
2035 ParamValue = mm.app.NoCutoff
2036 elif re.match("^CutoffNonPeriodic$", ParamValue, re.I):
2037 ParamValue = mm.app.CutoffNonPeriodic
2038 elif re.match("^CutoffPeriodic$", ParamValue, re.I):
2039 ParamValue = mm.app.CutoffPeriodic
2040 elif re.match("^PME$", ParamValue, re.I):
2041 ParamValue = mm.app.PME
2042 else:
2043 MiscUtil.PrintError(
2044 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. Supported values: NoCutoff, CutoffNonPeriodic, CutoffPeriodic, or PME'
2045 % (ParamValue, ParamName, ParamsOptionName)
2046 )
2047 ParamsInfo[ParamName] = ParamValue
2048
2049 ParamName = "Constraints"
2050 ParamValue = ParamsInfo[ParamName]
2051 ConstraintsValue = None
2052 RigidWaterValue = False
2053 if re.match("^None$", ParamValue, re.I):
2054 ConstraintsValue = None
2055 RigidWaterValue = False
2056 elif re.match("^WaterOnly$", ParamValue, re.I):
2057 ConstraintsValue = None
2058 RigidWaterValue = True
2059 elif re.match("^BondsInvolvingHydrogens$", ParamValue, re.I):
2060 ConstraintsValue = mm.app.HBonds
2061 RigidWaterValue = True
2062 elif re.match("^AllBonds$", ParamValue, re.I):
2063 ConstraintsValue = mm.app.AllBonds
2064 RigidWaterValue = True
2065 elif re.match("^AnglesInvolvingHydrogens$", ParamValue, re.I):
2066 ConstraintsValue = mm.app.HAngles
2067 RigidWaterValue = True
2068 else:
2069 MiscUtil.PrintError(
2070 '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.'
2071 % (ParamValue, ParamName, ParamsOptionName)
2072 )
2073
2074 ParamsInfo[ParamName] = ConstraintsValue
2075
2076 ParamName = "RigidWater"
2077 ParamValue = "%s" % ParamsInfo[ParamName]
2078 if re.match("^auto$", ParamValue, re.I):
2079 ParamsInfo[ParamName] = RigidWaterValue
2080
2081
2082 def ProcessOptionOpenMMIntegratorParameters(
2083 ParamsOptionName, ParamsOptionValue, ParamsDefaultInfo=None, HydrogenMassRepartioningStatus=False
2084 ):
2085 """Process parameters for integrator option and return a map containing processed
2086 parameter names and values.
2087
2088 ParamsOptionValue is a comma delimited list of parameter name and value pairs
2089 to setup platform.
2090
2091 The supported parameter names along with their default and possible
2092 values are shown below:
2093
2094 integrator, LangevinMiddle [ Possible values: LangevinMiddle,
2095 Langevin, NoseHoover, Brownian ]
2096
2097 randomSeed, auto [ Possible values: > 0 ]
2098
2099 frictionCoefficient, 1.0 [ Units: 1/ps ]
2100 stepSize, auto [ Units: fs; Default value: 4 fs during yes value of
2101 hydrogen mass repartioning with no freezing/restraining of atoms;
2102 otherwsie, 2 fs ]
2103 temperature, 300.0 [ Units: kelvin ]
2104
2105 barostat, MonteCarlo [ Possible values: MonteCarlo or
2106 MonteCarloMembrane ]
2107 barostatInterval, 25
2108 pressure, 1.0 [ Units: atm ]
2109
2110 Parameters used only for MonteCarloMembraneBarostat with default
2111 values corresponding to Amber forcefields:
2112
2113 surfaceTension, 0.0 [ Units: atm*A. It is automatically converted
2114 into OpenMM default units of atm*nm before its usage. ]
2115 xymode, Isotropic [ Possible values: Anisotropic or Isotropic ]
2116 zmode, Free [ Possible values: Free or Fixed ]
2117
2118 A brief description of parameters is provided below:
2119
2120 integrator: Type of integrator
2121
2122 randomSeed: Random number seed for barostat and integrator. Not supported
2123 NoseHoover integrator.
2124
2125 frictionCoefficient: Friction coefficient for coupling the system to the heat
2126 bath.
2127
2128 stepSize: Simulation time step size.
2129
2130 temperature: Simulation temperature.
2131
2132 barostat: Barostat type.
2133
2134 barostatInterval: Barostat interval step size, in terms of time step size,
2135 for applying Monte Carlo pressure changes during NPT simulation.
2136
2137 pressure: Pressure during NPT simulation.
2138
2139 surfaceTension: Surface tension acting on the system.
2140
2141 xymode: Behavior along X and Y axes. You may allow the X and Y axes
2142 to vary independently of each other or always scale them by the same
2143 amount to keep the ratio of their lengths constant.
2144
2145 zmode: Beahvior along Z axis. You may allow the Z axis to vary
2146 independently of the other axes or keep it fixed.
2147
2148 Arguments:
2149 ParamsOptionName (str): Command line OpenMM integrator option name.
2150 ParamsOptionValues (str): Space delimited list of parameter name and value pairs.
2151 ParamsDefaultInfo (dict): Default values to override for selected parameters.
2152
2153 Returns:
2154 dictionary: Processed parameter name and value pairs.
2155
2156 """
2157
2158 ParamsInfo = {
2159 "Integrator": "LangevinMiddle",
2160 "RandomSeed": "auto",
2161 "FrictionCoefficient": 1.0,
2162 "StepSize": "auto",
2163 "Temperature": 300.0,
2164 "Barostat": "MonteCarlo",
2165 "BarostatInterval": 25,
2166 "Pressure": 1.0,
2167 "SurfaceTension": 0.0,
2168 "XYMode": "Isotropic",
2169 "ZMode": "Free",
2170 }
2171
2172 (ValidParamNames, CanonicalParamNamesMap, ParamsOptionValue, ParamsOptionValueWords) = (
2173 _ValidateAndCanonicalizeParameterNames(ParamsOptionName, ParamsOptionValue, ParamsInfo, ParamsDefaultInfo)
2174 )
2175
2176 if re.match("^auto$", ParamsOptionValue, re.I):
2177 _ProcessOptionOpenMMIntegratorParameters(
2178 ParamsInfo, ParamsOptionName, ParamsOptionValue, HydrogenMassRepartioningStatus
2179 )
2180 return ParamsInfo
2181
2182 for Index in range(0, len(ParamsOptionValueWords), 2):
2183 Name = ParamsOptionValueWords[Index].strip()
2184 Value = ParamsOptionValueWords[Index + 1].strip()
2185
2186 ParamName = CanonicalParamNamesMap[Name.lower()]
2187 ParamValue = Value
2188
2189 if re.match("^Integrator$", ParamName, re.I):
2190 if not re.match("^(LangevinMiddle|Langevin|NoseHoover|Brownian)$", Value, re.I):
2191 MiscUtil.PrintError(
2192 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. Supported values: LangevinMiddle,Langevin, NoseHoover, or Brownian.'
2193 % (Value, Name, ParamsOptionName)
2194 )
2195 ParamValue = Value
2196 elif re.match("^(FrictionCoefficient|Pressure)$", ParamName, re.I):
2197 if not MiscUtil.IsFloat(Value):
2198 MiscUtil.PrintError(
2199 'The parameter value, %s, specified for parameter name, %s, using "%s" option must be a float.\n'
2200 % (Value, ParamName, ParamsOptionName)
2201 )
2202 Value = float(Value)
2203 if Value <= 0:
2204 MiscUtil.PrintError(
2205 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. Supported values: > 0\n'
2206 % (ParamValue, ParamName, ParamsOptionName)
2207 )
2208 ParamValue = Value
2209 elif re.match("^StepSize$", ParamName, re.I):
2210 if not re.match("^auto$", Value, re.I):
2211 if not MiscUtil.IsFloat(Value):
2212 MiscUtil.PrintError(
2213 'The parameter value, %s, specified for parameter name, %s, using "%s" option must be a float.\n'
2214 % (Value, ParamName, ParamsOptionName)
2215 )
2216 Value = float(Value)
2217 if Value <= 0:
2218 MiscUtil.PrintError(
2219 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. Supported values: > 0\n'
2220 % (ParamValue, ParamName, ParamsOptionName)
2221 )
2222 ParamValue = Value
2223 elif re.match("^(Temperature|SurfaceTension)$", ParamName, re.I):
2224 if not MiscUtil.IsFloat(Value):
2225 MiscUtil.PrintError(
2226 'The parameter value, %s, specified for parameter name, %s, using "%s" option must be a float.\n'
2227 % (Value, ParamName, ParamsOptionName)
2228 )
2229 Value = float(Value)
2230 if Value < 0:
2231 MiscUtil.PrintError(
2232 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. Supported values: >= 0\n'
2233 % (ParamValue, ParamName, ParamsOptionName)
2234 )
2235 ParamValue = Value
2236 elif re.match("^BarostatInterval$", ParamName, re.I):
2237 if not MiscUtil.IsInteger(Value):
2238 MiscUtil.PrintError(
2239 'The parameter value, %s, specified for parameter name, %s, using "%s" option must be an integer.\n'
2240 % (Value, ParamName, ParamsOptionName)
2241 )
2242 Value = int(Value)
2243 if Value <= 0:
2244 MiscUtil.PrintError(
2245 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. Supported values: > 0\n'
2246 % (ParamValue, ParamName, ParamsOptionName)
2247 )
2248 ParamValue = Value
2249 elif re.match("^Barostat$", ParamName, re.I):
2250 if not re.match("^(MonteCarlo|MonteCarloMembrane)$", Value, re.I):
2251 MiscUtil.PrintError(
2252 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. Supported values: MonteCarlo or MonteCarloMembrane'
2253 % (Value, Name, ParamsOptionName)
2254 )
2255 ParamValue = Value
2256 elif re.match("^XYMode$", ParamName, re.I):
2257 if not re.match("^(Anisotropic|Isotropic)$", Value, re.I):
2258 MiscUtil.PrintError(
2259 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. Supported values: Anisotropic or Isotropic'
2260 % (Value, Name, ParamsOptionName)
2261 )
2262 ParamValue = Value
2263 elif re.match("^ZMode$", ParamName, re.I):
2264 if not re.match("^(Free|Fixed)$", Value, re.I):
2265 MiscUtil.PrintError(
2266 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. Supported values: Fixed or Free'
2267 % (Value, Name, ParamsOptionName)
2268 )
2269 ParamValue = Value
2270 elif re.match("^RandomSeed$", ParamName, re.I):
2271 if not re.match("^auto$", Value, re.I):
2272 if not MiscUtil.IsInteger(Value):
2273 MiscUtil.PrintError(
2274 'The parameter value, %s, specified for parameter name, %s, using "%s" option must be an integer.\n'
2275 % (Value, ParamName, ParamsOptionName)
2276 )
2277 Value = int(Value)
2278 if Value <= 0:
2279 MiscUtil.PrintError(
2280 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. Supported values: > 0\n'
2281 % (ParamValue, ParamName, ParamsOptionName)
2282 )
2283 ParamValue = Value
2284 else:
2285 ParamValue = Value
2286
2287 # Set value...
2288 ParamsInfo[ParamName] = ParamValue
2289
2290 # Handle parameters with possible auto values...
2291 _ProcessOptionOpenMMIntegratorParameters(
2292 ParamsInfo, ParamsOptionName, ParamsOptionValue, HydrogenMassRepartioningStatus
2293 )
2294
2295 return ParamsInfo
2296
2297
2298 def _ProcessOptionOpenMMIntegratorParameters(
2299 ParamsInfo, ParamsOptionName, ParamsOptionValue, HydrogenMassRepartioningStatus
2300 ):
2301 """Process parameters with possible auto values and perform validation."""
2302
2303 ParamName = "StepSize"
2304 ParamValue = "%s" % ParamsInfo[ParamName]
2305 ParamsInfo["StepSizeSpecified"] = ParamValue
2306 if re.match("^auto$", ParamValue, re.I):
2307 ParamValue = 4.0 if HydrogenMassRepartioningStatus else 2.0
2308 ParamsInfo[ParamName] = ParamValue
2309
2310 ParamName = "RandomSeed"
2311 ParamValue = "%s" % ParamsInfo[ParamName]
2312 ParamsInfo["RandomSeedSpecified"] = ParamValue
2313 if re.match("^auto$", ParamValue, re.I):
2314 ParamsInfo[ParamName] = None
2315
2316
2317 def ProcessOptionOpenMMSimulationParameters(ParamsOptionName, ParamsOptionValue, ParamsDefaultInfo=None):
2318 """Process parameters for simulation option and return a map containing processed
2319 parameter names and values.
2320
2321 ParamsOptionValue is a comma delimited list of parameter name and value pairs
2322 to setup platform.
2323
2324 The supported parameter names along with their default and possible
2325 values are shown below:
2326
2327 steps, 1000000 [ Possible values: > 0 ]
2328
2329 minimization, yes [ Possible values: yes or no ]
2330 minimizationMaxSteps, auto [ Possible values: >= 0. The value of
2331 zero implies until the minimization is converged. ]
2332 minimizationTolerance, 0.24 [ Units: kcal/mol/A. The default value
2333 0.24, corresponds to OpenMM default of value of 10.04
2334 kjoules/mol/nm. It is automatically converted into OpenMM
2335 default units before its usage. ]
2336
2337 equilibration, yes [ Possible values: yes or no ]
2338 equilibrationSteps, 1000 [ Possible values: > 0 ]
2339
2340 A brief description of parameters is provided below:
2341
2342 steps: Number of steps for production run.
2343
2344 equilibration: Perform equilibration before the production run.
2345
2346 equilibrationSteps: Number of steps for equilibration.
2347
2348 minimizationMaxSteps: Maximum number of minimization steps. The value
2349 of zero implies until the minimization is converged.
2350
2351 minimizationTolerance: Energy convergence tolerance during minimization.
2352
2353 minimization: Perform minimization before equilibration and production run.
2354
2355 Arguments:
2356 ParamsOptionName (str): Command line OpenMM simulation option name.
2357 ParamsOptionValues (str): Space delimited list of parameter name and value pairs.
2358 ParamsDefaultInfo (dict): Default values to override for selected parameters.
2359
2360 Returns:
2361 dictionary: Processed parameter name and value pairs.
2362
2363 """
2364
2365 ParamsInfo = {
2366 "Steps": 1000000,
2367 "Minimization": True,
2368 "MinimizationMaxSteps": "auto",
2369 "MinimizationTolerance": 0.24,
2370 "Equilibration": True,
2371 "EquilibrationSteps": 1000,
2372 }
2373
2374 (ValidParamNames, CanonicalParamNamesMap, ParamsOptionValue, ParamsOptionValueWords) = (
2375 _ValidateAndCanonicalizeParameterNames(ParamsOptionName, ParamsOptionValue, ParamsInfo, ParamsDefaultInfo)
2376 )
2377
2378 if re.match("^auto$", ParamsOptionValue, re.I):
2379 _ProcessOptionOpenMMSimulationParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue)
2380 return ParamsInfo
2381
2382 for Index in range(0, len(ParamsOptionValueWords), 2):
2383 Name = ParamsOptionValueWords[Index].strip()
2384 Value = ParamsOptionValueWords[Index + 1].strip()
2385
2386 ParamName = CanonicalParamNamesMap[Name.lower()]
2387 ParamValue = Value
2388
2389 if re.match("^(Steps|EquilibrationSteps)$", ParamName, re.I):
2390 if not MiscUtil.IsInteger(Value):
2391 MiscUtil.PrintError(
2392 'The parameter value, %s, specified for parameter name, %s, using "%s" option must be an integer.\n'
2393 % (Value, ParamName, ParamsOptionName)
2394 )
2395 Value = int(Value)
2396 if Value <= 0:
2397 MiscUtil.PrintError(
2398 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. Supported values: > 0\n'
2399 % (ParamValue, ParamName, ParamsOptionName)
2400 )
2401 ParamValue = Value
2402 elif re.match("^(Minimization|Equilibration)$", ParamName, re.I):
2403 if not re.match("^(yes|no|true|false)$", Value, re.I):
2404 MiscUtil.PrintError(
2405 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. Supported values: yes or no'
2406 % (Value, Name, ParamsOptionName)
2407 )
2408 ParamValue = True if re.match("^(yes|true)$", Value, re.I) else False
2409 elif re.match("^MinimizationMaxSteps$", ParamName, re.I):
2410 if not re.match("^auto$", Value, re.I):
2411 if not MiscUtil.IsInteger(Value):
2412 MiscUtil.PrintError(
2413 'The parameter value, %s, specified for parameter name, %s, using "%s" option must be an integer.\n'
2414 % (Value, ParamName, ParamsOptionName)
2415 )
2416 Value = int(Value)
2417 if Value < 0:
2418 MiscUtil.PrintError(
2419 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. Supported values: >= 0\n'
2420 % (ParamValue, ParamName, ParamsOptionName)
2421 )
2422 ParamValue = Value
2423 elif re.match("^MinimizationTolerance$", ParamName, re.I):
2424 if not MiscUtil.IsFloat(Value):
2425 MiscUtil.PrintError(
2426 'The parameter value, %s, specified for parameter name, %s, using "%s" option must be a float.\n'
2427 % (Value, ParamName, ParamsOptionName)
2428 )
2429 Value = float(Value)
2430 if Value <= 0:
2431 MiscUtil.PrintError(
2432 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. Supported values: > 0\n'
2433 % (ParamValue, ParamName, ParamsOptionName)
2434 )
2435 ParamValue = Value
2436 else:
2437 ParamValue = Value
2438
2439 # Set value...
2440 ParamsInfo[ParamName] = ParamValue
2441
2442 # Handle parameters with possible auto values...
2443 _ProcessOptionOpenMMSimulationParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue)
2444
2445 return ParamsInfo
2446
2447
2448 def _ProcessOptionOpenMMSimulationParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue):
2449 """Process parameters with possible auto values and perform validation."""
2450
2451 ParamName = "MinimizationMaxSteps"
2452 ParamValue = "%s" % ParamsInfo[ParamName]
2453 if re.match("^auto$", ParamValue, re.I):
2454 ParamsInfo[ParamName] = 0
2455
2456
2457 def ProcessOptionOpenMMOutputParameters(ParamsOptionName, ParamsOptionValue, OutfilePrefix, ParamsDefaultInfo=None):
2458 """Process parameters for output option and return a map containing processed
2459 parameter names and values.
2460
2461 ParamsOptionValue is a comma delimited list of parameter name and value pairs
2462 to setup platform.
2463
2464 The supported parameter names along with their default and possible
2465 values are shown below:
2466
2467 checkpoint, no [ Possible values: yes or no ]
2468 checkpointFile, auto [ Default: <OutfilePrefix>.chk ]
2469 checkpointSteps, 10000
2470
2471 dataOutType, auto [ Possible values: A space delimited list of valid
2472 parameter names.
2473 NPT simulation default: Density Step Speed Progress
2474 PotentialEnergy Temperature Time.
2475 NVT simulation default: Step Speed Progress PotentialEnergy
2476 Temperature Time Volumne
2477 Other valid names: ElapsedTime RemainingTime KineticEnergy
2478 TotalEnergy ]
2479
2480 dataLog, yes [ Possible values: yes or no ]
2481 dataLogFile, auto [ Default: <OutfilePrefix>.csv ]
2482 dataLogSteps, 1000
2483
2484 dataStdout, no [ Possible values: yes or no ]
2485 dataStdoutSteps, 1000
2486
2487 dataOutTypePlot, yes [ Possible values: yes or no ]
2488 dataOutTypePlotX, auto [ Default: Time; Possible values: Step or
2489 Time ]
2490 dataOutTypePlotY, auto [ Possible values: A space delimited list
2491 of valid parameter names specified for dataOutType.
2492 NPT simulation default: Density PotentialEnergy Temperature
2493 NVT simulation default: PotentialEnergy Temperature Volume
2494 Other valid names: KineticEnergy TotalEnergy]
2495
2496 minimizationDataSteps, 100
2497 minimizationDataStdout, no [ Possible values: yes or no ]
2498 minimizationDataLog, no [ Possible values: yes or no ]
2499 minimizationDataLogFile, auto [ Default:
2500 <OutfilePrefix>_MinimizationOut.csv ]
2501 minimizationDataOutType, auto [ Possible values: A space delimited
2502 list of valid parameter names. Default: SystemEnergy
2503 RestraintEnergy MaxConstraintError.
2504 Other valid names: RestraintStrength ]
2505
2506 pdbOutFormat, PDB [ Possible values: PDB or CIF ]
2507 pdbOutKeepIDs, yes [ Possible values: yes or no ]
2508
2509 pdbOutMinimized, no [ Possible values: yes or no ]
2510 pdbOutEquilibrated, no [ Possible values: yes or no ]
2511 pdbOutFinal, no [ Possible values: yes or no ]
2512
2513 pdbOutPhase1HeatedNVT, no [ Possible values: yes or no ]
2514 pdbOutPhase2AnnealedNVT, no [ Possible values: yes or no ]
2515 pdbOutPhase3EquilibratedNVT, no [ Possible values: yes or no ]
2516 pdbOutPhase4EquilibratedNPT, no [ Possible values: yes or no ]
2517 pdbOutPhase5ProductionNPT, no [ Possible values: yes or no ]
2518
2519 saveFinalStateCheckpoint, yes [ Possible values: yes or no ]
2520 saveFinalStateCheckpointFile, auto [ Default:
2521 <OutfilePrefix>_FinalState.chk ]
2522 saveFinalStateXML, no [ Possible values: yes or no ]
2523 saveFinalStateXMLFile, auto [ Default:
2524 <OutfilePrefix>_FinalState.xml]
2525
2526 traj, yes [ Possible values: yes or no ]
2527 trajFile, auto [ Default: <OutfilePrefix>.<TrajFormat> ]
2528 trajFormat, DCD [ Possible values: DCD or XTC ]
2529 trajSteps, 10000
2530
2531 xmlSystemOut, no [ Possible values: yes or no ]
2532 xmlSystemFile, auto [ Default: <OutfilePrefix>_System.xml ]
2533 xmlIntegratorOut, no [ Possible values: yes or no ]
2534 xmlIntegratorFile, auto [ Default: <OutfilePrefix>_Integrator.xml ]
2535
2536 A brief description of parameters is provided below:
2537
2538 checkpoint: Write intermediate checkpoint file.
2539 checkpointFile: Intermediate checkpoint file name.
2540 checkpointSteps: Frequency of writing intermediate checkpoint file.
2541
2542 dataOutType: Type of data to write to stdout and log file.
2543
2544 dataLog: Write data to log file.
2545 dataLogFile: Data log file name.
2546 dataLogSteps: Frequency of writing data to log file.
2547
2548 dataStdout: Write data to stdout.
2549 dataStdoutSteps: Frequency of writing data to stdout.
2550
2551 dataOutTypePlot: Generate plots using data written to log file.
2552 dataOutTypePlotX: Data out type to plot on X axis.
2553 dataOutTypePlotY: Data out types to plot on Y axis. An individual plot
2554 is generated for each pair of X and Y vaues to be plotted.
2555
2556 minimizationDataSteps: Frequency of writing data to stdout and log file.
2557 minimizationDataStdout: Write data to stdout.
2558 minimizationDataLog: Write data to log file.
2559 minimizationDataLogFile: Data log fie name.
2560 minimizationDataOutType: Type of data to write to stdout and log file.
2561
2562 pdbOutFormat: Format of output PDB files.
2563 pdbOutKeepIDs: Keep existing chain and residue IDs.
2564
2565 pdbOutMinimized: Write PDB file after minimization.
2566 pdbOutEquilibrated: Write PDB file after equilibration.
2567 pdbOutFinal: Write final PDB file after production run.
2568
2569 pdbOutPhase1HeatedNVT: Write out PDB file after initial heatin
2570 pdbOutPhase2AnnealedNVT: Write out PDB file after heating and cooling.
2571 pdbOutPhase3EquilibratedNVT: Write out PDB file after equilibration.
2572 pdbOutPhase4EquilibratedNPT: Write out PDB file after equilibration.
2573 pdbOutPhase5ProductionNPT: Write out PDB file after production run.
2574
2575 saveFinalStateCheckpoint: Save final state checkpoint file.
2576 saveFinalStateCheckpointFile: Name of final state checkpoint file.
2577 saveFinalStateXML: Save final state XML file.
2578 saveFinalStateXMLFile: Name of final state XML file.
2579
2580 traj: Write out trajectory file.
2581 trajFile: Trajectory file name.
2582 trajFormat: Trajectory file format.
2583 trajSteps: Frequency of writing trajectory file.
2584
2585 xmlSystemOut: Write system XML file.
2586 xmlSystemFile: System XML file name.
2587 xmlIntegratorOut: Write integrator XML file.
2588 xmlIntegratorFile: Integrator XML file name.
2589
2590 Arguments:
2591 ParamsOptionName (str): Command line OpenMM system option name.
2592 ParamsOptionValues (str): Space delimited list of parameter name and value pairs.
2593 ParamsDefaultInfo (dict): Default values to override for selected parameters.
2594
2595 Returns:
2596 dictionary: Processed parameter name and value pairs.
2597
2598 """
2599
2600 ParamsInfo = {
2601 "Checkpoint": False,
2602 "CheckpointFile": "auto",
2603 "CheckpointSteps": 10000,
2604 "DataOutType": "auto",
2605 "DataLog": True,
2606 "DataLogFile": "auto",
2607 "DataLogSteps": 1000,
2608 "DataStdout": False,
2609 "DataStdoutSteps": 1000,
2610 "DataOutTypePlot": True,
2611 "DataOutTypePlotX": "auto",
2612 "DataOutTypePlotY": "auto",
2613 "MinimizationDataSteps": 100,
2614 "MinimizationDataStdout": False,
2615 "MinimizationDataLog": False,
2616 "MinimizationDataLogFile": "auto",
2617 "MinimizationDataOutType": "auto",
2618 "PDBOutFormat": "PDB",
2619 "PDBOutKeepIDs": True,
2620 "PDBOutMinimized": False,
2621 "PDBOutEquilibrated": False,
2622 "PDBOutFinal": False,
2623 "PDBOutPhase1HeatedNVT": False,
2624 "PDBOutPhase2AnnealedNVT": False,
2625 "PDBOutPhase3EquilibratedNVT": False,
2626 "PDBOutPhase4EquilibratedNPT": False,
2627 "PDBOutPhase5ProductionNPT": False,
2628 "SaveFinalStateCheckpoint": True,
2629 "SaveFinalStateCheckpointFile": "auto",
2630 "SaveFinalStateXML": False,
2631 "SaveFinalStateXMLFile": "auto",
2632 "Traj": True,
2633 "TrajFile": "auto",
2634 "TrajFormat": "DCD",
2635 "TrajSteps": 10000,
2636 "XmlSystemOut": False,
2637 "XmlSystemFile": "auto",
2638 "XmlIntegratorOut": False,
2639 "XmlIntegratorFile": "auto",
2640 }
2641
2642 (ValidParamNames, CanonicalParamNamesMap, ParamsOptionValue, ParamsOptionValueWords) = (
2643 _ValidateAndCanonicalizeParameterNames(ParamsOptionName, ParamsOptionValue, ParamsInfo, ParamsDefaultInfo)
2644 )
2645
2646 if re.match("^auto$", ParamsOptionValue, re.I):
2647 _ProcessOptionOpenMMOutputParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue, OutfilePrefix)
2648 return ParamsInfo
2649
2650 for Index in range(0, len(ParamsOptionValueWords), 2):
2651 Name = ParamsOptionValueWords[Index].strip()
2652 Value = ParamsOptionValueWords[Index + 1].strip()
2653
2654 ParamName = CanonicalParamNamesMap[Name.lower()]
2655 ParamValue = Value
2656
2657 if re.match(
2658 "^(Checkpoint|DataLog|DataStdout|DataOutTypePlot|MinimizationDataStdout|MinimizationDataLog|PDBOutKeepIDs|SaveFinalStateCheckpoint|SaveFinalStateXML|Traj|XmlSystemOut|XmlIntegratorOut|PDBOutMinimized|PDBOutEquilibrated|PDBOutFinal|PDBOutPhase1HeatedNVT|PDBOutPhase2AnnealedNVT|PDBOutPhase3EquilibratedNVT|PDBOutPhase4EquilibratedNPT|PDBOutPhase5ProductionNPT)$",
2659 ParamName,
2660 re.I,
2661 ):
2662 if not re.match("^(yes|no|true|false)$", Value, re.I):
2663 MiscUtil.PrintError(
2664 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. Supported values: yes or no'
2665 % (Value, Name, ParamsOptionName)
2666 )
2667 ParamValue = True if re.match("^(yes|true)$", Value, re.I) else False
2668 elif re.match("^(CheckpointFile|SaveFinalStateCheckpointFile)$", ParamName, re.I):
2669 if not re.match("^auto$", Value, re.I):
2670 if not MiscUtil.CheckFileExt(Value, "chk"):
2671 MiscUtil.PrintError(
2672 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. Supported file format: chk'
2673 % (Value, Name, ParamsOptionName)
2674 )
2675 ParamValue = Value
2676 elif re.match("^(DataLogFile|MinimizationDataLogFile)$", ParamName, re.I):
2677 if not re.match("^auto$", Value, re.I):
2678 if not MiscUtil.CheckFileExt(Value, "csv"):
2679 MiscUtil.PrintError(
2680 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. Supported file formats: csv'
2681 % (Value, Name, ParamsOptionName)
2682 )
2683 ParamValue = Value
2684 elif re.match("^(SaveFinalStateXMLFile|XmlSystemFile|XmlIntegratorFile)$", ParamName, re.I):
2685 if not re.match("^auto$", Value, re.I):
2686 if not MiscUtil.CheckFileExt(Value, "xml"):
2687 MiscUtil.PrintError(
2688 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. Supported file format: xml'
2689 % (Value, Name, ParamsOptionName)
2690 )
2691 ParamValue = Value
2692 elif re.match("^TrajFile$", ParamName, re.I):
2693 if not re.match("^auto$", Value, re.I):
2694 if not MiscUtil.CheckFileExt(Value, "dcd xtc"):
2695 MiscUtil.PrintError(
2696 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. Supported file formats: dcd xtc'
2697 % (Value, Name, ParamsOptionName)
2698 )
2699 ParamValue = Value
2700 elif re.match(
2701 "^(CheckpointSteps|DataLogSteps|DataStdoutSteps|MinimizationDataSteps|TrajSteps)$", ParamName, re.I
2702 ):
2703 if not MiscUtil.IsInteger(Value):
2704 MiscUtil.PrintError(
2705 'The parameter value, %s, specified for parameter name, %s, using "%s" option must be an integer.\n'
2706 % (Value, ParamName, ParamsOptionName)
2707 )
2708 Value = int(Value)
2709 if Value <= 0:
2710 MiscUtil.PrintError(
2711 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. Supported values: > 0\n'
2712 % (ParamValue, ParamName, ParamsOptionName)
2713 )
2714 ParamValue = Value
2715 elif re.match("^DataOutType$", ParamName, re.I):
2716 if not re.match("^auto$", Value, re.I):
2717 ValueTypes = Value.split()
2718 if len(ValueTypes) == 0:
2719 MiscUtil.PrintError(
2720 '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'
2721 % (Value, ParamName, ParamsOptionName)
2722 )
2723 ValueTypesSpecified = []
2724 for ValueType in ValueTypes:
2725 if not re.match(
2726 "^(Step|Speed|Progress|PotentialEnergy|Temperature|ElapsedTime|RemainingTime|Time|KineticEnergy|TotalEnergy|Volume|Density)$",
2727 ValueType,
2728 re.I,
2729 ):
2730 MiscUtil.PrintError(
2731 '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'
2732 % (ValueType, Name, ParamsOptionName)
2733 )
2734 if ValueType in ValueTypesSpecified:
2735 MiscUtil.PrintError(
2736 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. It has already been specified.'
2737 % (ValueType, Name, ParamsOptionName)
2738 )
2739 ValueTypesSpecified.append(ValueType)
2740 ParamsInfo["DataOutTypeList"] = ValueTypes
2741 elif re.match("^DataOutTypePlotX$", ParamName, re.I):
2742 if not re.match("^auto$", Value, re.I):
2743 if not re.match("^(Step|Time)$", Value, re.I):
2744 MiscUtil.PrintError(
2745 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. Supported values: Step or Time'
2746 % (Value, Name, ParamsOptionName)
2747 )
2748 ParamValue = Value
2749 elif re.match("^DataOutTypePlotY$", ParamName, re.I):
2750 if not re.match("^auto$", Value, re.I):
2751 ValueTypes = Value.split()
2752 if len(ValueTypes) == 0:
2753 MiscUtil.PrintError(
2754 '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'
2755 % (Value, ParamName, ParamsOptionName)
2756 )
2757 ValueTypesSpecified = []
2758 for ValueType in ValueTypes:
2759 if not re.match(
2760 "^(PotentialEnergy|Temperature|KineticEnergy|TotalEnergy|Volume|Density)$", ValueType, re.I
2761 ):
2762 MiscUtil.PrintError(
2763 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. Supported values: PotentialEnergy, Temperature, KineticEnergy, TotalEnergy, Volume, or Density'
2764 % (ValueType, Name, ParamsOptionName)
2765 )
2766 if ValueType in ValueTypesSpecified:
2767 MiscUtil.PrintError(
2768 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. It has already been specified.'
2769 % (ValueType, Name, ParamsOptionName)
2770 )
2771 ValueTypesSpecified.append(ValueType)
2772 ParamsInfo["DataOutTypePlotXList"] = ValueTypes
2773 elif re.match("^MinimizationDataOutType$", ParamName, re.I):
2774 if not re.match("^auto$", Value, re.I):
2775 ValueTypes = Value.split()
2776 if len(ValueTypes) == 0:
2777 MiscUtil.PrintError(
2778 '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'
2779 % (Value, ParamName, ParamsOptionName)
2780 )
2781 ValueTypesSpecified = []
2782 for ValueType in ValueTypes:
2783 if not re.match(
2784 "^(SystemEnergy|RestraintEnergy|RestraintStrength|MaxConstraintError)$", ValueType, re.I
2785 ):
2786 MiscUtil.PrintError(
2787 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. Supported values: SystemEnergy, RestraintEnergy, RestraintStrength, or MaxConstraintError'
2788 % (ValueType, Name, ParamsOptionName)
2789 )
2790 if ValueType in ValueTypesSpecified:
2791 MiscUtil.PrintError(
2792 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. It has already been specified.'
2793 % (ValueType, Name, ParamsOptionName)
2794 )
2795 ValueTypesSpecified.append(ValueType)
2796 ParamsInfo["MinimizationDataOutTypeList"] = ValueTypes
2797 elif re.match("^PDBOutFormat$", ParamName, re.I):
2798 if not re.match("^(PDB|CIF)$", Value, re.I):
2799 MiscUtil.PrintError(
2800 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. Supported values: PDB or CIF'
2801 % (Value, Name, ParamsOptionName)
2802 )
2803 ParamValue = Value
2804 elif re.match("^TrajFormat$", ParamName, re.I):
2805 if not re.match("^(DCD|XTC)$", Value, re.I):
2806 MiscUtil.PrintError(
2807 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. Supported values: DCD or XTC'
2808 % (Value, Name, ParamsOptionName)
2809 )
2810 ParamValue = Value
2811 else:
2812 ParamValue = Value
2813
2814 # Set value...
2815 ParamsInfo[ParamName] = ParamValue
2816
2817 # Handle parameters with possible auto values...
2818 _ProcessOptionOpenMMOutputParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue, OutfilePrefix)
2819
2820 return ParamsInfo
2821
2822
2823 def _ProcessOptionOpenMMOutputParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue, OutfilePrefix):
2824 """Process parameters with possible auto values and perform validation."""
2825
2826 # Use comma as a delimiter...
2827 ParamsInfo["DataOutDelimiter"] = ","
2828 ParamsInfo["DataOutfileExt"] = "csv"
2829
2830 ParamName = "TrajFormat"
2831 ParamValue = ParamsInfo[ParamName]
2832 if re.match("^DCD$", ParamValue, re.I):
2833 TrajFileExt = "dcd"
2834 elif re.match("^XTC$", ParamValue, re.I):
2835 TrajFileExt = "xtc"
2836 else:
2837 MiscUtil.PrintError(
2838 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. Supported values: DCD or XTC'
2839 % (ParamValue, ParamName, ParamsOptionName)
2840 )
2841 ParamsInfo["TrajFileExt"] = TrajFileExt
2842
2843 ParamName = "PDBOutFormat"
2844 ParamValue = ParamsInfo[ParamName]
2845 if re.match("^PDB$", ParamValue, re.I):
2846 PDBOutfileExt = "pdb"
2847 elif re.match("^CIF$", ParamValue, re.I):
2848 PDBOutfileExt = "cif"
2849 else:
2850 MiscUtil.PrintError(
2851 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. Supported values: PDB or CIF'
2852 % (ParamValue, ParamName, ParamsOptionName)
2853 )
2854 ParamsInfo["PDBOutfileExt"] = PDBOutfileExt
2855
2856 _ProcessFileNamesOutputPatramaters(ParamsInfo, ParamsOptionName, ParamsOptionValue, OutfilePrefix)
2857 _ProcessDataOutTypeOutputParameter(ParamsInfo, ParamsOptionName, ParamsOptionValue, OutfilePrefix)
2858 _ProcessMinimizationDataOutTypeOutputParameter(ParamsInfo, ParamsOptionName, ParamsOptionValue, OutfilePrefix)
2859 _ProcessDataOutTypePlotOutputParameter(ParamsInfo, ParamsOptionName, ParamsOptionValue, OutfilePrefix)
2860
2861
2862 def _ProcessFileNamesOutputPatramaters(ParamsInfo, ParamsOptionName, ParamsOptionValue, OutfilePrefix):
2863 """Process output parameters corresponding to file names."""
2864
2865 OutfileExt = ParamsInfo["DataOutfileExt"]
2866 TrajFileExt = ParamsInfo["TrajFileExt"]
2867 OutfilesSuffixAndExtMap = {
2868 "CheckpointFile": ["", "chk"],
2869 "DataLogFile": ["", OutfileExt],
2870 "MinimizationDataLogFile": ["Minimization", OutfileExt],
2871 "SaveFinalStateCheckpointFile": ["FinalState", "chk"],
2872 "SaveFinalStateXMLFile": ["FinalState", "xml"],
2873 "TrajFile": ["", TrajFileExt],
2874 "XmlSystemFile": ["System", "xml"],
2875 "XmlIntegratorFile": ["Integrator", "xml"],
2876 }
2877 OutfileNames = []
2878 for ParamName in OutfilesSuffixAndExtMap:
2879 ParamValue = ParamsInfo[ParamName]
2880 if re.match("^auto$", ParamValue, re.I):
2881 DataOutfileSuffix, DataOutfileExt = OutfilesSuffixAndExtMap[ParamName]
2882 if len(DataOutfileSuffix):
2883 DataOutfileSuffix = "_%s" % DataOutfileSuffix
2884 ParamValue = "%s%s.%s" % (OutfilePrefix, DataOutfileSuffix, DataOutfileExt)
2885 ParamsInfo[ParamName] = ParamValue
2886 else:
2887 # Check for duplicate output file names...
2888 if ParamValue not in OutfileNames:
2889 OutfileNames.append(ParamValue)
2890 else:
2891 MiscUtil.PrintError(
2892 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. It\'s a duplicate file name.'
2893 % (ParamValue, ParamName, ParamsOptionName)
2894 )
2895
2896 # Validate specified traj file extension...
2897 if re.match("^TrajFile$", ParamName, re.I):
2898 TrajFormat = ParamsInfo["TrajFormat"]
2899 if not MiscUtil.CheckFileExt(ParamValue, TrajFileExt):
2900 MiscUtil.PrintError(
2901 '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.'
2902 % (ParamValue, ParamName, ParamsOptionName, TrajFileExt, TrajFormat)
2903 )
2904
2905
2906 def _ProcessDataOutTypeOutputParameter(ParamsInfo, ParamsOptionName, ParamsOptionValue, OutfilePrefix):
2907 """Process output parameter corresponding to data out type."""
2908
2909 # Setup data out types...
2910 DataOutTypeStatusMap = {
2911 "Step": False,
2912 "Speed": False,
2913 "Progress": False,
2914 "PotentialEnergy": False,
2915 "Temperature": False,
2916 "ElapsedTime": False,
2917 "RemainingTime": False,
2918 "Time": False,
2919 "KineticEnergy": False,
2920 "TotalEnergy": False,
2921 "Volume": False,
2922 "Density": False,
2923 }
2924 CanonicalDataOutTypeMap = {}
2925 ValidDataOutTypes = []
2926 for DataOutType in DataOutTypeStatusMap:
2927 ValidDataOutTypes.append(DataOutType)
2928 CanonicalDataOutTypeMap[DataOutType.lower()] = DataOutType
2929
2930 # Process data out types...
2931 ParamName = "DataOutType"
2932 ParamValue = ParamsInfo[ParamName]
2933 DataOutTypeList = []
2934 if re.match("^auto$", ParamValue, re.I):
2935 DataOutTypeList = ["Step", "Speed", "Progress", "PotentialEnergy", "Temperature", "Time"]
2936 else:
2937 if "DataOutTypeList" in ParamsInfo:
2938 DataOutTypeList = ParamsInfo["DataOutTypeList"]
2939 else:
2940 DataOutTypeList = ParamsInfo["DataOutType"].split()
2941 ParamsInfo["DataOutTypeList"] = DataOutTypeList
2942
2943 for DataOutType in DataOutTypeList:
2944 CanonicalDataOutType = DataOutType.lower()
2945 if CanonicalDataOutType not in CanonicalDataOutTypeMap:
2946 MiscUtil.PrintError(
2947 'The parameter value, %s specified for paramaer name, %s, using "%s" is not a valid name. Supported parameter names: %s'
2948 % (DataOutType, ParamName, ParamsOptionName, " ".join(ValidDataOutTypes))
2949 )
2950
2951 DataOutType = CanonicalDataOutTypeMap[CanonicalDataOutType]
2952 DataOutTypeStatusMap[DataOutType] = True
2953
2954 ParamsInfo["DataOutTypeList"] = DataOutTypeList
2955 ParamsInfo["DataOutTypeStatusMap"] = DataOutTypeStatusMap
2956
2957
2958 def _ProcessDataOutTypePlotOutputParameter(ParamsInfo, ParamsOptionName, ParamsOptionValue, OutfilePrefix):
2959 """Process output parameter corresponding to plot data out type."""
2960
2961 # Setup specified data out types...
2962 DataOutTypes = ParamsInfo["DataOutTypeList"]
2963 CanonicalDataOutTypeMap = {}
2964 for DataOutType in DataOutTypes:
2965 CanonicalDataOutTypeMap[DataOutType.lower()] = DataOutType
2966
2967 # Process data out type plot X value...
2968 ParamName = "DataOutTypePlotX"
2969 ParamValue = ParamsInfo[ParamName]
2970 if re.match("^auto$", ParamValue, re.I):
2971 ParamValue = "Time"
2972 if ParamValue.lower() not in CanonicalDataOutTypeMap:
2973 MiscUtil.PrintError(
2974 'The specified or auto assigned parameter value, %s for paramaer name, %s, using "%s" is not a valid. It must be present in the list of values specified for parameter name, dataOutType, using "--dataOutType"option.'
2975 % (ParamValue, ParamName, ParamsOptionName)
2976 )
2977
2978 ParamsInfo[ParamName] = CanonicalDataOutTypeMap[ParamValue.lower()]
2979
2980 # Process data out type plot Y values...
2981 ParamName = "DataOutTypePlotY"
2982 ParamValue = ParamsInfo[ParamName]
2983 DataOutTypePlotYList = []
2984 if re.match("^auto$", ParamValue, re.I):
2985 DataOutTypePlotYList = ["PotentialEnergy", "Temperature"]
2986 else:
2987 if "DataOutTypePlotYList" in ParamsInfo:
2988 DataOutTypePlotYList = ParamsInfo["DataOutTypePlotYList"]
2989 else:
2990 DataOutTypePlotYList = ParamsInfo["DataOutTypePlotY"].split()
2991 ParamsInfo["DataOutTypePlotYList"] = DataOutTypePlotYList
2992
2993 CanonicalDataOutTypePlotYList = []
2994 for DataOutTypePlotY in DataOutTypePlotYList:
2995 CanonicalDataOutTypePlotY = DataOutTypePlotY.lower()
2996 if CanonicalDataOutTypePlotY not in CanonicalDataOutTypeMap:
2997 MiscUtil.PrintError(
2998 'The specified or auto assigned parameter value, %s for paramaer name, %s, using "%s" is not a valid. It must be present in the list of values specified for parameter name, dataOutType, using "--dataOutType"option.'
2999 % (DataOutTypePlotY, ParamName, ParamsOptionName)
3000 )
3001 CanonicalDataOutTypePlotYList.append(CanonicalDataOutTypeMap[CanonicalDataOutTypePlotY])
3002
3003 ParamsInfo["DataOutTypePlotYList"] = CanonicalDataOutTypePlotYList
3004
3005
3006 def _ProcessMinimizationDataOutTypeOutputParameter(ParamsInfo, ParamsOptionName, ParamsOptionValue, OutfilePrefix):
3007 """Process output parameter corresponding to minimization data out type."""
3008
3009 # Setup mimimization data out types...
3010 DataOutTypeOpenMMNameMap = {
3011 "SystemEnergy": "system energy",
3012 "RestraintEnergy": "restraint energy",
3013 "RestraintStrength": "restraint strength",
3014 "MaxConstraintError": "max constraint error",
3015 }
3016
3017 CanonicalDataOutTypeMap = {}
3018 ValidDataOutTypes = []
3019 for DataOutType in DataOutTypeOpenMMNameMap:
3020 ValidDataOutTypes.append(DataOutType)
3021 CanonicalDataOutTypeMap[DataOutType.lower()] = DataOutType
3022
3023 # Process minimization data out types...
3024 ParamName = "MinimizationDataOutType"
3025 ParamValue = ParamsInfo[ParamName]
3026 DataOutTypeList = []
3027 if re.match("^auto$", ParamValue, re.I):
3028 DataOutTypeList = ["SystemEnergy", "RestraintEnergy", "MaxConstraintError"]
3029 else:
3030 if "MinimizationDataOutTypeList" in ParamsInfo:
3031 DataOutTypeList = ParamsInfo["MinimizationDataOutTypeList"]
3032 else:
3033 DataOutTypeList = ParamsInfo["MinimizationDataOutType"].split()
3034 ParamsInfo["MinimizationDataOutTypeList"] = DataOutTypeList
3035
3036 # Set up a list containing OpenMM names for minimization reporter...
3037 DataOutTypeOpenMMNameList = []
3038 for DataOutType in DataOutTypeList:
3039 CanonicalDataOutType = DataOutType.lower()
3040 if CanonicalDataOutType not in CanonicalDataOutTypeMap:
3041 MiscUtil.PrintError(
3042 'The parameter value, %s specified for paramaer name, %s, specified using "%s" is not a valid name. Supported parameter names: %s'
3043 % (DataOutType, ParamName, ParamsOptionName, " ".join(ValidDataOutTypes))
3044 )
3045
3046 DataOutType = CanonicalDataOutTypeMap[CanonicalDataOutType]
3047
3048 DataOutTypeOpenMMName = DataOutTypeOpenMMNameMap[DataOutType]
3049 DataOutTypeOpenMMNameList.append(DataOutTypeOpenMMName)
3050
3051 ParamsInfo["MinimizationDataOutTypeList"] = DataOutTypeList
3052 ParamsInfo["MinimizationDataOutTypeOpenMMNameList"] = DataOutTypeOpenMMNameList
3053
3054
3055 def ProcessOptionOpenMMAtomsSelectionParameters(ParamsOptionName, ParamsOptionValue, ParamsDefaultInfo=None):
3056 """Process parameters for selecting atoms and return a map containing
3057 processed parameter names and values.
3058
3059 ParamsOptionValue is a comma delimited list of parameter name and value pairs
3060 to select atoms.
3061
3062 The supported parameter names along with their default and possible
3063 values are shown below:
3064
3065 selection, none [ Possible values: CAlphaProtein, Ions, Ligand,
3066 Protein, Residues, or Water ]
3067 selectionSpec, auto [ Possible values: A space delimited list of
3068 residue names ]
3069 negate, no [ Possible values: yes or no ]
3070
3071 A brief description of parameters is provided below:
3072
3073 selection: Atom selection to freeze.
3074
3075 selectionSpec: A space delimited list of residue names for selecting atoms.
3076 You must specify its value during 'Ligand' and 'Protein' value for 'selection'.
3077 The default values are automatically set for 'CAlphaProtein', 'Ions', 'Protein',
3078 and 'Water' values of 'selection' as shown below:
3079
3080 CAlphaProtein: List of stadard protein residues from pdbfixer
3081 for selecting CAlpha atoms.
3082 Ions: Li Na K Rb Cs Cl Br F I
3083 Water: HOH
3084 Protein: List of standard protein residues from pdbfixer.
3085
3086 negate: Negate atom selection match to select atoms for freezing.
3087
3088 In addition, you may specify an explicit space delimited list of residue
3089 names using 'selectionSpec' for any 'selection". The specified residue
3090 names are appended to the appropriate default values during the
3091 selection of atoms for freezing.
3092
3093 Arguments:
3094 ParamsOptionName (str): Command line OpenMM selection option name.
3095 ParamsOptionValues (str): Space delimited list of parameter name and value pairs.
3096 ParamsDefaultInfo (dict): Default values to override for selected parameters.
3097
3098 Returns:
3099 dictionary: Processed parameter name and value pairs.
3100
3101 """
3102
3103 ParamsInfo = {"Selection": None, "SelectionSpec": "auto", "Negate": False}
3104
3105 if ParamsOptionValue is None:
3106 return ParamsInfo
3107
3108 (ValidParamNames, CanonicalParamNamesMap, ParamsOptionValue, ParamsOptionValueWords) = (
3109 _ValidateAndCanonicalizeParameterNames(ParamsOptionName, ParamsOptionValue, ParamsInfo, ParamsDefaultInfo)
3110 )
3111
3112 if re.match("^auto$", ParamsOptionValue, re.I):
3113 _ProcessOptionOpenMMAtomsSelectionParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue)
3114 return ParamsInfo
3115
3116 for Index in range(0, len(ParamsOptionValueWords), 2):
3117 Name = ParamsOptionValueWords[Index].strip()
3118 Value = ParamsOptionValueWords[Index + 1].strip()
3119
3120 ParamName = CanonicalParamNamesMap[Name.lower()]
3121 ParamValue = Value
3122
3123 # Set value...
3124 ParamsInfo[ParamName] = ParamValue
3125 if re.match("^Selection$", ParamName, re.I):
3126 if not re.match("^(CAlphaProtein|Ions|Ligand|Protein|Residues|Water)$", Value, re.I):
3127 MiscUtil.PrintError(
3128 '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'
3129 % (Value, Name, ParamsOptionName)
3130 )
3131 ParamValue = Value
3132 elif re.match("^SelectionSpec$", ParamName, re.I):
3133 if not re.match("^(auto|none)$", Value, re.I):
3134 Values = Value.split()
3135 if len(Values) == 0:
3136 MiscUtil.PrintError(
3137 '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'
3138 % (Value, ParamName, ParamsOptionName)
3139 )
3140 # Set residues list...
3141 ParamsInfo["SelectionSpecList"] = Values
3142 elif re.match("^Negate$", ParamName, re.I):
3143 if not re.match("^(yes|no|true|false)$", Value, re.I):
3144 MiscUtil.PrintError(
3145 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. Supported values: yes or no'
3146 % (Value, Name, ParamsOptionName)
3147 )
3148 ParamValue = True if re.match("^(yes|true)$", Value, re.I) else False
3149 else:
3150 ParamValue = Value
3151
3152 # Set value...
3153 ParamsInfo[ParamName] = ParamValue
3154
3155 # Handle parameters with possible auto values...
3156 _ProcessOptionOpenMMAtomsSelectionParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue)
3157
3158 return ParamsInfo
3159
3160
3161 def _ProcessOptionOpenMMAtomsSelectionParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue):
3162 """Process parameters with possible auto values and perform validation."""
3163
3164 SelectionParamName = "Selection"
3165 SelectionParamValue = ParamsInfo[SelectionParamName]
3166
3167 SelectionSpecParamName = "SelectionSpec"
3168 SelectionSpecParamValue = ParamsInfo[SelectionSpecParamName]
3169
3170 SelectionSpecList = (
3171 None if re.match("^(auto|none)$", SelectionSpecParamValue, re.I) else ParamsInfo["SelectionSpecList"]
3172 )
3173
3174 ResidueNames = None
3175 if re.match("^(CAlphaProtein|Protein)$", SelectionParamValue, re.I):
3176 ResidueNames = pdbfixer.pdbfixer.proteinResidues
3177 if SelectionSpecList is not None:
3178 ResidueNames.extend(SelectionSpecList)
3179 elif re.match("^Ions$", SelectionParamValue, re.I):
3180 ResidueNames = ["Li", "Na", "K", "Rb", "Cs", "Cl", "Br", "F", "I"]
3181 if SelectionSpecList is not None:
3182 ResidueNames.extend(SelectionSpecList)
3183 elif re.match("^Ligand$", SelectionParamValue, re.I):
3184 if SelectionSpecList is None:
3185 MiscUtil.PrintError(
3186 'No value specified for parameter name, %s, using "%s" option is not a valid value. It must contain a ligand residue name.\n'
3187 % (SelectionSpecParamName, ParamsOptionName)
3188 )
3189 elif len(SelectionSpecList) != 1:
3190 MiscUtil.PrintError(
3191 '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'
3192 % (SelectionSpecParamValue, SelectionSpecParamName, ParamsOptionName)
3193 )
3194 ResidueNames = SelectionSpecList
3195 elif re.match("^Residues$", SelectionParamValue, re.I):
3196 if SelectionSpecList is None:
3197 MiscUtil.PrintError(
3198 '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'
3199 % (SelectionSpecParamValue, SelectionSpecParamName, ParamsOptionName)
3200 )
3201 ResidueNames = SelectionSpecList
3202 elif re.match("^Water$", SelectionParamValue, re.I):
3203 ResidueNames = ["HOH"]
3204 if SelectionSpecList is not None:
3205 ResidueNames.extend(SelectionSpecList)
3206
3207 ParamsInfo["ResidueNames"] = [ResidueName.upper() for ResidueName in ResidueNames]
3208 ParamsInfo["CAlphaProteinStatus"] = True if re.match("^CAlphaProtein$", SelectionParamValue, re.I) else False
3209
3210
3211 def ProcessOptionOpenMMForcefieldParameters(ParamsOptionName, ParamsOptionValue, ParamsDefaultInfo=None):
3212 """Process parameters for biopolymer, small molecule, and water forcefields and
3213 return a map containing processed parameter names and values.
3214
3215 ParamsOptionValue is a comma delimited list of parameter name and value pairs
3216 for forcefields.
3217
3218 The supported parameter names along with their default and possible
3219 values are shown below:
3220
3221 biopolymer, amber14-all.xml [ Possible values: Any Valid value ]
3222 smallMolecule, OpenFF_2.2.0 [ Possible values: Any Valid value ]
3223 water, auto [ Possible values: Any Valid value ]
3224
3225 Possible biopolymer forcefield values:
3226
3227 amber14-all.xml, amber99sb.xml, amber99sbildn.xml, amber03.xml,
3228 amber10.xml
3229 charmm36.xml, charmm_polar_2019.xml
3230 amoeba2018.xml
3231
3232 Possible small molecule forcefield values:
3233
3234 openff_2.2.0, openff_2.0.0, openff_1.3.1, openff_1.2.1, openff_1.1.1,
3235 smirnoff99frosst
3236 gaff-2.11, gaff-2.1, gaff-1.81, gaff-1.8, gaff-1.4
3237
3238 The default water forcefield valus is dependent on the type of the
3239 biopolymer forcefield as shown below:
3240
3241 Amber: amber14/tip3pfb.xml
3242 CHARMM: charmm36/water.xml or None for charmm_polar_2019.xml
3243 Amoeba: None (Explicit)
3244
3245 Possible water forcefield values:
3246
3247 amber14/tip3p.xml, amber14/tip3pfb.xml, amber14/spce.xml,
3248 amber14/tip4pew.xml, amber14/tip4pfb.xml,
3249 implicit/obc2.xml, implicit/GBn.xml, implicit/GBn2.xml
3250 charmm36/water.xml, charmm36/tip3p-pme-b.xml,
3251 charmm36/tip3p-pme-f.xml, charmm36/spce.xml,
3252 charmm36/tip4pew.xml, charmm36/tip4p2005.xml,
3253 charmm36/tip5p.xml, charmm36/tip5pew.xml,
3254 implicit/obc2.xml, implicit/GBn.xml, implicit/GBn2.xml
3255 amoeba2018_gk.xml (Implict water), None (Explicit water for amoeba)
3256
3257 You may specify any valid forcefield name supported by OpenMM. No
3258 explicit validation is performed.
3259
3260 Arguments:
3261 ParamsOptionName (str): Command line OpenMM forcefield option name.
3262 ParamsOptionValues (str): Space delimited list of parameter name and value pairs.
3263 ParamsDefaultInfo (dict): Default values to override for selected parameters.
3264
3265 Returns:
3266 dictionary: Processed parameter name and value pairs.
3267
3268 """
3269
3270 ParamsInfo = {
3271 "Biopolymer": "amber14-all.xml",
3272 "SmallMolecule": "openff-2.2.1",
3273 "Water": "auto",
3274 "Additional": "None",
3275 }
3276
3277 (ValidParamNames, CanonicalParamNamesMap, ParamsOptionValue, ParamsOptionValueWords) = (
3278 _ValidateAndCanonicalizeParameterNames(ParamsOptionName, ParamsOptionValue, ParamsInfo, ParamsDefaultInfo)
3279 )
3280
3281 if re.match("^auto$", ParamsOptionValue, re.I):
3282 _ProcessOptionOpenMMForcefieldParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue)
3283 return ParamsInfo
3284
3285 for Index in range(0, len(ParamsOptionValueWords), 2):
3286 Name = ParamsOptionValueWords[Index].strip()
3287 Value = ParamsOptionValueWords[Index + 1].strip()
3288
3289 ParamName = CanonicalParamNamesMap[Name.lower()]
3290 ParamValue = Value
3291
3292 # Set value...
3293 ParamsInfo[ParamName] = ParamValue
3294
3295 # Handle parameters with possible auto values...
3296 _ProcessOptionOpenMMForcefieldParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue)
3297
3298 return ParamsInfo
3299
3300
3301 def _ProcessOptionOpenMMForcefieldParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue):
3302 """Process parameters with possible auto values and perform validation."""
3303 WaterForcefield = ParamsInfo["Water"]
3304 if re.match("^None$", WaterForcefield, re.I):
3305 WaterForcefield = None
3306 ParamsInfo["Water"] = WaterForcefield
3307 elif re.match("^auto$", WaterForcefield, re.I):
3308 BiopolymerForcefield = ParamsInfo["Biopolymer"]
3309 if re.search("amber", BiopolymerForcefield, re.I):
3310 WaterForcefield = "amber14/tip3pfb.xml"
3311 elif re.search("charmm", BiopolymerForcefield, re.I):
3312 if re.search("charmm_polar_2019", BiopolymerForcefield, re.I):
3313 WaterForcefield = None
3314 else:
3315 WaterForcefield = "charmm36/water.xml"
3316 elif re.search("amoeba", BiopolymerForcefield, re.I):
3317 # Explicit water...
3318 WaterForcefield = None
3319 else:
3320 WaterForcefield = None
3321 ParamsInfo["Water"] = WaterForcefield
3322
3323 # Set status of implicit water forcefield...
3324 BiopolymerForcefield = ParamsInfo["Biopolymer"]
3325 ParamsInfo["ImplicitWater"] = True if _IsImplicitWaterForcefield(BiopolymerForcefield, WaterForcefield) else False
3326
3327 # Process additional forcefields...
3328 ParamName = "Additional"
3329 ParamValue = ParamsInfo[ParamName]
3330 ParamValuesList = None
3331 if not re.match("^None$", ParamValue, re.I):
3332 ParamValuesList = ParamValue.split()
3333 if len(ParamValuesList) == 0:
3334 MiscUtil.PrintError(
3335 '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'
3336 % (ParamValue, ParamName, ParamsOptionName)
3337 )
3338 ParamsInfo["AdditionalList"] = ParamValuesList
3339
3340
3341 def _IsImplicitWaterForcefield(BiopolymerForcefield, WaterForcefield):
3342 """Check the nature of the water forcefield."""
3343
3344 Status = False
3345 if WaterForcefield is None:
3346 if re.search("charmm_polar_2019", BiopolymerForcefield, re.I):
3347 Status = True
3348 else:
3349 Status = False
3350 else:
3351 if re.search("amber", BiopolymerForcefield, re.I):
3352 if re.search("implicit", WaterForcefield, re.I):
3353 Status = True
3354 elif re.search("charmm", BiopolymerForcefield, re.I):
3355 if re.search("implicit", WaterForcefield, re.I):
3356 Status = True
3357 elif re.search("amoeba", BiopolymerForcefield, re.I):
3358 Status = True
3359
3360 return Status
3361
3362
3363 def ProcessOptionOpenMMAnnealingParameters(ParamsOptionName, ParamsOptionValue, ParamsDefaultInfo=None):
3364 """Process parameters for annealing option and return a map containing processed
3365 parameter names and values.
3366
3367 ParamsOptionValue is a comma delimited list of parameter name and value pairs
3368 to setup platform.
3369
3370 The supported parameter names along with their default values for
3371 different platforms are shown below:
3372
3373 Initial heating parameters:
3374
3375 initialStart, 0.0 [ Units: kelvin ]
3376 initialEnd, 300.0 [ Units: kelvin ]
3377 initialChange, 5.0 [ Units: kelvin ]
3378 initialSteps, 5000
3379
3380 initialEquilibrationSteps, 100000
3381
3382 Heating and cooling cycle parameters:
3383
3384 cycles, 1
3385
3386 cycleStart, auto [ Units: kelvin. The default value is set to
3387 initialEnd ]
3388 cycleEnd, 315.0 [ Units: kelvin ]
3389 cycleChange, 1.0 [ Units: kelvin ]
3390 cycleSteps, 1000
3391
3392 cycleEquilibrationSteps, 100000
3393
3394 Final equilibration parameters:
3395
3396 finalEquilibrationSteps, 200000
3397
3398 A brief description of parameters is provided below:
3399
3400 Initial heating parameters:
3401
3402 initialStart: Start temperature for initial heating.
3403 initialEnd: End temperature for initial heating.
3404 initialChange: Temperature change for increasing temperature
3405 during initial heating.
3406 initialSteps: Number of simulation steps after each
3407 heating step during initial heating
3408
3409 initialEquilibrationSteps: Number of equilibration steps
3410 after the completion of initial heating.
3411
3412 Heating and cooling cycles parameters:
3413
3414 cycles: Number of annealing cycles to perform. Each cycle
3415 consists of a heating and a cooling phase. The heating phase
3416 consists of the following steps: Heat system from start to
3417 end temperature using change size and perform simulation for a
3418 number of steps after each increase in temperature; Perform
3419 equilibration after the completion of heating. The cooling
3420 phase is reverse of the heating phase and cools the system
3421 from end to start temperature.
3422
3423 cycleStart: Start temperature for annealing cycle.
3424 cycleEnd: End temperature for annealing cycle.
3425 cycleChange: Temperature change for increasing or decreasing
3426 temperature during annealing cycle.
3427 cycleSteps: Number of simulation steps after each heating and
3428 cooling step during annealing cycle.
3429
3430 cycleEquilibrationSteps: Number of equilibration steps
3431 after the completion of heating and cooling phase during a
3432 annealing cycle.
3433
3434 Final equilibration parameters:
3435
3436 finalEquilibrationSteps: Number of final equilibration
3437 steps after the completion of annealing cycles.
3438
3439 Arguments:
3440 ParamsOptionName (str): Command line OpenMM annealing option name.
3441 ParamsOptionValues (str): Space delimited list of parameter name and value pairs.
3442 ParamsDefaultInfo (dict): Default values to override for selected parameters.
3443
3444 Returns:
3445 dictionary: Processed parameter name and value pairs.
3446
3447 """
3448
3449 ParamsInfo = {
3450 "InitialStart": 0.0,
3451 "InitialEnd": 300.0,
3452 "InitialChange": 5.0,
3453 "InitialSteps": 5000,
3454 "InitialEquilibrationSteps": 100000,
3455 "Cycles": 1,
3456 "CycleStart": "auto",
3457 "CycleEnd": 315.0,
3458 "CycleChange": 1.0,
3459 "CycleSteps": 1000,
3460 "CycleEquilibrationSteps": 100000,
3461 "FinalEquilibrationSteps": 200000,
3462 }
3463
3464 (ValidParamNames, CanonicalParamNamesMap, ParamsOptionValue, ParamsOptionValueWords) = (
3465 _ValidateAndCanonicalizeParameterNames(ParamsOptionName, ParamsOptionValue, ParamsInfo, ParamsDefaultInfo)
3466 )
3467
3468 if re.match("^auto$", ParamsOptionValue, re.I):
3469 _ProcessOptionOpenMMAnnealingParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue)
3470 return ParamsInfo
3471
3472 for Index in range(0, len(ParamsOptionValueWords), 2):
3473 Name = ParamsOptionValueWords[Index].strip()
3474 Value = ParamsOptionValueWords[Index + 1].strip()
3475
3476 ParamName = CanonicalParamNamesMap[Name.lower()]
3477 ParamValue = Value
3478
3479 if re.match("^(InitialStart|InitialEnd|CycleEnd)$", ParamName, re.I):
3480 if not MiscUtil.IsFloat(Value):
3481 MiscUtil.PrintError(
3482 'The parameter value, %s, specified for parameter name, %s, using "%s" option must be a float.\n'
3483 % (Value, ParamName, ParamsOptionName)
3484 )
3485 Value = float(Value)
3486 if Value < 0:
3487 MiscUtil.PrintError(
3488 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. Supported values: > 0\n'
3489 % (ParamValue, ParamName, ParamsOptionName)
3490 )
3491 ParamValue = Value
3492 elif re.match("^(InitialChange|CycleChange)$", ParamName, re.I):
3493 if not MiscUtil.IsFloat(Value):
3494 MiscUtil.PrintError(
3495 'The parameter value, %s, specified for parameter name, %s, using "%s" option must be a float.\n'
3496 % (Value, ParamName, ParamsOptionName)
3497 )
3498 Value = float(Value)
3499 if Value <= 0:
3500 MiscUtil.PrintError(
3501 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. Supported values: > 0\n'
3502 % (ParamValue, ParamName, ParamsOptionName)
3503 )
3504 ParamValue = Value
3505 elif re.match("^CycleStart$", ParamName, re.I):
3506 if not re.match("^auto$", Value, re.I):
3507 if not MiscUtil.IsFloat(Value):
3508 MiscUtil.PrintError(
3509 'The parameter value, %s, specified for parameter name, %s, using "%s" option must be a float.\n'
3510 % (Value, ParamName, ParamsOptionName)
3511 )
3512 Value = float(Value)
3513 if Value < 0:
3514 MiscUtil.PrintError(
3515 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. Supported values: > 0\n'
3516 % (ParamValue, ParamName, ParamsOptionName)
3517 )
3518 ParamValue = Value
3519 elif re.match(
3520 "^(InitialSteps|InitialEquilibrationSteps|Cycles|CycleSteps|CycleEquilibrationSteps|FinalEquilibrationSteps)$",
3521 ParamName,
3522 re.I,
3523 ):
3524 if not MiscUtil.IsInteger(Value):
3525 MiscUtil.PrintError(
3526 'The parameter value, %s, specified for parameter name, %s, using "%s" option must be a integer.\n'
3527 % (Value, ParamName, ParamsOptionName)
3528 )
3529 Value = int(Value)
3530 if Value <= 0:
3531 MiscUtil.PrintError(
3532 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. Supported values: > 0\n'
3533 % (ParamValue, ParamName, ParamsOptionName)
3534 )
3535 ParamValue = Value
3536 else:
3537 ParamValue = Value
3538
3539 # Set value...
3540 ParamsInfo[ParamName] = ParamValue
3541
3542 # Handle parameters with possible auto values...
3543 _ProcessOptionOpenMMAnnealingParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue)
3544
3545 return ParamsInfo
3546
3547
3548 def _ProcessOptionOpenMMAnnealingParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue):
3549 """Process parameters with possible auto values and perform validation."""
3550
3551 ParamName = "CycleStart"
3552 ParamValue = "%s" % ParamsInfo[ParamName]
3553 if re.match("^auto$", ParamValue, re.I):
3554 ParamsInfo[ParamName] = ParamsInfo["InitialEnd"]
3555
3556 if ParamsInfo["InitialStart"] >= ParamsInfo["InitialEnd"]:
3557 MiscUtil.PrintError(
3558 'The parameter value, %s, specified for parameter name, initialStart, must be less than value, %s, specified for parameter name, initialEnd, using "%s" option.\n'
3559 % (ParamsInfo["InitialStart"], ParamsInfo["InitialEnd"], ParamsOptionName)
3560 )
3561
3562 if ParamsInfo["CycleStart"] >= ParamsInfo["CycleEnd"]:
3563 MiscUtil.PrintError(
3564 'The parameter value, %s, specified for parameter name, cycleStart, must be less than value, %s, specified for parameter name, cycleEnd, using "%s" option.\n'
3565 % (ParamsInfo["CycleStart"], ParamsInfo["CycleEnd"], ParamsOptionName)
3566 )
3567
3568 if ParamsInfo["CycleStart"] != ParamsInfo["InitialEnd"]:
3569 MiscUtil.PrintError(
3570 'The parameter value, %s, specified for parameter name, cycleStart, must be equal to value, %s, specified for parameter name, initialEndEnd, using "%s" option.\n'
3571 % (ParamsInfo["CycleStart"], ParamsInfo["InitialEnd"], ParamsOptionName)
3572 )
3573
3574 if ParamsInfo["InitialChange"] >= (ParamsInfo["InitialEnd"] - ParamsInfo["InitialStart"]):
3575 MiscUtil.PrintError(
3576 'The parameter value, %s, specified for parameter name, initialChange, must be less than value, %s, corresponding to the difference between values specified for parameter names, initialStart and initialEnd, using "%s" option.\n'
3577 % (ParamsInfo["InitialChange"], (ParamsInfo["InitialEnd"] - ParamsInfo["InitialStart"]), ParamsOptionName)
3578 )
3579
3580 if ParamsInfo["CycleChange"] >= (ParamsInfo["CycleEnd"] - ParamsInfo["CycleStart"]):
3581 MiscUtil.PrintError(
3582 'The parameter value, %s, specified for parameter name, cycleChange, must be less than value, %s, corresponding to the difference between values specified for parameter names, cycleStart and cycleEnd, using "%s" option.\n'
3583 % (ParamsInfo["CycleChange"], (ParamsInfo["CycleEnd"] - ParamsInfo["CycleStart"]), ParamsOptionName)
3584 )
3585
3586
3587 def ProcessOptionOpenMMMDProtocolParameters(ParamsOptionName, ParamsOptionValue, ParamsDefaultInfo=None):
3588 """Process parameters for MD protocol option and return a map containing
3589 processed parameter names and values.
3590
3591 ParamsOptionValue is a comma delimited list of parameter name and value pairs
3592 to setup platform.
3593
3594 The supported parameter names along with their default values for
3595 different platforms are shown below:
3596
3597 Phase1 - Initial heating parameters (NVT simulation):
3598
3599 phase1, yes [ Possible values: yes or no ]
3600 phase1InitialStart, 0.0 [ Units: kelvin ]
3601 phase1InitialEnd, 300.0 [ Units: kelvin ]
3602 phase1InitialChange, 5.0 [ Units: kelvin ]
3603 phase1InitialSteps, 5000
3604
3605 phase1InitialEquilibrationSteps, 100000
3606
3607 Phase2 - Heating and cooling cycles parameters (NVT simulation):
3608
3609 phase2, yes [ Possible values: yes or no ]
3610 phase2Cycles, 1
3611 phase2CycleStart, auto [ Units: kelvin. The default value is set to
3612 initialEnd ]
3613 phase2CycleEnd, 315.0 [ Units: kelvin ]
3614 phase2CycleChange, 1.0 [ Units: kelvin ]
3615 phase2CycleSteps, 1000
3616
3617 phase2CycleEquilibrationSteps, 100000
3618
3619 Phase3 - NVT equilibration parameters:
3620
3621 phase3, yes [ Possible values: yes or no ]
3622 phase3Steps, 200000
3623
3624 Phase4 - NPT equilibration parameters:
3625
3626 phase4, yes [ Possible values: yes or no ]
3627 phase4Steps, 200000
3628
3629 Phase5 - NPT production parameters:
3630
3631 phase5, yes [ Possible values: yes or no ]
3632 phase5Steps, 1000000
3633 phase5StepSize, auto [ Units: fs; Default value: Same as stepSize
3634 parameter in integratorParams option. ]
3635
3636 A brief description of parameters is provided below:
3637
3638 Phase1 - Initial heating parameters (NVT simulation):
3639
3640 phase1: Execute phase1.
3641 phase1InitialStart: Start temperature for initial heating.
3642 phase1InitialEnd: End temperature for initial heating.
3643 phas1InitialChange: Temperature change for increasing temperature
3644 during initial heating.
3645 phase1InitialSteps: Number of simulation steps after each
3646 heating step during initial heating
3647
3648 phase1InitialEquilibrationSteps: Number of equilibration steps
3649 after the completion of initial heating.
3650
3651 Phase2 - Heating and cooling cycles parameters (NVT simulation):
3652
3653 phase2: Execute phase2.
3654 phase2Cycles: Number of annealing cycles to perform. Each cycle
3655 consists of a heating and a cooling phase. The heating phase
3656 consists of the following steps: Heat system from start to
3657 end temperature using change size and perform simulation for a
3658 number of steps after each increase in temperature; Perform
3659 equilibration after the completion of heating. The cooling
3660 phase is reverse of the heating phase and cools the system
3661 from end to start temperature.
3662
3663 phase2CycleStart: Start temperature for annealing cycle.
3664 phase2CycleEnd: End temperature for annealing cycle.
3665 phase2CycleChange: Temperature change for increasing or decreasing
3666 temperature during annealing cycle.
3667 phase2CycleSteps: Number of simulation steps after each heating and
3668 cooling step during annealing cycle.
3669
3670 phase2CycleEquilibrationSteps: Number of equilibration steps
3671 after the completion of heating and cooling phase during a
3672 annealing cycle.
3673
3674 Phase3 - NVT equilibration parameters:
3675
3676 phase3: Execute phase3.
3677 phase3Steps: Number of NVT equilibration steps.
3678
3679 Phase4 - NPT equilibration parameters:
3680
3681 phase4: Execute phase4.
3682 phase4Steps: Number of NPT equilibration steps.
3683
3684 Phase5 - NPT production parameters:
3685
3686 phase5: Execute phase5
3687 phase5Steps: Number of NPT production steps.
3688 phase5StepSize: Simulation time step size for NPT production.
3689
3690 Arguments:
3691 ParamsOptionName (str): Command line OpenMM MD protocol option name.
3692 ParamsOptionValues (str): Space delimited list of parameter name and value pairs.
3693 ParamsDefaultInfo (dict): Default values to override for selected parameters.
3694
3695 Returns:
3696 dictionary: Processed parameter name and value pairs.
3697
3698 """
3699
3700 ParamsInfo = {
3701 "Phase1": True,
3702 "Phase1InitialStart": 0.0,
3703 "Phase1InitialEnd": 300.0,
3704 "Phase1InitialChange": 5.0,
3705 "Phase1InitialSteps": 5000,
3706 "Phase1InitialEquilibrationSteps": 100000,
3707 "Phase2": True,
3708 "Phase2Cycles": 1,
3709 "Phase2CycleStart": "auto",
3710 "Phase2CycleEnd": 315.0,
3711 "Phase2CycleChange": 1.0,
3712 "Phase2CycleSteps": 1000,
3713 "Phase2CycleEquilibrationSteps": 100000,
3714 "Phase3": True,
3715 "Phase3Steps": 200000,
3716 "Phase4": True,
3717 "Phase4Steps": 200000,
3718 "Phase5": True,
3719 "Phase5Steps": 1000000,
3720 "Phase5StepSize": "auto",
3721 }
3722
3723 (ValidParamNames, CanonicalParamNamesMap, ParamsOptionValue, ParamsOptionValueWords) = (
3724 _ValidateAndCanonicalizeParameterNames(ParamsOptionName, ParamsOptionValue, ParamsInfo, ParamsDefaultInfo)
3725 )
3726
3727 if re.match("^auto$", ParamsOptionValue, re.I):
3728 _ProcessOptionOpenMMMDProtocolParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue)
3729 return ParamsInfo
3730
3731 for Index in range(0, len(ParamsOptionValueWords), 2):
3732 Name = ParamsOptionValueWords[Index].strip()
3733 Value = ParamsOptionValueWords[Index + 1].strip()
3734
3735 ParamName = CanonicalParamNamesMap[Name.lower()]
3736 ParamValue = Value
3737
3738 if re.match("^(Phase1|Phase2|Phase3|Phase4|Phase5)$", ParamName, re.I):
3739 if not re.match("^(yes|no|true|false)$", Value, re.I):
3740 MiscUtil.PrintError(
3741 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. Supported values: yes or no'
3742 % (Value, Name, ParamsOptionName)
3743 )
3744 ParamValue = True if re.match("^(yes|true)$", Value, re.I) else False
3745 elif re.match("^(Phase1InitialStart|Phase1InitialEnd|Phase2CycleEnd)$", ParamName, re.I):
3746 if not MiscUtil.IsFloat(Value):
3747 MiscUtil.PrintError(
3748 'The parameter value, %s, specified for parameter name, %s, using "%s" option must be a float.\n'
3749 % (Value, ParamName, ParamsOptionName)
3750 )
3751 Value = float(Value)
3752 if Value < 0:
3753 MiscUtil.PrintError(
3754 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. Supported values: > 0\n'
3755 % (ParamValue, ParamName, ParamsOptionName)
3756 )
3757 ParamValue = Value
3758 elif re.match("^(Phase1InitialChange|Phase2CycleChange)$", ParamName, re.I):
3759 if not MiscUtil.IsFloat(Value):
3760 MiscUtil.PrintError(
3761 'The parameter value, %s, specified for parameter name, %s, using "%s" option must be a float.\n'
3762 % (Value, ParamName, ParamsOptionName)
3763 )
3764 Value = float(Value)
3765 if Value <= 0:
3766 MiscUtil.PrintError(
3767 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. Supported values: > 0\n'
3768 % (ParamValue, ParamName, ParamsOptionName)
3769 )
3770 ParamValue = Value
3771 elif re.match("^Phase2CycleStart$", ParamName, re.I):
3772 if not re.match("^auto$", Value, re.I):
3773 if not MiscUtil.IsFloat(Value):
3774 MiscUtil.PrintError(
3775 'The parameter value, %s, specified for parameter name, %s, using "%s" option must be a float.\n'
3776 % (Value, ParamName, ParamsOptionName)
3777 )
3778 Value = float(Value)
3779 if Value < 0:
3780 MiscUtil.PrintError(
3781 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. Supported values: > 0\n'
3782 % (ParamValue, ParamName, ParamsOptionName)
3783 )
3784 ParamValue = Value
3785 elif re.match(
3786 "^(Phase1InitialSteps|Phase1InitialEquilibrationSteps|Phase2Cycles|Phase2CycleSteps|Phase2CycleEquilibrationSteps|Phase3Steps|Phase4Steps|Phase5Steps|Phase5StepSize)$",
3787 ParamName,
3788 re.I,
3789 ):
3790 if not MiscUtil.IsInteger(Value):
3791 MiscUtil.PrintError(
3792 'The parameter value, %s, specified for parameter name, %s, using "%s" option must be a integer.\n'
3793 % (Value, ParamName, ParamsOptionName)
3794 )
3795 Value = int(Value)
3796 if Value <= 0:
3797 MiscUtil.PrintError(
3798 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. Supported values: > 0\n'
3799 % (ParamValue, ParamName, ParamsOptionName)
3800 )
3801 ParamValue = Value
3802 else:
3803 ParamValue = Value
3804
3805 # Set value...
3806 ParamsInfo[ParamName] = ParamValue
3807
3808 # Handle parameters with possible auto values...
3809 _ProcessOptionOpenMMMDProtocolParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue)
3810
3811 return ParamsInfo
3812
3813
3814 def _ProcessOptionOpenMMMDProtocolParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue):
3815 """Process parameters with possible auto values and perform validation."""
3816
3817 ParamName = "Phase2CycleStart"
3818 ParamValue = "%s" % ParamsInfo[ParamName]
3819 if re.match("^auto$", ParamValue, re.I):
3820 ParamsInfo[ParamName] = ParamsInfo["Phase1InitialEnd"]
3821
3822 ParamName = "Phase5StepSize"
3823 ParamValue = "%s" % ParamsInfo[ParamName]
3824 if re.match("^auto$", ParamValue, re.I):
3825 # Set Phase5StepSize to None to use StepSize specifieid using --integratiorParams option...
3826 ParamsInfo[ParamName] = None
3827
3828 if ParamsInfo["Phase1InitialStart"] >= ParamsInfo["Phase1InitialEnd"]:
3829 MiscUtil.PrintError(
3830 'The parameter value, %s, specified for parameter name, phase1InitialStart, must be less than value, %s, specified for parameter name, phase1InitialEnd, using "%s" option.\n'
3831 % (ParamsInfo["Phase1InitialStart"], ParamsInfo["Phase1InitialEnd"], ParamsOptionName)
3832 )
3833
3834 if ParamsInfo["Phase2CycleStart"] >= ParamsInfo["Phase2CycleEnd"]:
3835 MiscUtil.PrintError(
3836 'The parameter value, %s, specified for parameter name, phase2CycleStart, must be less than value, %s, specified for parameter name, phase2CycleEnd, using "%s" option.\n'
3837 % (ParamsInfo["Phase2CycleStart"], ParamsInfo["Phase2CycleEnd"], ParamsOptionName)
3838 )
3839
3840 if ParamsInfo["Phase2CycleStart"] != ParamsInfo["Phase1InitialEnd"]:
3841 MiscUtil.PrintError(
3842 'The parameter value, %s, specified for parameter name, phase2CycleStart, must be equal to value, %s, specified for parameter name, phase1InitialEndEnd, using "%s" option.\n'
3843 % (ParamsInfo["Phase2CycleStart"], ParamsInfo["Phase1InitialEnd"], ParamsOptionName)
3844 )
3845
3846 if ParamsInfo["Phase1InitialChange"] >= (ParamsInfo["Phase1InitialEnd"] - ParamsInfo["Phase1InitialStart"]):
3847 MiscUtil.PrintError(
3848 'The parameter value, %s, specified for parameter name, phase2InitialChange, must be less than value, %s, corresponding to the difference between values specified for parameter names, phase1InitialStart and phase1InitialEnd, using "%s" option.\n'
3849 % (
3850 ParamsInfo["Phase1InitialChange"],
3851 (ParamsInfo["Phase1InitialEnd"] - ParamsInfo["Phase1InitialStart"]),
3852 ParamsOptionName,
3853 )
3854 )
3855
3856 if ParamsInfo["Phase2CycleChange"] >= (ParamsInfo["Phase2CycleEnd"] - ParamsInfo["Phase2CycleStart"]):
3857 MiscUtil.PrintError(
3858 'The parameter value, %s, specified for parameter name, phase2CycleChange, must be less than value, %s, corresponding to the difference between values specified for parameter names, phase2CycleStart and Phase2CycleEnd, using "%s" option.\n'
3859 % (
3860 ParamsInfo["Phase2CycleChange"],
3861 (ParamsInfo["Phase2CycleEnd"] - ParamsInfo["Phase2CycleStart"]),
3862 ParamsOptionName,
3863 )
3864 )
3865
3866
3867 def ProcessOptionOpenMMPlatformParameters(ParamsOptionName, ParamsOptionValue, ParamsDefaultInfo=None):
3868 """Process parameters for platform option and return a map containing processed
3869 parameter names and values.
3870
3871 ParamsOptionValue is a comma delimited list of parameter name and value pairs
3872 to setup platform.
3873
3874 The supported parameter names along with their default values for
3875 different platforms are shown below:
3876
3877 CPU:
3878
3879 threads, 1 [ Possible value: >= 0 or auto. The value of 'auto'
3880 or zero implies the use of all available CPUs for threading. ]
3881
3882 CUDA:
3883
3884 deviceIndex, auto [ Possible values: 0, '0 1' etc. ]
3885 deterministicForces, auto [ Possible values: yes or no ]
3886 precision, single [ Possible values: single, double, or mix ]
3887 tempDirectory, auto [ Possible value: DirName ]
3888 useBlockingSync, auto [ Possible values: yes or no ]
3889 useCpuPme, auto [ Possible values: yes or no ]
3890
3891 OpenCL:
3892
3893 deviceIndex, auto [ Possible values: 0, '0 1' etc. ]
3894 openCLPlatformIndex, auto [ Possible value: Number]
3895 precision, single [ Possible values: single, double, or mix ]
3896 useCpuPme, auto [ Possible values: yes or no ]
3897
3898 A brief description of parameters is provided below:
3899
3900 CPU:
3901
3902 threads: Number of threads to use for simulation.
3903
3904 CUDA:
3905
3906 deviceIndex: Space delimited list of device indices to use for
3907 calculations.
3908 deterministicForces: Generate reproducible results at the cost of a
3909 small decrease in performance.
3910 precision: Number precision to use for calculations.
3911 tempDirectory: Directory name for storing temporary files.
3912 useBlockingSync: Control run-time synchronization between CPU and
3913 GPU.
3914 useCpuPme: Use CPU-based PME implementation.
3915
3916 OpenCL:
3917
3918 deviceIndex: Space delimited list of device indices to use for
3919 simulation.
3920 openCLPlatformIndex: Platform index to use for calculations.
3921 precision: Number precision to use for calculations.
3922 useCpuPme: Use CPU-based PME implementation.
3923
3924 Arguments:
3925 ParamsOptionName (str): Command line OpenMM platform option name.
3926 ParamsOptionValues (str): Space delimited list of parameter name and value pairs.
3927 ParamsDefaultInfo (dict): Default values to override for selected parameters.
3928
3929 Returns:
3930 dictionary: Processed parameter name and value pairs.
3931
3932 """
3933
3934 ParamsInfo = {
3935 "Name": "CPU",
3936 "Threads": "auto",
3937 "DeviceIndex": "auto",
3938 "DeterministicForces": "auto",
3939 "Precision": "single",
3940 "TempDirectory": "auto",
3941 "UseBlockingSync": "auto",
3942 "UseCpuPme": "auto",
3943 "OpenCLPlatformIndex": "auto",
3944 }
3945
3946 (ValidParamNames, CanonicalParamNamesMap, ParamsOptionValue, ParamsOptionValueWords) = (
3947 _ValidateAndCanonicalizeParameterNames(ParamsOptionName, ParamsOptionValue, ParamsInfo, ParamsDefaultInfo)
3948 )
3949
3950 if re.match("^auto$", ParamsOptionValue, re.I):
3951 _ProcessOptionOpenMMPlatformParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue)
3952 return ParamsInfo
3953
3954 for Index in range(0, len(ParamsOptionValueWords), 2):
3955 Name = ParamsOptionValueWords[Index].strip()
3956 Value = ParamsOptionValueWords[Index + 1].strip()
3957
3958 ParamName = CanonicalParamNamesMap[Name.lower()]
3959 ParamValue = Value
3960
3961 if re.match("^Name$", ParamName, re.I):
3962 if not re.match("^(CPU|CUDA|OpenCL|Reference)$", Value, re.I):
3963 MiscUtil.PrintError(
3964 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. Supported values: CPU, GPU, OpenCL, or Reference'
3965 % (Value, Name, ParamsOptionName)
3966 )
3967 ParamValue = Value
3968 elif re.match("^Threads$", ParamName, re.I):
3969 if not re.match("^auto$", Value, re.I):
3970 if not MiscUtil.IsInteger(Value):
3971 MiscUtil.PrintError(
3972 'The parameter value, %s, specified for parameter name, %s, using "%s" option must be an integer.\n'
3973 % (Value, ParamName, ParamsOptionName)
3974 )
3975 Value = int(Value)
3976 if Value < 0:
3977 MiscUtil.PrintError(
3978 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. Supported values: >=0 \n'
3979 % (ParamValue, ParamName, ParamsOptionName)
3980 )
3981 if Value > mp.cpu_count():
3982 MiscUtil.PrintError(
3983 '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'
3984 % (ParamValue, ParamName, ParamsOptionName, mp.cpu_count())
3985 )
3986 ParamValue = "%s" % Value
3987 elif re.match("^Precision$", ParamName, re.I):
3988 if not re.match("^(Single|Double|Mix)$", Value, re.I):
3989 MiscUtil.PrintError(
3990 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. Supported values: single, double or mix'
3991 % (Value, Name, ParamsOptionName)
3992 )
3993 ParamValue = Value.lower()
3994 elif re.match("^(DeterministicForces|UseBlockingSync|UseCpuPme)$", ParamName, re.I):
3995 if not re.match("^auto$", Value, re.I):
3996 if not re.match("^(yes|no|true|false)$", Value, re.I):
3997 MiscUtil.PrintError(
3998 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. Supported values: yes or no'
3999 % (Value, Name, ParamsOptionName)
4000 )
4001 ParamValue = "true" if re.match("^(yes|true)$", Value, re.I) else "false"
4002 elif re.match("^(DeviceIndex|openCLPlatformIndex)$", ParamName, re.I):
4003 if not re.match("^auto$", Value, re.I):
4004 DeviceIndices = Value.split()
4005 if len(DeviceIndices) == 0:
4006 MiscUtil.PrintError(
4007 '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'
4008 % (Value, ParamName, ParamsOptionName)
4009 )
4010 for DeviceIndex in DeviceIndices:
4011 if not MiscUtil.IsInteger(DeviceIndex):
4012 MiscUtil.PrintError(
4013 'The parameter value, %s, specified for parameter name, %s, using "%s" option must be an integer.\n'
4014 % (DeviceIndex, ParamName, ParamsOptionName)
4015 )
4016 ParamValue = ",".join(DeviceIndices)
4017 elif re.match("^TempDirectory$", ParamName, re.I):
4018 if not re.match("^auto$", Value, re.I):
4019 if not os.path.isdir(Value):
4020 MiscUtil.PrintError(
4021 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. The specified directory doesn\'t exists.'
4022 % (Value, Name, ParamsOptionName)
4023 )
4024 ParamValue = Value
4025 else:
4026 ParamValue = Value
4027
4028 # Set value...
4029 ParamsInfo[ParamName] = ParamValue
4030
4031 # Handle parameters with possible auto values...
4032 _ProcessOptionOpenMMPlatformParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue)
4033
4034 return ParamsInfo
4035
4036
4037 def _ProcessOptionOpenMMPlatformParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue):
4038 """Process parameters with possible auto values and perform validation."""
4039
4040 ParamValueMap = {"cpu": "CPU", "cuda": "CUDA", "opencl": "OpenCL", "reference": "Reference"}
4041 ParamName = "Name"
4042 ParamValue = ParamsInfo[ParamName].lower()
4043 if ParamValue in ParamValueMap:
4044 ParamsInfo[ParamName] = ParamValueMap[ParamValue]
4045
4046 ParamsInfo["Precision"] = ParamsInfo["Precision"].lower()
4047
4048 # Set "auto" values to None and treat all other values as strings...
4049 for ParamName in ParamsInfo:
4050 ParamValue = "%s" % ParamsInfo[ParamName]
4051 if re.match("^auto$", ParamValue, re.I):
4052 ParamsInfo[ParamName] = None
4053 else:
4054 ParamsInfo[ParamName] = ParamValue
4055
4056
4057 def ProcessOptionOpenMMWaterBoxParameters(ParamsOptionName, ParamsOptionValue, ParamsDefaultInfo=None):
4058 """Process parameters for adding a water box option and return a map containing
4059 processed parameter names and values.
4060
4061 ParamsOptionValue is a comma delimited list of parameter name and value pairs
4062 for adding a water box.
4063
4064 The supported parameter names along with their default and possible
4065 values are shown below:
4066
4067 model, tip3p [ Possible values: tip3p, spce, tip4pew, tip5p or swm4ndp ]
4068 mode, Padding [ Possible values: Size or Padding ]
4069 size, None [ Possible values: xsize ysize zsize ]
4070 padding, 1.0
4071 shape, cube [ Possible values: cube, dodecahedron, or octahedron ]
4072 ionPositive, Na+ [ Possible values: Li+, Na+, K+, Rb+, or Cs+ ]
4073 ionNegative, Cl- [ Possible values: Cl-, Br-, F-, or I- ]
4074 ionicStrength, 0.0
4075
4076 A brief description of parameters is provided below:
4077
4078 model: Water model to use for adding water box.
4079
4080 mode: Specify the size of the waterbox explicitly or calculate it automatically
4081 for a macromolecule along with adding padding around macromolecule.
4082 Possible values: Size or Padding.
4083
4084 size: A space delimited triplet of values corresponding to water size in
4085 nanometers. It must be specified during 'Size' value of 'mode' parameter.
4086
4087 padding: Padding around macromolecule in nanometers for filling box with
4088 water. It must be specified during 'Padding' value of 'mode' parameter.
4089
4090 ionPositive: Type of positive ion to add during the addition of a water box.
4091
4092 ionNegative: Type of negative ion to add during the addition of a water box.
4093
4094 ionicStrength: Total concentration (molar) of both positive and negative ions
4095 to add excluding he ions added to neutralize the system during the addition
4096 of a water box.
4097
4098 Arguments:
4099 ParamsOptionName (str): Command line OpenMM water box option name.
4100 ParamsOptionValues (str): Space delimited list of parameter name and value pairs.
4101 ParamsDefaultInfo (dict): Default values to override for selected parameters.
4102
4103 Returns:
4104 dictionary: Processed parameter name and value pairs.
4105
4106 """
4107
4108 ParamsInfo = {
4109 "Model": "tip3p",
4110 "Mode": "Padding",
4111 "Size": None,
4112 "Padding": 1.0,
4113 "Shape": "cube",
4114 "IonPositive": "Na+",
4115 "IonNegative": "Cl-",
4116 "IonicStrength": 0.0,
4117 }
4118
4119 (ValidParamNames, CanonicalParamNamesMap, ParamsOptionValue, ParamsOptionValueWords) = (
4120 _ValidateAndCanonicalizeParameterNames(ParamsOptionName, ParamsOptionValue, ParamsInfo, ParamsDefaultInfo)
4121 )
4122
4123 if re.match("^auto$", ParamsOptionValue, re.I):
4124 _ProcessOptionOpenMMWaterBoxParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue)
4125 return ParamsInfo
4126
4127 for Index in range(0, len(ParamsOptionValueWords), 2):
4128 Name = ParamsOptionValueWords[Index].strip()
4129 Value = ParamsOptionValueWords[Index + 1].strip()
4130
4131 ParamName = CanonicalParamNamesMap[Name.lower()]
4132 ParamValue = Value
4133
4134 if re.match("^Model$", ParamName, re.I):
4135 if not re.match("^(tip3p|spce|tip4pew|tip5p|swm4ndp)$", Value, re.I):
4136 MiscUtil.PrintError(
4137 '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'
4138 % (Value, Name, ParamsOptionName)
4139 )
4140 ParamValue = Value.lower()
4141 elif re.match("^Mode$", ParamName, re.I):
4142 if not re.match("^(Padding|Size)$", Value, re.I):
4143 MiscUtil.PrintError(
4144 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. Supported values: Padding or Size'
4145 % (Value, Name, ParamsOptionName)
4146 )
4147 ParamValue = Value
4148 elif re.match("^Size$", ParamName, re.I):
4149 if Value is not None and not re.match("^None$", Value, re.I):
4150 SizeValues = Value.split()
4151 if len(SizeValues) != 3:
4152 MiscUtil.PrintError(
4153 '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'
4154 % (Value, ParamName, ParamsOptionName)
4155 )
4156
4157 SizeValueList = []
4158 for SizeValue in SizeValues:
4159 if not MiscUtil.IsFloat(SizeValue):
4160 MiscUtil.PrintError(
4161 'The parameter value, %s, specified for parameter name, %s, using "%s" option must be a float.\n'
4162 % (SizeValue, ParamName, ParamsOptionName)
4163 )
4164 SizeValue = float(SizeValue)
4165 if SizeValue <= 0:
4166 MiscUtil.PrintError(
4167 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. Supported values: > 0\n'
4168 % (SizeValue, ParamName, ParamsOptionName)
4169 )
4170 SizeValueList.append(SizeValue)
4171
4172 # Set size values...
4173 ParamsInfo["SizeList"] = SizeValueList
4174
4175 ParamValue = Value
4176 elif re.match("^Padding$", ParamName, re.I):
4177 if not MiscUtil.IsFloat(Value):
4178 MiscUtil.PrintError(
4179 'The parameter value, %s, specified for parameter name, %s, using "%s" option must be a float.\n'
4180 % (Value, ParamName, ParamsOptionName)
4181 )
4182 Value = float(Value)
4183 if Value <= 0:
4184 MiscUtil.PrintError(
4185 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. Supported values: > 0\n'
4186 % (ParamValue, ParamName, ParamsOptionName)
4187 )
4188 ParamValue = Value
4189 elif re.match("^Shape$", ParamName, re.I):
4190 if not re.match("^(cube|dodecahedron|octahedron)$", Value, re.I):
4191 MiscUtil.PrintError(
4192 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. Supported values: cube, dodecahedron, or octahedron'
4193 % (Value, Name, ParamsOptionName)
4194 )
4195 ParamValue = Value.lower()
4196 elif re.match("^IonPositive$", ParamName, re.I):
4197 ValidValues = "Li+ Na+ K+ Rb+ Cs+"
4198 EscapedValidValuesPattern = r"Li\+|Na\+|K\+|Rb\+|Cs\+"
4199 if not re.match("^(%s)$" % EscapedValidValuesPattern, Value):
4200 MiscUtil.PrintError(
4201 'The value specified, %s, for parameter name, %s, using "%s" option is not a valid. Supported value(s): %s'
4202 % (ParamValue, ParamName, ParamsOptionName, ValidValues)
4203 )
4204 ParamValue = Value
4205 elif re.match("^IonNegative$", ParamName, re.I):
4206 ValidValues = "F- Cl- Br- I-"
4207 ValidValuesPattern = "F-|Cl-|Br-|I-"
4208 if not re.match("^(%s)$" % ValidValuesPattern, Value):
4209 MiscUtil.PrintError(
4210 'The value specified, %s, for parameter name, %s, using "%s" option is not a valid. Supported value(s): %s'
4211 % (ParamValue, ParamName, ParamsOptionName, ValidValues)
4212 )
4213 ParamValue = Value
4214 elif re.match("^IonicStrength$", ParamName, re.I):
4215 if not MiscUtil.IsFloat(Value):
4216 MiscUtil.PrintError(
4217 'The parameter value, %s, specified for parameter name, %s, using "%s" option must be a float.\n'
4218 % (Value, ParamName, ParamsOptionName)
4219 )
4220 Value = float(Value)
4221 if Value < 0:
4222 MiscUtil.PrintError(
4223 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. Supported values: >= 0\n'
4224 % (ParamValue, ParamName, ParamsOptionName)
4225 )
4226 ParamValue = Value
4227 else:
4228 ParamValue = Value
4229
4230 # Set value...
4231 ParamsInfo[ParamName] = ParamValue
4232
4233 # Handle parameters with possible auto values...
4234 _ProcessOptionOpenMMWaterBoxParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue)
4235
4236 return ParamsInfo
4237
4238
4239 def _ProcessOptionOpenMMWaterBoxParameters(ParamsInfo, ParamsOptionName, ParamsOptionValue):
4240 """Process parameters with possible auto values and perform validation."""
4241
4242 ParamsInfo["ModeSize"] = True if re.match("^Size$", ParamsInfo["Mode"], re.I) else False
4243 ParamsInfo["ModePadding"] = True if re.match("^Padding$", ParamsInfo["Mode"], re.I) else False
4244
4245 if ParamsInfo["ModeSize"]:
4246 ParamName = "Size"
4247 ParamValue = ParamsInfo[ParamName]
4248 if ParamValue is None:
4249 MiscUtil.PrintError(
4250 'The parameter value, %s, specified for parameter name, %s, using "%s" option is not a valid value. Supported values: x y z\n'
4251 % (ParamValue, ParamName, ParamsOptionName)
4252 )
4253 else:
4254 ParamsInfo["SizeList"] = None
4255
4256
4257 def _ValidateAndCanonicalizeParameterNames(ParamsOptionName, ParamsOptionValue, ParamsInfo, ParamsDefaultInfo):
4258 """Validate and canonicalize parameter names."""
4259
4260 # Setup a canonical paramater names...
4261 ValidParamNames = []
4262 CanonicalParamNamesMap = {}
4263 for ParamName in sorted(ParamsInfo):
4264 ValidParamNames.append(ParamName)
4265 CanonicalParamNamesMap[ParamName.lower()] = ParamName
4266
4267 # Update default values...
4268 if ParamsDefaultInfo is not None:
4269 for ParamName in ParamsDefaultInfo:
4270 if ParamName not in ParamsInfo:
4271 MiscUtil.PrintError(
4272 'The default parameter name, %s, specified using "%s" option is not a valid name. Supported parameter names: %s'
4273 % (ParamName, ParamsDefaultInfo, " ".join(ValidParamNames))
4274 )
4275 ParamsInfo[ParamName] = ParamsDefaultInfo[ParamName]
4276
4277 ParamsOptionValue = ParamsOptionValue.strip()
4278 if not ParamsOptionValue:
4279 MiscUtil.PrintError('No valid parameter name and value pairs specified using "%s" option' % ParamsOptionName)
4280
4281 ParamsOptionValueWords = None
4282 if not re.match("^auto$", ParamsOptionValue, re.I):
4283 ParamsOptionValueWords = ParamsOptionValue.split(",")
4284 if len(ParamsOptionValueWords) % 2:
4285 MiscUtil.PrintError(
4286 'The number of comma delimited paramater names and values, %d, specified using "%s" option must be an even number.'
4287 % (len(ParamsOptionValueWords), ParamsOptionName)
4288 )
4289
4290 if ParamsOptionValueWords is not None:
4291 for Index in range(0, len(ParamsOptionValueWords), 2):
4292 Name = ParamsOptionValueWords[Index].strip()
4293 CanonicalName = Name.lower()
4294 if CanonicalName not in CanonicalParamNamesMap:
4295 MiscUtil.PrintError(
4296 'The parameter name, %s, specified using "%s" is not a valid name. Supported parameter names: %s'
4297 % (Name, ParamsOptionName, " ".join(ValidParamNames))
4298 )
4299
4300 return (ValidParamNames, CanonicalParamNamesMap, ParamsOptionValue, ParamsOptionValueWords)