Overview

This chapter explains the basic structure of MMTK and its view of molecular systems. Every MMTK user should read it at least once.


Using MMTK

MMTK applications are ordinary Python programs, and can be written using any standard text editor. For interactive use it is recommended to use either the special Python mode for the Emacs editor, or one of the Tk-based graphical user interfaces for Python, IDLE (comes with the Python interpreter from version 1.5.2) or PTUI.

MMTK tries to be as user-friendly as possible for interactive use. For example, lengthy calculations can usually be interrupted by typing Control-C. This will result in an error message ("Keyboard Interrupt"), but you can simply go on typing other commands. Interruption is particularly useful for energy minimization and molecular dynamics: you can interrupt the calculation at any time, look at the current state or do some analysis, and then continue.


Modules

MMTK is a package consisting of various modules, most of them written in Python, and some in C for efficiency. The individual modules are described in the Module Reference. The basic definitions that almost every application needs are collected in the top-level module, MMTK. The first line of most applications is therefore

from MMTK import *

The definitions that are specific to particular applications reside in submodules within the package MMTK. For example, force fields are defined in MMTK.ForceFields, and peptide chain and protein objects are defined in MMTK.Proteins.

Python provides two ways to access objects in modules and submodules. The first one is importing a module and referring to objects in it, e.g.:

import MMTK
import MMTK.ForceFields
universe = MMTK.InfiniteUniverse(MMTK.ForceFields.Amber94ForceField())
The second method is importing all or some objects from a module:
from MMTK import InfiniteUniverse
from MMTK.ForceFields import Amber94ForceField
universe = InfiniteUniverse(Amber94ForceField())
These two import styles can also be mixed according to convience. In order to prevent any confusion, all objects are referred to by their full names in this manual. The Amber force field object is thus called MMTK.ForceFields.Amber94ForceField. Of course the user is free to use selective imports in order to be able to use such objects with shorter names.


Objects

MMTK is an object-oriented system. Since objects are everywhere and everything is an object, it is useful to know the most important object types and what can be done with them. All object types in MMTK have meaningful names, so it is easy to identify them in practice. The following overview contains only those objects that a user will see directly. There are many more object types used by MMTK internally, and also some less common user objects that are not mentioned here.

Chemical objects

These are the objects that represent the parts of a molecular system:

These objects form a simple hierarchy: complexes consist of molecules, molecules consist of groups and atoms, groups consist of smaller groups and atoms. All of these, except for groups, can be used directly to construct a molecular system. Groups can only be used in the definitions of other groups and molecules in the chemical database.

A number of operations can be performed on chemical objects, which can roughly be classified into inquiry (constituent atoms, bonds, center of mass etc.) and modification (translate, rotate).

There are also specialized versions of some of these objects. For example, MMTK defines proteins as special complexes, consisting of peptide chains, which are special molecules. They offer a range of special operations (such as selecting residues or constructing the positions of missing hydrogen atoms) that do not make sense for molecules in general.

Collections

Collection objects represent arbitrary collections of chemical objects. They are used to be able to refer to collections as single entities. For example, you might want to call all water molecules collectively "solvent". Most of the operations on chemical objects are also available for collections.

Force fields

Force field objects represent a precise description of force fields, i.e. a complete recipe for calculating the potential energy (and its derivatives) for a given molecular system. In other words, they specify not only the functional form of the various interactions, but also all parameters and the prescriptions for applying these parameters to an actual molecular system.

Universes

Universes define complete molecular systems, i.e. they contain chemical objects. In addition, they describe interactions within the system (by a force field), boundary conditions, external fields, etc. Many of the operations that can be used on chemical objects can also be applied to complete universes.

Minimizers and integrators

A minimizer object is a special "machine" that can find local minima in the potential energy surface of a universe. You may consider this a function, if you wish, but of course functions are just special objects. Similarly, an integrator is a special "machine" that can determine a dynamical trajectory for a system on a given potential energy surface.

Trajectories

