Molecular dynamics protocols in HTMD#

In this tutorial, we should how to equilibrate and prepare a system for productive simulations in HTMD.

First, let’s import HTMD:

from htmd.ui import *
from moleculekit.config import config

config(viewer='webgl')
2024-12-05 13:27:36,940 - numexpr.utils - INFO - Note: NumExpr detected 20 cores but "NUMEXPR_MAX_THREADS" not set, so enforcing safe limit of 8.
2024-12-05 13:27:36,940 - numexpr.utils - INFO - NumExpr defaulting to 8 threads.
/home/sdoerr/miniforge3/envs/htmd/lib/python3.10/site-packages/pandas/core/computation/expressions.py:21: UserWarning: Pandas requires version '2.8.4' or newer of 'numexpr' (version '2.7.3' currently installed).
  from pandas.core.computation.check import NUMEXPR_INSTALLED
Please cite HTMD: Doerr et al.(2016)JCTC,12,1845. https://dx.doi.org/10.1021/acs.jctc.6b00049
HTMD Documentation at: https://software.acellera.com/htmd/

You are on the latest HTMD version (2.4.2+20.g74f7135a7.dirty).

Build a sample system#

We need a built system to perform simulations. We can easily build one with:

tryp = Molecule("3PTB")
tryp.filter("protein")
tryp_op = systemPrepare(tryp)
tryp_seg = autoSegment(tryp_op)
tryp_solv = solvate(tryp_seg, pad=10)
2024-12-05 13:27:39,407 - moleculekit.molecule - INFO - Removed 72 atoms. 1629 atoms remaining in the molecule.
---- Molecule chain report ----
Chain A:
    First residue: ILE    16
    Final residue: ASN   245
---- End of chain report ----
2024-12-05 13:27:40,621 - moleculekit.tools.preparation - INFO - Modified residue CYS    22 A to CYX
2024-12-05 13:27:40,621 - moleculekit.tools.preparation - INFO - Modified residue HIS    40 A to HIE
2024-12-05 13:27:40,621 - moleculekit.tools.preparation - INFO - Modified residue CYS    42 A to CYX
2024-12-05 13:27:40,622 - moleculekit.tools.preparation - INFO - Modified residue HIS    57 A to HIP
2024-12-05 13:27:40,622 - moleculekit.tools.preparation - INFO - Modified residue CYS    58 A to CYX
2024-12-05 13:27:40,622 - moleculekit.tools.preparation - INFO - Modified residue HIS    91 A to HID
2024-12-05 13:27:40,622 - moleculekit.tools.preparation - INFO - Modified residue CYS   128 A to CYX
2024-12-05 13:27:40,623 - moleculekit.tools.preparation - INFO - Modified residue CYS   136 A to CYX
2024-12-05 13:27:40,623 - moleculekit.tools.preparation - INFO - Modified residue CYS   157 A to CYX
2024-12-05 13:27:40,624 - moleculekit.tools.preparation - INFO - Modified residue CYS   168 A to CYX
2024-12-05 13:27:40,625 - moleculekit.tools.preparation - INFO - Modified residue CYS   182 A to CYX
2024-12-05 13:27:40,625 - moleculekit.tools.preparation - INFO - Modified residue CYS   191 A to CYX
2024-12-05 13:27:40,625 - moleculekit.tools.preparation - INFO - Modified residue CYS   201 A to CYX
2024-12-05 13:27:40,626 - moleculekit.tools.preparation - INFO - Modified residue CYS   220 A to CYX
2024-12-05 13:27:40,627 - moleculekit.tools.preparation - INFO - Modified residue CYS   232 A to CYX
2024-12-05 13:27:40,628 - moleculekit.tools.preparation - WARNING - Dubious protonation state: the pKa of 4 residues is within 1.0 units of pH 7.4.
2024-12-05 13:27:40,628 - moleculekit.tools.preparation - WARNING - Dubious protonation state:    TYR    39 A (pKa= 8.24)
2024-12-05 13:27:40,629 - moleculekit.tools.preparation - WARNING - Dubious protonation state:    HIS    57 A (pKa= 7.46)
2024-12-05 13:27:40,629 - moleculekit.tools.preparation - WARNING - Dubious protonation state:    GLU    70 A (pKa= 7.06)
2024-12-05 13:27:40,630 - moleculekit.tools.preparation - WARNING - Dubious protonation state:    ASP   189 A (pKa= 6.49)
2024-12-05 13:27:40,640 - moleculekit.tools.autosegment - INFO - Created segment P0 between resid 16 and 245.
2024-12-05 13:27:40,646 - htmd.builder.solvate - INFO - Using water pdb file at: /home/sdoerr/Work/htmd/htmd/share/solvate/wat.pdb
2024-12-05 13:27:40,912 - htmd.builder.solvate - INFO - Replicating 4 water segments, 2 by 1 by 2

