GSoC 2026: Week 3 & 4 - Setting up the Reader

Since the base of the bridge was done once the parser was set up, it was time to move to the next phase. Tbe parser only handles the static parts of the simulation. In order to actually analyze the simulation, we need a way to read dynamic trajectory data.

Here is where WESTPAReader comes into place. It needs to expose the full WESTPA trajectory as a linear sequence of MDAnalysis frames, complete with coordinates and metadata. WESTPA uses a weighted ensemble approach. Instead of one long continuous path, WESTPA generates hundreds of short, branching trajectory segments that split and merge across multiple iterations. However MDAnalysis expects a linear sequence of frames. If a researcher wants to trace a continuous pathway from a WESTPA simulation, they would have to manually stitch those scattered segment files together.

WESTPAReader takes away that complexity. Its job is to act as the translator between WESTPA’s scattered data and MDAnalysis’s linear expectations. To the user, it feels like analyzing any normal file but under the hood the reader is doing the heavy lifting.

There were certainly some challenges in implementing this.
WESTPA simulations can generate a massive amount of trajectory data spread across multiple files. If the reader opened and closed an HDF5 file for every single frame, the I/O overhead would bring the analysis to a crawl. Hence a caching mechanism was needed.

This was done by checking if the file needed was different from the already open or not. This saves alot of time when reading sequential frames in the same file.

if self._current_path != path:
    if self._current_h5:
        self._current_h5.close()
    self._current_h5 = h5py.File(path, 'r')
    self._current_path = path

One of the main benefits of this crawler is retaining WESTPA-specific data (like statistical weights, segment IDs, and iteration numbers) directly alongside the physical coordinates. Rather than forcing the researcher to cross-reference two different data structures, I injected the metadata directly into the MDAnalysis timestep dictionary. However while testing, I noticed all the frames had the same metadata. This was because ts.data was retaining its values from the previous frame and was polluting every subsequent frame. Hence it was necessary to clear it for every frame.

self.ts.data.clear()

It was also necessary to ensure that the trajectory frames are in correct order as they may not be sequentially stored and maybe on first come basis. This is done by referencing an additional pointer dataset which stores info about iteration number and the segment id. Hence we get the actual positions using two filter masks.

valid = ptr[:, 0] > 0
seg_mask = ptr[:, 1] == seg_id

With all this out of the way, the reader was functional.

Testing with slicing and using MDAnalysis’s random access: universe

Testing MDAnalysis’s Radius of Gyration tool: universe

Now that the reader is in place, users can take full advantage of MDAnalyis’s tools using WESTPA simulation data. The next step is getting MDAnalysis’s parallelization backend working and a way to let users save analysis data back into the source HDF5 file.

Summary

  • Implemented the WESTPAReader class to extract dynamic trajectory data and expose branching WESTPA segments as a linear MDAnalysis sequence.
  • Added a file caching mechanism within the reader to minimize I/O reads when navigating HDF5 files.
  • Injected WESTPA-specific metadata directly into the MDAnalysis timestep dictionary.