Minimizers and integrators can produce trajectories, which are special files containing a sequence of configurations and/or other related information. Of course trajectory objects can also be read for analysis.

Variables

Variable objects (not to be confused with standard Python variables) describe quantities that have a value for each atom in a system, for example positions, masses, or energy gradients. Their most common use is for storing various configurations of a system.

Normal modes

Normal mode objects contain normal mode frequencies and atomic displacements for a given universe.

Non-MMTK objects

An MMTK application program will typically also make use of objects provided by Python or Python library modules. A particularly useful library is the package Scientific, which is also used by MMTK itself. The most important objects are

Of course MMTK applications can make use of the Python standard library or any other Python modules. For example, it is possible to write a simulation program that provides status reports via an integrated Web server, using the Python standard module SimpleHTTPServer.


The chemical database

For defining the chemical objects described above, MMTK uses a database of descriptions. There is a database for atoms, one for groups, etc. When you ask MMTK to make a specific chemical object, for example a water molecule, MMTK looks for the definition of water in the molecule database. A database entry contains everything there is to know about the object it defines: its constituents and their names, configurations, other names used e.g. for I/O, and all information force fields might need about the objects.

MMTK comes with database entries for many common objects (water, amino acids, etc.). For other objects you will have to write the definitions yourself, as described in the section on the database.


Force fields

MMTK contains everything necessary to use the Amber 94 force field on proteins, DNA, and water molecules. It uses the standard Amber parameter and modification file format. In addition to the Amber force field, there is a simple Lennard-Jones force field for noble gases, and a deformation force field for normal mode calculations on large proteins.

MMTK was designed to make the addition of force field terms and the implementation of other force fields as easy as possible. Force field terms can be defined in Python (for ease of implementation) or in C or Fortran (for efficiency). This is described in the developer's guide.


Units

Since MMTK is not a black-box program, but a modular library, it is essential for it to use a consistent unit system in which, for example, the inverse of a frequency is a time, and the product of a mass and the square of a velocity is an energy, without additional conversion factors. Black-box programs can (and usually do) use a consistent unit system internally and convert to "conventional" units for input and output.

The unit system of MMTK consists mostly of SI units of appropriate magnitude for molecular systems:

The module MMTK.Units contains convenient conversion constants for the units commonly used in computational chemistry. For example, a length of 2 ngstrm can be written as 2*Units.Ang, and a frequency can be printed in wavenumbers with print frequency/Units.invcm.


A simple example

The following simple example shows how a typical MMTK application might look like. It constructs a system consisting of a single water molecule and runs a short molecular dynamics trajectory. There are many alternative ways to do this; this particular one was chosen because it makes each step explicit and clear. The individual steps are explained in the remaining chapters of the manual.

# Import the necessary MMTK definitions.
from MMTK import *
from MMTK.ForceFields import Amber94ForceField
from MMTK.Trajectory import Trajectory, TrajectoryOutput, \
                            StandardLogOutput
from MMTK.Dynamics import VelocityVerletIntegrator
# Create an infinite universe (i.e. no boundaries, non-periodic).
universe = InfiniteUniverse(Amber94ForceField())
# Create a water molecule in the universe.
# Water is defined in the database.
universe.molecule = Molecule('water')
# Generate random velocities.
universe.initializeVelocitiesToTemperature(300*Units.K)
# Create an integrator.
integrator = VelocityVerletIntegrator(universe)
# Generate a trajectory
trajectory = Trajectory(universe, "water.nc", "w")
# Run the integrator for 50 steps of 1 fs, printing time and energy
# every fifth step and writing time, energy, temperature, and the positions
# of all atoms to the trajectory at each step.
integrator(delta_t = 1.*Units.fs, steps = 50,
           actions = [StandardLogOutput(5),
                      TrajectoryOutput(trajectory, ("time", "energy",
                                                    "thermodynamic",
                                                    "configuration"),
                                       0, None, 1)])
# Close the trajectory
trajectory.close()