Batching

IMDReader provides support for reading MD simulation data via the IMDv3 Protocol in MDAnalysis since Release 2.10.0.

Since IMD streams data in real-time from a running simulation, it has fundamental constraints that differ from traditional trajectory readers and this leads to some Important Limitations in IMDReader.

Buffered Access

To support buffered, time-dependent analyses in mdadash, a BufferedTrajectory is introduced.

The original trajectory is wrapped by the BufferedTrajectory to provide buffered access to the last n timesteps, where n is the configured batch size.

u.trajectory = BufferedTrajectory(u.trajectory, config["batch_size"])

trajectory[index] can be used to access individual frames. Index values can range from 0 to the configured batch size n. The batch size n is available via the trajectory.buffer_size attribute.

When a Widget class supports batching and implements the run_batch() method, the trajectory can be iterated this way to access the last n timesteps.

Here is a typical compute batch block used in the code for Built-in Analysis Widgets:

def _compute_batch(self):
    """Compute for current batch"""
    values = []
    for i in range(self.u.trajectory.buffer_size):
        _ = self.u.trajectory[i]  # set the trajectory to frame i
        values.append(self._compute_current_frame())
    return values

AnalysisBase support

MDAnalysis provides an AnalysisBase, which is the base class for defining multi-frame analysis.

A lot of built-in MDAnalysis Analysis modules derive from AnalysisBase.

The BufferedTrajectory enables using these analysis modules in the Widget classes, which are not possible with IMDReader.

Note

The total number of frames as seen by the AnalysisBase-based classes will be the configured Buffer / batch size during a full analysis.run() invocation.

Here is an example of using an AnalysisBase-based class within the Widget code by the Native Contacts built-in Widget.

from MDAnalysis.analysis import contacts
.....

def _create_contacts(self):
    """Update atom groups when selection phrases change"""
    self.contacts = contacts.Contacts(
        self.u,
        .....

def _compute_batch(self):
    """Compute values for current batch"""
    self.contacts.run()
    values = []
    for i, (_, q) in enumerate(self.contacts.results.timeseries):
        .....

AnalysisBase-based classes can also be used per-frame by passing the current frame as shown in this example:

def _compute_current_frame(self):
    """Compute values for current frame"""
    self.contacts.run(frames=[self.u.trajectory.frame])
    .....

The list of all the Widgets that support batching can be found on the Built-in Analysis Widgets page.