Skip to content

Analysis classes fail with HOOMD GSD files with a TypeError #5224

@orbeckst

Description

@orbeckst

Following discussion #5222 we found that AnalysisBase-derived analysis classes do not currently work with HOOMD GSD trajectories. The issue appears that the new parallelization framework generates lists of frames as a numpy array with datatype np.int64. When such a frame is used to index the GSD trajectory, a TypeError is raised because (apparently) frames need to be normal Python int (see #5222 (reply in thread) ).

Normal iteration and indexing such as u.trajectory[1] work (as long as one uses normal ints — see below).

Examples

Failure example with Analysis class

from MDAnalysis.tests.datafiles import GSD
from MDAnalysis.analysis import rms
u = mda.Universe(GSD)
rr = rms.RMSD(u.atoms)
rr.run()

fails with a TypeError in gsd

> ~/miniforge3/envs/mda314/lib/python3.14/site-packages/gsd/hoomd.py(1046)__getitem__()
   1044             return self._read_frame(key)
   1045
-> 1046         raise TypeError
   1047
   1048     def __iter__(self):

The original error report showed failure with RDF but this seems to be general. A quick %pdb shows that we are working with the custom sliced trajectory in analysis

> ~/miniforge3/envs/mda314/lib/python3.14/site-packages/MDAnalysis/analysis/base.py(554)_compute()
    552             return self
    553
--> 554         for idx, ts in enumerate(
    555             ProgressBar(
    556                 self._sliced_trajectory, verbose=verbose, **progressbar_kwargs

ipdb> p self._sliced_trajectory
<MDAnalysis.coordinates.base.FrameIteratorIndices object at 0x160ad2a50>
ipdb> p self._sliced_trajectory.frames
(np.int64(0), np.int64(1))

and here the frames are np.int64.

Minimal failure example

Just index with something integer-like:

u.trajectory[np.int64(0)]

fails with the same TypeError.

Discussed in #5222

Originally posted by Lynn3512138 February 4, 2026
Hi All,

I'm using MDAnalysis 2.10.0 and try to get RDFs from a .gsd trajectories. The code is as below:

u=mda.Universe("2_B50_try7.gsd","2_B50_try7.gsd")

c=u.select_atoms("name C")
a=u.select_atoms("name A")

print(u.trajectory)
print(len(c))
print(len(a))

rdf = InterRDF(c,a,range=(0,5))
rdf.run()

plt.plot(rdf.bins, rdf.rdf)

However it gets the problems:

<GSDReader 2_B50_try7.gsd with 50 frames of 100 atoms>
50
50

TypeError Traceback (most recent call last)
Cell In[45], line 11
8 print(len(c))
10 rdf = InterRDF(c,a,range=(0,5))
---> 11 rdf.run()
13 plt.plot(rdf.bins, rdf.rdf)

File /opt/homebrew/Caskroom/miniconda/base/envs/hoomdenv/lib/python3.13/site-packages/MDAnalysis/analysis/base.py:898, in AnalysisBase.run(self, start, stop, step, frames, verbose, n_workers, n_parts, backend, unsupported_backend, progressbar_kwargs)
891 computation_groups = self._setup_computation_groups(
892 start=start, stop=stop, step=step, frames=frames, n_parts=n_parts
893 )
895 # get all results from workers in other processes.
896 # we need AnalysisBase classes
897 # since they hold frames, times and results attributes
--> 898 remote_objects: list["AnalysisBase"] = executor.apply(
899 worker_func, computation_groups
900 )
901 self.frames = np.hstack([obj.frames for obj in remote_objects])
902 self.times = np.hstack([obj.times for obj in remote_objects])

File /opt/homebrew/Caskroom/miniconda/base/envs/hoomdenv/lib/python3.13/site-packages/MDAnalysis/analysis/backends.py:208, in BackendSerial.apply(self, func, computations)
192 def apply(self, func: Callable, computations: list) -> list:
193 """
194 Serially applies func to each task object in computations.
195
(...)
206 list of results of the function
207 """
--> 208 return [func(task) for task in computations]

File /opt/homebrew/Caskroom/miniconda/base/envs/hoomdenv/lib/python3.13/site-packages/MDAnalysis/analysis/base.py:554, in AnalysisBase._compute(self, indexed_frames, verbose, progressbar_kwargs)
551 if len(frames) == 0: # if frames were empty in run or stop=0
552 return self
--> 554 for idx, ts in enumerate(
555 ProgressBar(
556 self._sliced_trajectory, verbose=verbose, **progressbar_kwargs
557 )
558 ):
559 self._frame_index = idx # accessed later by subclasses
560 self._ts = ts

File /opt/homebrew/Caskroom/miniconda/base/envs/hoomdenv/lib/python3.13/site-packages/tqdm/notebook.py:250, in tqdm_notebook.iter(self)
248 try:
249 it = super().iter()
--> 250 for obj in it:
251 # return super(tqdm...) will not catch exception
252 yield obj
253 # NB: except ... [ as ...] breaks IPython async KeyboardInterrupt

File /opt/homebrew/Caskroom/miniconda/base/envs/hoomdenv/lib/python3.13/site-packages/tqdm/std.py:1169, in tqdm.iter(self)
1166 # If the bar is disabled, then just walk the iterable
1167 # (note: keep this check outside the loop for performance)
1168 if self.disable:
-> 1169 for obj in iterable:
1170 yield obj
1171 return

File /opt/homebrew/Caskroom/miniconda/base/envs/hoomdenv/lib/python3.13/site-packages/MDAnalysis/coordinates/base.py:333, in FrameIteratorIndices.iter(self)
331 def iter(self):
332 for frame in self.frames:
--> 333 yield self.trajectory._read_frame_with_aux(frame)
334 self.trajectory.rewind()

File /opt/homebrew/Caskroom/miniconda/base/envs/hoomdenv/lib/python3.13/site-packages/MDAnalysis/coordinates/base.py:870, in ProtoReader._read_frame_with_aux(self, frame)
868 def _read_frame_with_aux(self, frame):
869 """Move to frame, updating ts with trajectory, transformations and auxiliary data."""
--> 870 ts = self._read_frame(frame) # pylint: disable=assignment-from-no-return
871 for aux in self.aux_list:
872 ts = self._auxs[aux].update_ts(ts)

File /opt/homebrew/Caskroom/miniconda/base/envs/hoomdenv/lib/python3.13/site-packages/MDAnalysis/coordinates/GSD.py:132, in GSDReader._read_frame(self, frame)
130 def _read_frame(self, frame):
131 try:
--> 132 myframe = self._file[frame]
133 except IndexError:
134 raise IOError from None

File /opt/homebrew/Caskroom/miniconda/base/envs/hoomdenv/lib/python3.13/site-packages/gsd/hoomd.py:1058, in HOOMDTrajectory.getitem(self, key)
1055 raise IndexError()
1056 return self._read_frame(key)
-> 1058 raise TypeError

TypeError:

I think the software can successfully read .gsd because when I directly analyze u.trajectory in other occasions everything is fine. But I don't know if my code is wrong or there's some internal problems with rdf. I also attached my trajectory in this post. 2_B50_try7.gsd.zipI would really appreciate your advice. Thank you in advance!

Metadata

Metadata

Assignees

No one assigned

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions