HOOMD examples

gsd.hoomd provides high-level access to HOOMD schema GSD files.

View the page source to find unformatted example code.

Import the module

In [1]: import gsd.hoomd

Define a snapshot

In [2]: s = gsd.hoomd.Snapshot()

In [3]: s.particles.N = 4

In [4]: s.particles.types = ['A', 'B']

In [5]: s.particles.typeid = [0,0,1,1]

In [6]: s.particles.position = [[0,0,0],[1,1,1], [-1,-1,-1], [1,-1,-1]]

In [7]: s.configuration.box = [3, 3, 3, 0, 0, 0]

gsd.hoomd.Snapshot stores the state of a single system configuration, or frame, in the file. Instantiate this class to create a system configuration. All fields default to None. Each field is written to the file when not None and when the data does not match the data in the first frame or defaults specified in the schema.

Create a hoomd gsd file

In [8]: f = gsd.hoomd.open(name='file.gsd', mode='wb')

Use gsd.hoomd.open to open a GSD file as a gsd.hoomd.HOOMDTrajectory instance.

Write frames to a gsd file

In [9]: def create_frame(i):
   ...:     s = gsd.hoomd.Snapshot()
   ...:     s.configuration.step = i
   ...:     s.particles.N = 4+i
   ...:     s.particles.position = numpy.random.random(size=(4+i,3))
   ...:     return s
   ...: 

In [10]: f = gsd.hoomd.open(name='test.gsd', mode='wb')

In [11]: f.extend( (create_frame(i) for i in range(10)) )

In [12]: f.append( create_frame(10) )

In [13]: len(f)
Out[13]: 11

gsd.hoomd.HOOMDTrajectory is similar to a sequence of gsd.hoomd.Snapshot objects. The append and extend methods add frames to the trajectory.

Note

gsd.hoomd.HOOMDTrajectory currently does not support files opened in the ‘ab’ mode.

Tip

When using extend, pass in a generator or generator expression to avoid storing the entire trajectory in memory before writing it out.

Randomly index frames

In [14]: f = gsd.hoomd.open(name='test.gsd', mode='rb')

In [15]: snap = f[5]

In [16]: snap.configuration.step
Out[16]: 5

In [17]: snap.particles.N
Out[17]: 9

In [18]: snap.particles.position
Out[18]: 
array([[0.18422192, 0.09466249, 0.38323113],
       [0.47345772, 0.16781104, 0.9544454 ],
       [0.45992118, 0.7358498 , 0.91641   ],
       [0.51144546, 0.09961978, 0.25954124],
       [0.48245394, 0.67932445, 0.08312619],
       [0.8085284 , 0.95634735, 0.87444085],
       [0.6481263 , 0.1973414 , 0.3093521 ],
       [0.1962839 , 0.42468652, 0.6804826 ],
       [0.05064661, 0.7936267 , 0.6833044 ]], dtype=float32)

gsd.hoomd.HOOMDTrajectory supports random indexing of frames in the file. Indexing into a trajectory returns a gsd.hoomd.Snapshot.

Slicing and selection

Use the slicing operator to select individual frames or a subset of a trajectory.

In [19]: f = gsd.hoomd.open(name='test.gsd', mode='rb')

In [20]: for s in f[5:-2]:
   ....:     print(s.configuration.step, end=' ')
   ....: 
5 6 7 8 
In [21]: every_2nd_frame = f[::2]  # create a view of a trajectory subset

In [22]: for s in every_2nd_frame[:4]:
   ....:     print(s.configuration.step, end=' ')
   ....: 
0 2 4 6 

Slicing a trajectory creates a trajectory view, which can then be queried for length or sliced again.

Pure python reader

In [23]: f = gsd.pygsd.GSDFile(open('test.gsd', 'rb'))

In [24]: t = gsd.hoomd.HOOMDTrajectory(f);

In [25]: t[3].particles.position
Out[25]: 
array([[0.04063464, 0.6161694 , 0.2237447 ],
       [0.59745383, 0.02123008, 0.42634264],
       [0.8154588 , 0.14276674, 0.9221292 ],
       [0.12039564, 0.13733217, 0.5986491 ],
       [0.7738856 , 0.14683433, 0.2774252 ],
       [0.9460546 , 0.02909101, 0.6080086 ],
       [0.02730055, 0.9453248 , 0.6823403 ]], dtype=float32)

You can use GSD without needing to compile C code to read GSD files using gsd.pygsd.GSDFile in combination with gsd.hoomd.HOOMDTrajectory. It only supports the rb mode and does not read files as fast as the C implementation. It takes in a python file-like object, so it can be used with in-memory IO classes, and grid file classes that access data over the internet.

Warning

gsd.pygsd is slow. Use gsd.hoomd.open whenever possible.

Access logged data

In [26]: with gsd.hoomd.open(name='example.gsd', mode='wb') as f:
   ....:     s = gsd.hoomd.Snapshot()
   ....:     s.particles.N = 4
   ....:     s.log['particles/net_force'] = numpy.array([[-1,2,-3],
   ....:                                     [0,2,-4],
   ....:                                     [-3,2,1],
   ....:                                     [1,2,3]], dtype=numpy.float32)
   ....:     s.log['value/potential_energy'] = [1.5]
   ....:     f.append(s)
   ....: 

Logged data is stored in the log dictionary as numpy arrays. Place data into this dictionary directly without the ‘log/’ prefix and gsd will include it in the output. Store per-particle quantities with the prefix particles/. Choose another prefix for other quantities.

In [27]: f = gsd.hoomd.open(name='example.gsd', mode='rb')

In [28]: s = f[0]

In [29]: s.log['particles/net_force']
Out[29]: 
array([[-1.,  2., -3.],
       [ 0.,  2., -4.],
       [-3.,  2.,  1.],
       [ 1.,  2.,  3.]], dtype=float32)

In [30]: s.log['value/potential_energy']
Out[30]: array([1.5])

Read logged data from the log dictionary.

Note

Logged data must be a convertible to a numpy array of a supported type.

In [31]: with gsd.hoomd.open(name='example.gsd', mode='wb') as f:
   ....:     s = gsd.hoomd.Snapshot()
   ....:     s.particles.N = 4
   ....:     s.log['invalid'] = dict(a=1, b=5)
   ....:     f.append(s)
   ....: 
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-31-afa7e9459779> in <module>
      3     s.particles.N = 4
      4     s.log['invalid'] = dict(a=1, b=5)
----> 5     f.append(s)

~/checkouts/readthedocs.org/user_builds/gsd/conda/stable/lib/python3.7/site-packages/gsd-2.5.3-py3.7-linux-x86_64.egg/gsd/hoomd.py in append(self, snapshot)
    768         # write log data
    769         for log, data in snapshot.log.items():
--> 770             self.file.write_chunk('log/' + log, data)
    771 
    772         self.file.end_frame()

gsd/fl.pyx in gsd.fl.GSDFile.write_chunk()

ValueError: invalid type for chunk: log/invalid

Access state data

In [32]: with gsd.hoomd.open(name='test2.gsd', mode='wb') as f:
   ....:     s = gsd.hoomd.Snapshot()
   ....:     s.particles.types = ['A', 'B']
   ....:     s.state['hpmc/convex_polygon/N'] = [3, 4]
   ....:     s.state['hpmc/convex_polygon/vertices'] = [[-1, -1],
   ....:                                                [1, -1],
   ....:                                                [1, 1],
   ....:                                                [-2, -2],
   ....:                                                [2, -2],
   ....:                                                [2, 2],
   ....:                                                [-2, 2]]
   ....:     f.append(s)
   ....: 

State data is stored in the state dictionary as numpy arrays. Place data into this dictionary directly without the ‘state/’ prefix and gsd will include it in the output. Shape vertices are stored in a packed format. In this example, type ‘A’ has 3 vertices (the first 3 in the list) and type ‘B’ has 4 (the next 4).

In [33]: with gsd.hoomd.open(name='test2.gsd', mode='rb') as f:
   ....:     s = f[0]
   ....:     print(s.state['hpmc/convex_polygon/N'])
   ....:     print(s.state['hpmc/convex_polygon/vertices'])
   ....: 
[3 4]
[[-1. -1.]
 [ 1. -1.]
 [ 1.  1.]
 [-2. -2.]
 [ 2. -2.]
 [ 2.  2.]
 [-2.  2.]]

Access read state data in the same way.

Use multiprocessing

import multiprocessing

def count_particles(args):
   t, frame = args
   return len(t[frame].particles.position)

with gsd.hoomd.open(name='test.gsd', mode='rb') as t:
   with multiprocessing.Pool(processes=multiprocessing.cpu_count()) as pool:
      result = pool.map(count_particles, [(t, frame) for frame in range(len(t))])

 result

gsd.hoomd.HOOMDTrajectory can be pickled when in read mode to allow for multiprocessing through Python’s multiprocessing library. Here count_particles finds the number of particles in each frame and appends it to a list.

Using the command line

The GSD library provides a command line interface for reading files with first-class support for reading HOOMD GSD files. The CLI opens a Python interpreter with a file opened in a specified mode.

$ gsd read -s hoomd 'test.gsd'
...
File: test.gsd
Number of frames: 11

The GSD file handle is available via the "handle" variable.
For supported schema, you may access the trajectory using the "traj" variable.
Type "help(handle)" or "help(traj)" for more information.
The gsd and gsd.fl packages are always loaded.
Schema-specific modules (e.g. gsd.hoomd) are loaded if available.

>>> len(traj)
11
>>> traj[0].particles.position.shape == (4, 3)
True
>>> handle.read_chunk(0, 'particles/N')
array([4], dtype=uint32)