2024-12-05 13:27:41,299 - htmd.builder.solvate - INFO - 6943 water molecules were added to the system.
██████████████████████████████████████████████████████████████████████████| 4/4 [00:00<00:00, 11.70it/s]

With this solvated system and since HTMD is force-field agnostic, one can either build in CHARMM or Amber (for details on system building, see the corresponding tutorials):

tryp_amber = amber.build(tryp_solv, outdir='build-amber')
2024-12-05 13:27:42,181 - htmd.builder.amber - INFO - Detecting disulfide bonds.
2024-12-05 13:27:42,195 - htmd.builder.builder - INFO - 6 disulfide bonds were added
Disulfide Bond between: UniqueResidueID<resname: 'CYX', chain: 'A', resid: 26, insertion: '', segid: 'P0'>
                   and: UniqueResidueID<resname: 'CYX', chain: 'A', resid: 42, insertion: '', segid: 'P0'>

Disulfide Bond between: UniqueResidueID<resname: 'CYX', chain: 'A', resid: 117, insertion: '', segid: 'P0'>
                   and: UniqueResidueID<resname: 'CYX', chain: 'A', resid: 184, insertion: '', segid: 'P0'>

Disulfide Bond between: UniqueResidueID<resname: 'CYX', chain: 'A', resid: 174, insertion: '', segid: 'P0'>
                   and: UniqueResidueID<resname: 'CYX', chain: 'A', resid: 198, insertion: '', segid: 'P0'>

Disulfide Bond between: UniqueResidueID<resname: 'CYX', chain: 'A', resid: 149, insertion: '', segid: 'P0'>
                   and: UniqueResidueID<resname: 'CYX', chain: 'A', resid: 163, insertion: '', segid: 'P0'>

Disulfide Bond between: UniqueResidueID<resname: 'CYX', chain: 'A', resid: 8, insertion: '', segid: 'P0'>
                   and: UniqueResidueID<resname: 'CYX', chain: 'A', resid: 138, insertion: '', segid: 'P0'>

Disulfide Bond between: UniqueResidueID<resname: 'CYX', chain: 'A', resid: 110, insertion: '', segid: 'P0'>
                   and: UniqueResidueID<resname: 'CYX', chain: 'A', resid: 211, insertion: '', segid: 'P0'>
