# Post-processing

Once the system is simulated, the trajectory and stored observables can be analyzed. For this purpose a trajectory object can be created by providing a path to the output file of a simulation:

trajectory = readdy.Trajectory('out.h5')


# Visual representation of the trajectory

To look at the time-series of the position of particles, one can use VMD. To this end there is a function to convert the hdf5 trajectory into a VMD-readable xyz file.

trajectory.convert_to_xyz(particle_radii={'A': 1.})


In shell you can then call vmd as follows

vmd -e out.xyz.tcl


The particle_radii are all defaulted to 1. unless otherwise specified.

# Information about the simulated system

The trajectory file stores some information about the system that was simulated. Given a trajectory object, one can obtain

# the thermal energy
trajectory.kbt
# the volume of the simulation box
trajectory.box_volume
# the dimensions of the simulation box
trajectory.box_size
# whether periodic boundary conditions were used
trajectory.periodic_boundary_conditions
# diffusion constants for registered particle types
trajectory.diffusion_constants
# a mapping from particle type name -> internal particle type id
trajectory.particle_types
# registered reactions
trajectory.reactions


All observables including the actual trajectory have functions to read back the recorded data.

The actual trajectory can be read back as a list of lists by invoking

for frame in trajectory.read():
for particle in frame:
print("Particle with id {} of type {} at position {}"
.format(particle.id, particle.type, particle.position))


Except for the trajectory all observables can be stored at a different place in the file by providing a save argument when registering them. For such a case each method of the trajectory object that can obtain observable data has an additional argument data_set_name that needs to be set accordingly. If the default save argument was used or it was not specified, one can omit the data_set_name.

Since one can configure observables with different strides an array with simulation times is always returned, i.e., if an observable was configured with a stride of 5, it would contain [0, 5, 10, ...].

time, bin_centers, distribution = trajectory.read_observable_rdf()


where time is a list of simulation times, bin_centers are the bin centers and distribution contains the RDF in shape of a (T, N) array (T being the number of recordings and N being the number of bins).

• The particles data can be obtained by
time, types, ids, positions = trajectory.read_observable_particles()


where time is a list of simulation times, types is a list of particle type ids that can be converted to their respective names by calling trajectory.species_name(a_particular_id), ids is a list of lists containing the unique ids of each particle, and positions is a list of lists containing particle positions.

• The particle positions data can be obtained by
time, positions = trajectory.read_observable_particle_positions()


where time is a list of simulation times and positions is a list of (N_t, 3)-shaped arrays, where N_t is the number of particles in particular time step.

• The number of particles data can be obtained by
time, counts = trajectory.read_observable_number_of_particles()


where time is a list of simulation times and counts is an array containing the recorded number of particles per requested type.

• The energy observable data can be obtained by
time, energy = trajectory.read_observable_energy()


where time is a list of simulation times and energy is a list of potential energy values.

• The forces observable data can be obtained by
time, forces = trajectory.read_observable_forces()


where time is a list of simulation times and forces is a list of arrays containing the forces acting on each particle for each evaluated time step.

• The reactions observable data can be obtained by
time, reactions = trajectory.read_observable_reactions()


where time is a list of simulation times and reactions is a list of lists containing the occurred reaction events for each evaluated time step. The reaction event data can be accessed just like in the callback function of the observable.

• The reaction counts observable data can be obtained by
time, counts = trajectory.read_observable_reaction_counts()


where time is a list of simulation times and counts is a dictionary with the reaction names as keys and the corresponding counts as values, i.e.,

counts['my_reaction']


is an array of length N where N is the number of evaluations of the observable with the number of occurrences of my_reaction.

• The virial observable data can be obtained by
time, virials = trajectory.read_observable_virial()


where time is a list of simulation times and virials contains the system’s pressure virial for each simulation time in that it was evaluated.

• The pressure observable data can be obtained by
time, pressure = trajectory.read_observable_pressure()


where time is a list of simulation times and pressure contains the corresponding pressure per simulation time.