Data model

OVITO organizes the data it processes into data objects, each representing a specific fragment of a dataset. For example, a dataset may be composed of a SimulationCell object holding the cell dimensions, a Particles object storing the particle information, and a Bonds sub-object storing the bonds between particles. For each type of data object you will find a corresponding Python class in the ovito.data module. All of them derive from the DataObject base class.

Data objects can contain other data objects. For example, the Particles object holds a number of Property objects, one for each particle property that has been defined. The Particles object can also contain a Bonds object, which in turn is a container for a set of Property objects storing the per-bond properties:

../_images/data_objects.svg

The top-level container for all other data objects is the DataCollection class. It is the basic unit that gets processed by a data pipeline, i.e., it is loaded from an input file, flows down the data pipeline and is processed by modifiers. Modifiers may alter individual data objects within a DataCollection, add new data objects to the collection, or insert additional sub-objects into nested containers.

When you call the Pipeline.compute() method, you receive back a DataCollection holding the computation results of the pipeline. The DataCollection class provides various property fields for accessing the different kinds of sub-objects.

It is important to note that a DataCollection object represents just a single animation frame and not an entire animation sequence. Thus, in OVITO’s data model, a simulation trajectory is rather represented as a series of DataCollection instances. A data pipeline operates on and produces only a single DataCollection at a time, i.e., it works on a frame by frame basis.

Particle systems

The Particles data object, which is accessible through the DataCollection.particles field, holds all particle and molecule-related data. OVITO uses a property-centered representation of particles, where information is stored as a set of uniform memory arrays, all being of the same length. Each array represents one particle property such as position, type, mass, color, etc., and holds the values for all N particles in the system. A property data array is an instance of the Property data object class, which is not only used by OVITO for storing particle properties but also bond properties, voxel grid properties, and more.

Thus, a system of particles is nothing else than a loose collection of Property objects, which are held together by a container, the Particles object, which is a specialization of the generic PropertyContainer base class. Each particle property has a unique name that identifies the meaning of the property. OVITO defines a set of standard property names, which have a specific meaning to the program and a prescribed data format. The Position standard property, for example, holds the XYZ coordinates of all particles and is mandatory. Other standard properties, such as Color or Mass, are optional and may or may not be present in a Particles container. Furthermore, Property objects with non-standard names are supported, representing user-defined particle properties.

../_images/particles_object.svg

The Particles container object mimics the interface of a Python dictionary, which lets you look up properties by name. To find out which properties are present, you can query the dictionary for its keys:

>>> data = pipeline.compute()
>>> list(data.particles.keys())
['Particle Identifier', 'Particle Type', 'Position', 'Color']

Individual particle properties can be looked up by their name:

>>> color_property = data.particles['Color']

Some standard properties can also be accessed through convenient getter attributes defined in the Particles class:

>>> color_property = data.particles.colors

The Particles class is a sub-class of the more general PropertyContainer base class. OVITO defines more property container types, such as the Bonds, DataSeries and VoxelGrid types, which all work similar to the Particles type. They all have in common that they represent an array of uniform data elements, which may be associated with a variable sets of properties.

Property objects

Each Property in a PropertyContainer stores the values of one particular property for all data elements, for example all particles. A Property behaves pretty much like a standard NumPy array:

>>> coordinates = data.particles.positions

>>> print(coordinates[...])
[[ 73.24230194  -5.77583981  -0.87618297]
 [-49.00170135 -35.47610092 -27.92519951]
 [-50.36349869 -39.02569962 -25.61310005]
 ...,
 [ 42.71210098  59.44919968  38.6432991 ]
 [ 42.9917984   63.53770065  36.33330154]
 [ 44.17670059  61.49860001  37.5401001 ]]

Property arrays can be one-dimensional (in case of scalar properties) or two-dimensional (in case of vector properties). The size of the first array dimension is always equal to the number of data elements (e.g. particles) stored in the parent PropertyContainer. The container reports the current number of elements via its count attribute:

>>> data.particles.count  # This returns the number of particles
28655
>>> data.particles['Mass'].shape   # 1-dim. array
(28655,)
>>> data.particles['Color'].shape  # 2-dim. array
(28655, 3)
>>> data.particles['Color'].dtype  # Property data type
float64

OVITO currently supports three different numeric data types for property arrays: float64, int32 and int64. For built-in standard properties the data type and the dimensionality are prescribed by OVITO. For user-defined properties they can be chosen by the user when creating a new property.

Global attributes

Next topic

© 2019, Alexander Stukowski.
Close Menu