Source code for tcc_python_scripts.file_readers.snapshot
"""
Module defining interface for reading and writing snapshots in various file formats. A snapshot is an object which
holds data about a configuration of particles at a single point in time. A series of snapshots can be used to describe
a trajectory in time.
"""
import numpy
import contextlib
import abc
[docs]@contextlib.contextmanager
def stream_safe_open(path_or_file, mode='r'):
"""Context manager for parsers which accept an open file stream or a file path to open.
Args:
path_or_file: either an open file stream (in which case the context manager does nothing and returns it)
or a path (in which case the context manager will open this, return a stream and then clean up)
mode: mode to open file in, 'r' for read, 'w' for write
"""
if isinstance(path_or_file, str):
file_object = file_to_close = open(path_or_file, mode)
else:
file_object = path_or_file
file_to_close = None
try:
yield file_object
finally:
if file_to_close:
file_to_close.close()
[docs]class NoSnapshotError(RuntimeError):
"""Exception raised when not able to read a snapshot from a file."""
pass
[docs]class SnapshotIncompleteError(RuntimeError):
"""Exception raised when a snapshot is partially read
but not all particles are found or the coordinates cannot be read."""
pass
[docs]class Snapshot:
"""Snapshot of a system of particles. A snapshot is a single configuration of particles at a point in time.
Attributes:
particle_coordinates: particle coordinates (num_particles by dimensionality container)
box: box containing the particles (d by 2 container)
species: labels of the particle species (string or container of strings)
time: time or frame of the snapshot within a trajectory (integer or float)
"""
def __init__(self, particle_coordinates=numpy.empty((0, 0)), box=None, species=None, time=0):
"""Create a new snapshot."""
self.particle_coordinates = particle_coordinates
self.box = box
if species is None:
self.species = ['A'] * self.num_particles
else:
self.species = species
self.time = time
[docs] def copy(self):
"""
Returns:
A deep copy of the snapshot.
"""
return Snapshot(self.particle_coordinates.copy(), self.box.copy(), self.species.copy(), self.time)
@property
def num_particles(self):
"""
Returns:
Number of particles in snapshot.
"""
return len(self.particle_coordinates)
@property
def dimensionality(self):
"""
Returns:
Dimensionality of configuration space.
"""
return self.particle_coordinates.shape[1]
[docs] @classmethod
def read_single(cls, path_or_file):
"""Read a single snapshot from the disk.
Example:
>>> Snapshot.read_single('snapshot.atom')
<snapshot n=10976 t=0>
Args:
cls: derived class defining specific file format
path_or_file: file stream or path to read snapshot from
Returns:
snapshot: the snapshot read from disk
Raises:
NoSnapshotError: if could not read from file
RuntimeException: if did not recognise file format
"""
with stream_safe_open(path_or_file) as f:
snap = cls()
snap._read(f)
return snap
[docs] @classmethod
def read_trajectory(cls, path_or_file):
"""A generator that reads snapshots from a file.
Args:
path_or_file: file stream or path to read trajectory from
Raises:
NoSnapshotError: if file could not be read.
RuntimeException: file format is not recognised
"""
with stream_safe_open(path_or_file) as f:
while True:
snap = cls()
try:
snap._read(f)
except NoSnapshotError:
break
yield snap
[docs] def write(self, output_file):
"""Dump the snapshot to a file.
Args:
output_file: file or path to write the snapshot to
"""
with stream_safe_open(output_file, 'w') as output_file:
xyz_frame = str(self)
output_file.write(xyz_frame)
output_file.write('\n')
def __repr__(self):
"""Internal representation of the object for printing to debugger."""
return '<snapshot n=%r t=%r>' % (self.num_particles, self.time)
@abc.abstractmethod
def __str__(self):
"""
String representation of the snapshot in the chosen format not implemented in the base class,
and must be written for specific formats.
"""
raise NotImplementedError
@abc.abstractmethod
def _read(self, file_or_stream):
"""
Function to read a snapshot from a file. Not implemented in base class and must be written
for specific file formats.
"""
raise NotImplementedError