2024-12-05 13:27:42,717 - htmd.builder.amber - INFO - Starting the build.
2024-12-05 13:27:43,634 - htmd.builder.amber - INFO - Finished building.
2024-12-05 13:27:46,066 - htmd.builder.ionize - INFO - Adding 7 anions + 0 cations for neutralizing and 0 ions for the given salt concentration 0 M.
2024-12-05 13:27:46,983 - htmd.builder.amber - INFO - Starting the build.
2024-12-05 13:27:47,947 - htmd.builder.amber - INFO - Finished building.
2024-12-05 13:27:50,278 - py.warnings - WARNING - /home/sdoerr/miniforge3/envs/htmd/lib/python3.10/site-packages/Bio/pairwise2.py:278: BiopythonDeprecationWarning: Bio.pairwise2 has been deprecated, and we intend to remove it in a future release of Biopython. As an alternative, please consider using Bio.Align.PairwiseAligner as a replacement, and contact the Biopython developers if you still need the Bio.pairwise2 module.
  warnings.warn(

2024-12-05 13:27:51,311 - moleculekit.tools.sequencestructuralalignment - INFO - Alignment #0 was done on 223 residues: 2-224

Equilibration protocol#

First, let’s import the setup_equilibration function, which is an MD protocol:

from acemd.protocols import setup_equilibration
2024-12-05 13:27:51,810 - rdkit - INFO - Enabling RDKit 2024.03.5 jupyter extensions
2024-12-05 13:27:51,894 - acemd - INFO - # You are on the latest ACEMD version (4.0.1).

The setup_equilibration function has sensible defaults for an equilibration MD simulation but it also allows the user to override any options:

setup_equilibration('./build-amber/', './equil', run="1ns", temperature=300)
2024-12-05 13:27:51,898 - acemd - INFO - Copying ./build-amber/structure.pdb to ./equil/structure.pdb
2024-12-05 13:27:51,900 - acemd - INFO - Copying ./build-amber/structure.prmtop to ./equil/structure.prmtop

One can inspect what the Equilibration object has created with the write method:

%ls equil/
input.yaml  run.sh*  structure.pdb  structure.prmtop

Run the equilibration#

Now, let’s use the queue resources of HTMD to run the simulation. One can use the local computer and the LocalGPUQueue class to submit a job. The equilibration time is short (see above) for demonstration purposes:

local = LocalGPUQueue()
local.submit('./equil/')
local.wait()
2024-12-05 13:28:02,499 - jobqueues.util - INFO - Trying to determine all GPU devices
2024-12-05 13:28:02,548 - jobqueues.localqueue - INFO - Using GPU devices 0
2024-12-05 13:28:02,549 - jobqueues.util - INFO - Trying to determine all GPU devices
2024-12-05 13:28:02,594 - jobqueues.localqueue - INFO - Queueing /home/sdoerr/Work/htmd/tutorials/equil
2024-12-05 13:28:02,596 - jobqueues.localqueue - INFO - Running /home/sdoerr/Work/htmd/tutorials/equil on device 0
2024-12-05 13:31:44,008 - jobqueues.localqueue - INFO - Completed /home/sdoerr/Work/htmd/tutorials/equil

Let’s check which files have been created by the simulation

%ls equil/
input.yaml      minimized.coor  output.xsc       restraint_1.sel
jobqueues.done  output.coor     output.xtc       run.sh*
job.sh*         output.csv      restart.chk      structure.pdb
log.txt         output.vel      restraint_0.sel  structure.prmtop

Production protocol#

Now let’s use the setup_production function and do the same as before to perform a short production MD simulation:

from acemd.protocols import setup_production
setup_production('equil', 'prod', run="1ns", temperature=300)
2024-12-05 13:32:02,746 - acemd - INFO - Copying equil/output.coor to prod/input.coor
2024-12-05 13:32:02,747 - acemd - INFO - Copying equil/output.xsc to prod/input.xsc
2024-12-05 13:32:02,748 - acemd - INFO - Copying equil/structure.prmtop to prod/structure.prmtop
%ls prod/
input.coor  input.xsc  input.yaml  run.sh*  structure.prmtop

Run the production#

local = LocalGPUQueue()
local.submit('./prod/')
local.wait()
2024-12-05 13:32:26,221 - jobqueues.util - INFO - Trying to determine all GPU devices
2024-12-05 13:32:26,275 - jobqueues.localqueue - INFO - Using GPU devices 0
2024-12-05 13:32:26,276 - jobqueues.util - INFO - Trying to determine all GPU devices
2024-12-05 13:32:26,321 - jobqueues.localqueue - INFO - Queueing /home/sdoerr/Work/htmd/tutorials/prod
2024-12-05 13:32:26,323 - jobqueues.localqueue - INFO - Running /home/sdoerr/Work/htmd/tutorials/prod on device 0
2024-12-05 13:35:27,738 - jobqueues.localqueue - INFO - Completed /home/sdoerr/Work/htmd/tutorials/prod

When the above process finished, one can check that a trajectory was produced:

%ls prod/output.xtc
prod/output.xtc

Quickly visualize the trajectory#

traj = Molecule('prod/structure.prmtop')
traj.read('prod/output.xtc')
traj.wrap()
traj.align('protein and name CA')
traj.view()
NGLWidget(max_frame=9)

Note: Waters are not shown for clarity