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.