ovito.data

This module contains data structures and container classes that are used by OVITO’s modification pipeline system.

Data collection:

Data objects:

Auxiliary classes:

class ovito.data.BondProperty
Base class:ovito.data.DataObject

This data object stores the values of a certain bond property. A bond property is a quantity associated with every bond in a system. Bond properties work similar to particle properties (see ParticleProperty class).

All bond properties associated with the bonds in a system are stored in the DataCollection.bond_properties dictionary of the DataCollection container. Bond properties are either read from the external simulation file or can be newly generated by OVITO’s modifiers, the ComputeBondLengthsModifier being one example.

The topological definition of bonds, i.e. the connectivity of particles, is stored separately from the bond properties in the Bonds data object. The Bonds can be accessed through the DataCollection.bonds field.

Note that OVITO internally works with half-bonds, i.e., every full bond is represented as two half-bonds, one pointing from particle A to particle B and the other from B to A. Each half-bond is associated with its own property value, and the size of a bond property array is always twice as large as the number of full bonds (see DataCollection.number_of_half_bonds and DataCollection.number_of_full_bonds). Typically, however, the property values of a half-bond and its reverse bond are identical.

Similar to particle properties, it is possible to associate user-defined properties with bonds. OVITO also knows a set of standard bond properties (see the type attribute below), which control the visual appearance of bonds. For example, it is possible to assign the Color property to bonds, giving one control over the rendering color of each individual (half-)bond. The color values stored in this property array will be used by OVITO to render the bonds. If not present, OVITO will fall back to the default behavior, which is determined by the ovito.vis.BondsDisplay associated with the Bonds object.

array

This attribute returns a NumPy array, which provides read access to the per-bond data stored in this bond property object.

The returned array is one-dimensional for scalar bond properties (components == 1), or two-dimensional for vector properties (components > 1). The outer length of the array is equal to the number of half-bonds in both cases.

Note that the returned NumPy array is read-only and provides a view of the internal data. No copy of the data, which may be shared by multiple objects, is made. If you want to modify the data stored in this bond property, use marray instead.

changed()

Informs the bond property object that its stored data has changed. This function must be called after each direct modification of the per-bond data through the marray attribute.

Calling this method on an input bond property is necessary to invalidate data caches down the modification pipeline. Forgetting to call this method may result in an incomplete re-evaluation of the modification pipeline. See marray for more information.

components

The number of vector components (if this is a vector bond property); otherwise 1 (= scalar property).

static create(prop_type, num_bonds)

Static factory function that creates a new BondProperty instance for a standard bond property. To create a new user-defined property, use create_user() instead.

Note that this factory function is a low-level method. If you want to add a new bond property to an existing DataCollection, you can do so using the high-level method create_bond_property() instead.

Parameters:
  • prop_type (BondProperty.Type) – The standard bond property to create. See the type attribute for a list of possible values.
  • num_bonds (int) – The number of half-bonds. This determines the size of the allocated data array.
Returns:

A newly created instance of the BondProperty class or one of its sub-classes.

static create_user(name, data_type, num_bonds, num_components=1)

Static factory function that creates a new BondProperty instance for a user-defined bond property. To create one of the standard properties, use create() instead.

Note that this factory function is a low-level method. If you want to add a new user-defined bond property to an existing DataCollection, you can do so using the high-level method create_user_bond_property() instead.

Parameters:
  • name (str) – The name of the user-defined bond property to create.
  • data_type (str) – Must be either "int" or "float".
  • num_bonds (int) – The number of half-bonds. This determines the size of the allocated data array.
  • num_components (int) – The number of components when creating a vector property.
Returns:

A newly created instance of the BondProperty class.

findInState()
marray

This attribute returns a mutable NumPy array providing read/write access to the internal per-bond data.

The returned array is one-dimensional for scalar bond properties (components == 1), or two-dimensional for vector properties (components > 1). The outer length of the array is equal to the number of half-bonds in both cases.

Note

After you are done modifying the data in the returned NumPy array, you must call changed()! Calling this method is necessary to inform the data pipeline system that the input bond data has changed and the modification pipeline needs to be re-evaluated. The reason is that OVITO cannot automatically detect modifications made by the script to the returned NumPy array. Therefore, an explicit call to changed() is necessary.

name

The human-readable name of the bond property.

size

The number of stored property values, which is always equal to the number of half-bonds.

type

The type of the bond property (user-defined or one of the standard types). One of the following constants:

Type constant Property name Data type
BondProperty.Type.User (a user-defined property with a non-standard name) int/float
BondProperty.Type.BondType Bond Type int
BondProperty.Type.Selection Selection int
BondProperty.Type.Color Color float
BondProperty.Type.Length Length float
class ovito.data.BondType

Stores the properties of a bond type.

The list of bond types is stored in the BondTypeProperty class.

color

The display color to use for bonds of this type.

id

The identifier of the bond type.

name

The display name of this bond type.

class ovito.data.BondTypeProperty
Base class:ovito.data.BondProperty

A special BondProperty that stores a list of BondType instances in addition to the per-bond values.

The bond property Bond Type is represented by an instance of this class. In addition to the regular per-bond data (consisting of an integer per half-bond, indicating its type ID), this class holds the list of defined bond types. These are BondType instances, which store the ID, name, and color of each bond type.

get_type_by_id(id)

Returns the BondType with the given numeric ID from the type_list. Raises a KeyError if the ID does not exist.

get_type_by_name(name)

Returns the BondType with the given name from the type_list. If multiple types exists with the same name, the first type is returned. Raises a KeyError if there is no type with such a name.

type_list

A (mutable) list of BondType instances.

Note that the bond types may be stored in arbitrary order in this type list. Each type has a unique integer ID (given by the BondType.id attribute). The numbers stored in the bond type property array refer to these type IDs.

class ovito.data.Bonds
Base class:ovito.data.DataObject

This data object stores a list of bonds between pairs of particles. Typically, bonds are loaded from a simulation file or created by inserting the CreateBondsModifier into the modification pipeline.The following example demonstrates how to access the bonds list create by a CreateBondsModifier:

from ovito.io import import_file
from ovito.modifiers import CreateBondsModifier
from ovito.vis import BondsDisplay
import numpy

# Load a set of atoms and create bonds between pairs of atoms
# that are within a given cutoff distance of each other
# using the Create Bonds modifier.
node = import_file('simulation.dump')
node.modifiers.append(CreateBondsModifier(cutoff = 3.4))
node.compute()

# Read out list of generated bonds.
bonds_list = node.output.bonds.array
print("Number of generated bonds: ", len(bonds_list)//2)

OVITO represents each bond by two half-bonds, one pointing from a particle A to a particle B, and the other half-bond pointing back from B to A. Thus, you will typically find twice as many half-bonds in the Bonds object as there are bonds. The array attribute of the Bonds class returns a (read-only) NumPy array that contains the list of half-bonds, each being defined as a pair of particle indices.

Note that half-bonds are not stored in any particular order in the array. In particular, the half-bond (a, b) may not always be immediately succeeded by the corresponding reverse half-bond (b, a). Also, the half-bonds leaving a particle might not be not stored as a contiguous sequence. If you need to iterate over all half-bonds of a particle, you can use the Enumerator utility class described below.

Bond display settings

Every Bonds object is associated with a BondsDisplay instance, which controls the visual appearance of the bonds in the viewports. It can be accessed through the display attribute:

# Change appearance of bonds.
node.output.bonds.display.enabled = True
node.output.bonds.display.shading = BondsDisplay.Shading.Flat
node.output.bonds.display.width = 0.3

Computing bond vectors

Note that the Bonds class only stores the indices of the particles connected by bonds (the topology). Sometimes it might be necessary to determine the corresponding spatial bond vectors. They can be computed from the current positions of the particles:

particle_positions = node.output.particle_properties.position.array
bonds_array = node.output.bonds.array
bond_vectors = particle_positions[bonds_array[:,1]] - particle_positions[bonds_array[:,0]]

Here, the first and the second column of the bonds array were each used to index the particle positions array. The subtraction of the two indexed arrays yields the list of bond vectors. Each vector in this list points from the first particle to the second particle of the corresponding half-bond.

Finally, we need to correct for the effect of periodic boundary conditions when bonds cross the box boundaries. This is achieved by multiplying the cell matrix and the stored PBC shift vector of each bond and adding the product to the bond vectors:

bond_vectors += numpy.dot(node.output.cell.matrix[:,:3], node.output.bonds.pbc_vectors.T).T

Note that it was necessary to transpose the PBC vectors array first to facilitate the transformation of the entire array of vectors with a single 3x3 cell matrix. In the above code snippets we have performed the following calculation for every half-bond (a, b) in parallel:

v = x(b) - x(a) + dot(H, pbc)

where H is the cell matrix and pbc is the bond’s PBC shift vector of the form (nx, ny, nz). See the pbc_vectors array for its meaning.

class Enumerator(bonds)

Utility class that allows efficiently iterating over the bonds of a particle.

The class constructor takes the Bonds object containing all the bonds in the system, for which it will first build a lookup table. After the Enumerator has been constructed, the half-bonds of a particular atom can be visited using the bonds_of_particle() method.

Warning: Do not modify the underlying Bonds object while using the Enumerator. Adding or deleting bonds would render the internal lookup table of the Enumerator invalid.

Usage example

from ovito.io import import_file
from ovito.data import Bonds

# Load a system of atoms and bonds.
node = import_file('bonds.data.gz', atom_style = 'bond')

# Create bond enumerator object.
bonds_enum = Bonds.Enumerator(node.source.bonds)

# Loop over atoms.
bonds_array = node.source.bonds.array
for particle_index in range(node.source.number_of_particles):
    # Loop over half-bonds of current atom.
    for bond_index in bonds_enum.bonds_of_particle(particle_index):
        atomA = bonds_array[bond_index][0]
        atomB = bonds_array[bond_index][1]
        assert(atomA == particle_index)
        print("Atom %i has a bond to atom %i" % (atomA, atomB))
bonds_of_particle(particle_index)

Returns an iterator that yields the indices of the half-bonds connected to the given particle. The numbers returned by the iterator can be used to index the Bonds.array.

Bonds.add(p1, p2, pbc_shift=(0, 0, 0))

Creates a new half-bond from particle p1 to particle p2.

To also create a reverse half-bond from p2 to p1, use add_full() instead.

Parameters:
  • p1 (int) – Zero-based index of the particle at which the bonds originates.
  • p2 (int) – Zero-based index of the particle the bonds leads to.
  • pbc_shift – A tuple of three integers, which specifies how often each periodic boundary of the simulation cell is crossed when following the new bond from p1 to p2. This information is needed by OVITO to correctly wrap bonds at periodic boundaries. See pbc_vectors array.
Bonds.add_full(p1, p2, pbc_shift=(0, 0, 0))

Creates two half-bonds between the particles p1 and p2. This is equivalent to two calls to add().

Parameters:
  • p1 (int) – Zero-based index of the first particle.
  • p2 (int) – Zero-based index of the second particle.
  • pbc_shift – A tuple of three integers, which specifies how often each periodic boundary of the simulation cell is crossed when following the new bond from p1 to p2. This information is needed by OVITO to correctly wrap bonds at periodic boundaries. See pbc_vectors array.
Bonds.array

This attribute returns a NumPy array providing direct access to the bonds list.

The returned array is two-dimensional and contains pairs of particle indices connected by a bond. The array’s shape is N x 2, where N is the number of half-bonds. Each pair-wise bond occurs twice in the array, once for the connection A->B and second time for the connection B->A. Particle indices start at 0.

Note that the returned NumPy array is read-only and provides a view of the internal data.

Bonds.clear()

Removes all stored bonds.

Bonds.pbc_vectors

A NumPy array providing read access to the PBC shift vectors of bonds.

The returned array’s shape is N x 3, where N is the number of half-bonds. It contains the periodic shift vector for each half-bond.

A PBC shift vector consists of three integers, which specify how many times (and in which direction) the corresonding half-bond crosses the periodic boundaries of the simulation cell. For example, a shift vector (0,-1,0) indicates that the half-bond crosses the periodic boundary in the negative Y direction once. In other words, the particle where the half-bond originates from is located close to the lower edge of the simulation cell in the Y direction while the second particle is located close to the opposite side of the box.

The PBC shift vectors are important for visualizing the bonds between particles with wrapped coordinates, which are located on opposite sides of a periodic cell. When the PBC shift vector of a bond is (0,0,0), OVITO assumes that both particles connected by the bond are located in the same periodic image and the bond is rendered such that it directly connects the two particles without going through a cell boundary.

Note that, if the PBC shift vector of a half-bond A->B is (nx, ny, nz), then the shift vector of the reverse half-bond B->A is always (-nx, -ny, -nz).

class ovito.data.CutoffNeighborFinder(cutoff, data_collection)

A utility class that computes particle neighbor lists.

This class allows to iterate over the neighbors of each particle within a given cutoff distance. You can use it to build neighbors lists or perform other kinds of analyses that require neighbor information.

The constructor takes a positive cutoff radius and a DataCollection containing the input particle positions and the cell geometry (including periodic boundary flags).

Once the CutoffNeighborFinder has been constructed, you can call its find() method to iterate over the neighbors of a specific particle, for example:

from ovito.io import import_file
from ovito.data import CutoffNeighborFinder

# Load input simulation file.
node = import_file("simulation.dump")
data = node.source

# Initialize neighbor finder object:
cutoff = 3.5
finder = CutoffNeighborFinder(cutoff, data)

# Loop over all input particles:
for index in range(data.number_of_particles):
    print("Neighbors of particle %i:" % index)
    # Iterate over the neighbors of the current particle:
    for neigh in finder.find(index):
        print(neigh.index, neigh.distance, neigh.delta, neigh.pbc_shift)

If you want to determine the N nearest neighbors of a particle, use the NearestNeighborFinder class instead.

find(index)

Returns an iterator over all neighbors of the given particle.

Parameters:index (int) – The index of the central particle whose neighbors should be iterated. Particle indices start at 0.
Returns:A Python iterator that visits all neighbors of the central particle within the cutoff distance. For each neighbor the iterator returns an object with the following attributes:
  • index: The index of the current neighbor particle (starting at 0).
  • distance: The distance of the current neighbor from the central particle.
  • distance_squared: The squared neighbor distance.
  • delta: The three-dimensional vector connecting the central particle with the current neighbor (taking into account periodicity).
  • pbc_shift: The periodic shift vector, which specifies how often each periodic boundary of the simulation cell is crossed when going from the central particle to the current neighbor.

Note that all periodic images of particles within the cutoff radius are visited. Thus, the same particle index may appear multiple times in the neighbor list of a central particle. In fact, the central particle may be among its own neighbors in a sufficiently small periodic simulation cell. However, the computed vector (delta) and PBC shift (pbc_shift) taken together will be unique for each visited image of a neighboring particle.

class ovito.data.DataCollection

A data collection is a dictionary-like container that can store an arbitrary number of data objects. OVITO knows various types of data objects, e.g.

Data collections hold the data that enters or leaves an ObjectNode‘s modification pipeline. The input data collection of the pipeline can be accessed through the node’s source attribute:

>>> node = import_file(...)
>>> print(node.source)
DataCollection(['Simulation cell', 'Position'])

In this example the input data collection contains the original data that was read from the external file, consisting of the particle position property and a simulation cell.

The input data typically gets modified or extended by modifiers in the node’s modification pipeline. To access the results of the modification pipeline, we need to call ObjectNode.compute(), which returns the output data collection after evaluating the modifiers:

>>> node.modifiers.append(CommonNeighborAnalysisModifier())
>>> print(node.compute())
DataCollection(['Simulation cell', 'Position', 'Color', 'Structure Type'])

The output data collection is cached by the ObjectNode and may subsequently be accessed through the output attribute:

>>> print(node.output)
DataCollection(['Simulation cell', 'Position', 'Color', 'Structure Type'])

In our example, the CommonNeighborAnalysisModifier in the modification pipeline has added additional particle properties to the DataCollection. Particle properties, which are instances of the ParticleProperty class, are so-called data objects. Likewise, the simulation cell (SimulationCell) and bonds (Bonds) are data objects, which can all be part of a data collection.

The particle properties in a collection can be accessed through the particle_properties dictionary view. Use its keys() method to find out which particle properties are contained in the collection:

>>> data = node.compute()
>>> list(data.particle_properties.keys())
['Particle Identifier', 'Position', 
 'Potential Energy', 'Color', 'Structure Type']

Specific particle properties in the collection can be accessed using the dictionary interface:

>>> data.particle_properties['Potential Energy']
<ParticleProperty at 0x11d01d60>

Standard particle properties, however, can be directly accessed more conveniently via corresponding Python attributes, e.g.:

>>> data.particle_properties.potential_energy
<ParticleProperty at 0x11d01d60>

>>> print(data.particle_properties.position.array)
[[ 0.          0.          0.        ]
 [ 0.8397975   0.8397975   0.        ]
 ...

The SimulationCell, Bonds, and other data objects in the data collection can be accessed through its cell, bonds, surface, and dislocations property:

>>> data.cell
<SimulationCellObject at 0x24338a0>

>>> data.cell.matrix
[[ 3.35918999  0.          0.          0.        ]
 [ 0.          3.35918999  0.          0.        ]
 [ 0.          0.          3.35918999  0.        ]]
add(obj)

Inserts a DataObject into the DataCollection.

The method will do nothing if the data object is already part of the collection. A data object can be part of several data collections.

attributes

A dictionary object with key/value pairs that have been loaded from an input file or were produced by modifiers in the data pipeline.

Attributes are integer, float, or string values that are processed or generated by the modification pipeline. They represent global information or scalar quantities. This is in contrast to more complex data objects, which are also stored in the DataCollection such as particle properties or bonds.

Attribute names (dictionary keys) are simple strings such as "Timestep" or "ConstructSurfaceMesh.surface_area".

Attributes loaded from input files

The Timestep attribute is loaded from LAMMPS dump files and other simulation file formats that store the simulation timestep. This kind of information read from an input file can be retrieved from the attributes dictionary of the source data collection as follows:

>>> node = ovito.dataset.selected_node
>>> node.source.attributes['Timestep']
140000

Note that the attributes dictionary will contain all key/value pairs parsed from the comment line in the header of extended XYZ files.

Attributes computed by modifiers

Analysis modifiers like the CommonNeighborAnalysisModifier or the ClusterAnalysisModifier output scalar computation results as attributes. The class documentation of each modifier lists the names of the attributes it produces.

For example, the number of clusters generated by the ClusterAnalysisModifier can be queried as follows:

node.modifiers.append(ClusterAnalysisModifier(cutoff = 3.1))
node.compute()
nclusters = node.output.attributes["ClusterAnalysis.cluster_count"]

Exporting attributes to a text file

The ovito.io.export_file() function allows writing selected attributes to a text file, possibly as functions of time:

export_file(node, "data.txt", "txt", 
    columns = ["Timestep", "ClusterAnalysis.cluster_count"], 
    multiple_frames = True)

User-defined attributes

The PythonScriptModifier makes it possible for you to define your own attributes that are dynamically computed (on the basis of other information):

node.modifiers.append(CommonNeighborAnalysisModifier())

def compute_fcc_fraction(frame, input, output):
    n_fcc = input.attributes['CommonNeighborAnalysis.counts.FCC']
    output.attributes['fcc_fraction'] = n_fcc / input.number_of_particles

node.modifiers.append(PythonScriptModifier(function = compute_fcc_fraction))
node.compute()
print(node.output.attributes['fcc_fraction'])

In this example the CommonNeighborAnalysisModifier outputs the computed attribute CommonNeighborAnalysis.counts.FCC, which is the absolute number of atoms that form an FCC lattice. To compute the fraction of FCC atoms, we need to divide by the total number of atoms in the system. To this end, a PythonScriptModifier is defined and inserted into the pipeline following the CommonNeighborAnalysisModifier. The user-defined modifier function generates a new attribute named fcc_fraction. Finally, after the pipeline has been evaluated, the value of the user-defined attribute can be accessed as shown or exported to a text file.

bond_properties

Returns a dictionary view that provides access to the BondProperty instances stored in this DataCollection.

bonds

Returns the Bonds object stored in this DataCollection.

Accessing this property raises an AttributeError if the data collection contains no bonds.

cell

Returns the SimulationCell stored in this DataCollection.

Accessing this property raises an AttributeError if the data collection contains no simulation cell information.

copy_if_needed(obj)

Makes a copy of a data object if it was created upstream in the data pipeline.

Typically, this method is used in the user-defined implementation of a PythonScriptModifier that participates in OVITO’s data pipeline system. The user-defined modifier function receives a collection with input data objects from the system. However, directly modifying these input objects is not allowed because they are owned by the upstream part of the data pipeline. This is where this method comes into play: It makes a copy of a data object and replaces it with its copy in the modifier’s output. The modifier can then go ahead and modify the copy as needed, because it is now exclusively owned by the modifier.

The method first checks if obj, which must be a data object from this data collection, is owned by anybody else. If yes, it creates an exact copy of obj and replaces the original in this data collection with the copy. Now the copy is an independent object, which is referenced by nobody except this data collection. Thus, the modifier function is now free to modify the contents of the data object.

Note that the copy_if_needed() method should always be called on the output data collection of the modifier.

Parameters:obj (DataObject) – The object in the output data collection to be copied.
Returns:An exact copy of obj if obj is owned by someone else. Otherwise the original instance is returned.
create_bond_property(property_type, data=None)

Adds a standard bond property to this data collection.

If the specified particle property already exists in this data collection, the existing property instance is returned. Otherwise the method creates a new property instance using BondProperty.create() and adds it to this data collection.

The optional parameter data allows to directly set or initialize the values of the bond property.

Parameters:
  • property_type (BondProperty.Type) – The standard bond property to create. See the BondProperty.type attribute for a list of possible values.
  • data – An optional data array (e.g. NumPy array), which contains the per-bond values used to initialize the property. The size of the array must match the number of half-bonds in this data collection (see number_of_half_bonds attribute).
Returns:

A newly created instance of the ovito.data.BondProperty class or one of its sub-classes if the property did not exist yet in the data collection. Otherwise, the existing bond property object is returned.

classmethod create_from_ase_atoms(atoms)

Converts an ASE Atoms object to a DataCollection.

Note

The built-in Python interpreter shipping with OVITO does not contain the ASE module (Atomistic Simulation Environment). It is therefore recommended to build OVITO from source (as explained in the user manual), which will allow you to use all modules installed in the system’s Python interpreter.

Parameters:atoms

The ASE Atoms object to be converted.

Returns:A new DataCollection instance containing the converted data from the ASE object.
create_particle_property(property_type, data=None)

Adds a standard particle property to this data collection.

If the specified particle property already exists in this data collection, the existing property instance is returned. Otherwise the method creates a new property instance using ParticleProperty.create() and adds it to this data collection.

The optional parameter data allows to directly set or initialize the values of the particle property.

Parameters:
  • property_type (ParticleProperty.Type) – The standard particle property to create. See the ParticleProperty.type attribute for a list of possible values.
  • data – An optional data array (e.g. NumPy array), which contains the per-particle values used to initialize the particle property. The size of the array must match the number of particles in this data collection (see number_of_particles attribute).
Returns:

A newly created instance of the ovito.data.ParticleProperty class or one of its sub-classes if the property did not exist yet in the data collection. Otherwise, the existing particle property object is returned.

create_user_bond_property(name, data_type, num_components=1, data=None)

Adds a custom bond property to this data collection.

If a bond property with the given name already exists in this data collection, the existing property instance is returned. Otherwise the method creates a new property instance using BondProperty.create_user() and adds it to this data collection.

The optional parameter data allows to directly set or initialize the values of the bond property.

Parameters:
  • name (str) – The name of the user-defined bond property to create.
  • data_type (str) – Must be either "int" or "float".
  • num_components (int) – The number of components when creating a vector property.
  • data – An optional data array (e.g. NumPy array), which contains the per-bond values used to initialize the bond property. The size of the array must match the number of half-bonds in this data collection (see number_of_half_bonds attribute).
Returns:

A newly created instance of the BondProperty class or one of its sub-classes if the property did not exist yet in the data collection. Otherwise, the existing bond property object is returned.

create_user_particle_property(name, data_type, num_components=1, data=None)

Adds a user-defined particle property to this data collection.

If a particle property with the given name already exists in this data collection, the existing property instance is returned. Otherwise the method creates a new property instance using ParticleProperty.create_user() and adds it to this data collection.

The optional parameter data allows to directly set or initialize the values of the particle property.

Parameters:
  • name (str) – The name of the user-defined particle property to create.
  • data_type (str) – Must be either "int" or "float".
  • num_components (int) – The number of components when creating a vector property.
  • data – An optional data array (e.g. NumPy array), which contains the per-particle values used to initialize the particle property. The size of the array must match the number of particles in this data collection (see number_of_particles attribute).
Returns:

A newly created instance of the ParticleProperty class or one of its sub-classes if the property did not exist yet in the data collection. Otherwise, the existing particle property object is returned.

dislocations

Returns the DislocationNetwork object in this DataCollection.

Accessing this property raises an AttributeError if the data collection contains no dislocations object.

number_of_full_bonds

The number of (full) bonds stored in the data collection.

Note that OVITO internally represents each full bond as two half-bonds, A->B and B->A. See also number_of_half_bonds.

number_of_half_bonds

The number of half-bonds stored in the data collection.

Note that OVITO internally represents each full bond as two half-bonds, A->B and B->A. See also number_of_full_bonds.

number_of_particles

The number of particles stored in the data collection.

particle_properties

Returns a read-only dictionary view that provides access to the ParticleProperty objects stored in this DataCollection.

remove(obj)

Removes a DataObject from the DataCollection.

The method will do nothing if the data object is not part of the collection.

replace(old_obj, new_obj)

Replaces a DataObject in the DataCollection with a different one.

The method will do nothing if the data object to be replaced is not part of the collection.

surface

Returns the SurfaceMesh in this DataCollection.

Accessing this property raises an AttributeError if the data collection contains no surface mesh instance.

to_ase_atoms()

Constructs and returns an ASE Atoms object from the particles stored in this DataCollection.

Note

Calling this method raises an ImportError if ASE (Atomistic Simulation Environment) is not available. Note that the built-in Python interpreter shipping with OVITO does not contain the ASE module. It is therefore recommended to build OVITO from source (as explained in the user manual), which will allow you to use all modules installed in the system’s Python interpreter.

Returns:A new ASE Atoms object that contains the contains the converted particle data from this DataCollection.
class ovito.data.DataObject

Abstract base class for all data objects.

Some data objects are associated with a Display object, which is responsible for displaying the data in the viewports and in rendered images. The display attribute provides access to the attached display object and allows controlling the visual appearance of the data.

display

The Display object associated with this data object, which is responsible for displaying the data. If this field is None, the data is non-visual and doesn’t appear in the viewports or rendered images.

class ovito.data.DislocationNetwork
Base class:ovito.data.DataObject

This data object types stores the network of dislocation lines extracted by a DislocationAnalysisModifier.

Instances of this class are associated with a DislocationDisplay that controls the visual appearance of the dislocation lines. It can be accessed through the display attribute of the DataObject base class.

Example:

from ovito.io import import_file, export_file
from ovito.modifiers import DislocationAnalysisModifier

node = import_file("simulation.dump")

# Extract dislocation lines from a crystal with diamond structure:
modifier = DislocationAnalysisModifier()
modifier.input_crystal_structure = DislocationAnalysisModifier.Lattice.CubicDiamond
node.modifiers.append(modifier)
node.compute()

total_line_length = node.output.attributes['DislocationAnalysis.total_line_length']
print("Dislocation density: %f" % (total_line_length / node.output.cell.volume))

# Print list of dislocation lines:
network = node.output.dislocations
print("Found %i dislocation segments" % len(network.segments))
for segment in network.segments:
    print("Segment %i: length=%f, Burgers vector=%s" % (segment.id, segment.length, segment.true_burgers_vector))
    print(segment.points)

# Export dislocation lines to a CA file:
export_file(node, "dislocations.ca", "ca")
segments

The list of dislocation segments in this dislocation network. This list-like object is read-only and contains DislocationSegment objects.

class ovito.data.DislocationSegment

A single dislocation line from a DislocationNetwork.

The list of dislocation segments is returned by the DislocationNetwork.segments attribute.

cluster_id

The numeric identifier of the crystal cluster of atoms containing this dislocation segment.

The true Burgers vector of the segment is expressed in the local coordinate system of this crystal cluster.

id

The unique identifier of this dislocation segment.

is_infinite_line

This property indicates whether this segment is an infinite line passing through a periodic simulation box boundary. A segment is considered infinite if it is a closed loop and its start and end points do not coincide.

See also the is_loop property.

is_loop

This property indicates whether this segment forms a closed dislocation loop. Note that an infinite dislocation line passing through a periodic boundary is also considered a loop.

See also the is_infinite_line property.

length

Returns the length of this dislocation segment.

points

The list of space points that define the shape of this dislocation segment. This is a N x 3 Numpy array, where N is the number of points along the segment. For closed loops, the first and the last point coincide.

spatial_burgers_vector

The Burgers vector of the segment, expressed in the global coordinate system of the simulation. This vector is calculated by transforming the true Burgers vector from the local lattice coordinate system to the global simulation coordinate system using the average orientation matrix of the crystal cluster the dislocation segment is embedded in.

true_burgers_vector

The Burgers vector of the segment, expressed in the local coordinate system of the crystal. Also known as the True Burgers vector.

class ovito.data.NearestNeighborFinder(N, data_collection)

A utility class that finds the N nearest neighbors of a particle or a spatial location.

The constructor takes the (maximum) number of requested nearest neighbors, N, and a DataCollection containing the input particle positions and the cell geometry (including periodic boundary flags). N must be a positive integer not greater than 30 (which is the built-in maximum supported by this class).

Once the NearestNeighborFinder has been constructed, you can call its find() method to iterate over the sorted list of nearest neighbors of a specific particle, for example:

from ovito.io import import_file
from ovito.data import NearestNeighborFinder

# Load input simulation file.
node = import_file("simulation.dump")
data = node.source

# Initialize neighbor finder object.
# Visit the 12 nearest neighbors of each particle.
N = 12
finder = NearestNeighborFinder(N, data)

# Loop over all input particles:
for index in range(data.number_of_particles):
    print("Nearest neighbors of particle %i:" % index)
    # Iterate over the neighbors of the current particle, starting with the closest:
    for neigh in finder.find(index):
        print(neigh.index, neigh.distance, neigh.delta)

Furthermore, the class provides the find_at() method, which allows to query the nearest neighbors at an arbitrary spatial position (doesn’t have to be a physical particle):


# Find particles closest to some spatial point (x,y,z):
coords = (0, 0, 0)
for neigh in finder.find_at(coords):
    print(neigh.index, neigh.distance, neigh.delta)

If you want to find all neighbor particles within a certain cutoff radius of a central particle, use the CutoffNeighborFinder class instead.

find(index)

Returns an iterator that visits the N nearest neighbors of the given particle in order of ascending distance.

Parameters:index (int) – The index of the central particle whose neighbors should be iterated. Particle indices start at 0.
Returns:A Python iterator that visits the N nearest neighbors of the central particle in order of ascending distance. For each visited neighbor the iterator returns an object with the following attributes:
  • index: The index of the current neighbor particle (starting at 0).
  • distance: The distance of the current neighbor from the central particle.
  • distance_squared: The squared neighbor distance.
  • delta: The three-dimensional vector connecting the central particle with the current neighbor (taking into account periodicity).

Note that several periodic images of the same particle may be visited. Thus, the same particle index may appear multiple times in the neighbor list of a central particle. In fact, the central particle may be among its own neighbors in a sufficiently small periodic simulation cell. However, the computed neighbor vector (delta) will be unique for each visited image of a neighboring particle.

The number of neighbors actually visited may be smaller than the requested number, N, if the system contains too few particles and has no periodic boundary conditions.

find_at(coords)

Returns an iterator that visits the N nearest particles around a spatial point given by coords in order of ascending distance. Unlike the find() method, which queries the nearest neighbors of a physical particle, the find_at() method allows searching for neareby particles at arbitrary locations in space.

Parameters:coords – A (x,y,z) coordinate triple specifying the spatial location where the N nearest particles should be queried.
Returns:A Python iterator that visits the N nearest neighbors in order of ascending distance. For each visited particle the iterator returns an object with the following attributes:
  • index: The index of the current particle (starting at 0).
  • distance: The distance of the current neighbor from the query location.
  • distance_squared: The squared distance to the query location.
  • delta: The three-dimensional vector from the query point to the current particle (taking into account periodicity).

If there exists a particle that is exactly located at the query position given by coords, then it will be returned by this function. This is in contrast to the find() function, which does not visit the central particle itself.

The number of neighbors actually visited may be smaller than the requested number, N, if the system contains too few particles and has no periodic boundary conditions.

class ovito.data.ParticleProperty
Base class:ovito.data.DataObject

A data object that stores the per-particle values of a particle property.

The list of properties associated with a particle dataset can be access via the DataCollection.particle_properties dictionary. The size of a particle property is always equal to the number of particles in the dataset. The per-particle data of a property can be accessed as a NumPy array through the array attribute.

If you want to modify the property values, you have to use the marray (modifiable array) attribute instead, which provides read/write access to the underlying per-particle data. After you are done modifying the property values, you should call changed() to inform the system that it needs to update any state that depends on the data.

array

This attribute returns a NumPy array, which provides read access to the per-particle data stored in this particle property object.

The returned array is one-dimensional for scalar particle properties (components == 1), or two-dimensional for vector properties (components > 1). The outer length of the array is equal to the number of particles in both cases.

Note that the returned NumPy array is read-only and provides a view of the internal data. No copy of the data, which may be shared by multiple objects, is made. If you want to modify the data stored in this particle property, use marray instead.

changed()

Informs the particle property object that its internal data has changed. This function must be called after each direct modification of the per-particle data through the marray attribute.

Calling this method on an input particle property is necessary to invalidate data caches down the modification pipeline. Forgetting to call this method may result in an incomplete re-evaluation of the modification pipeline. See marray for more information.

components

The number of vector components (if this is a vector particle property); otherwise 1 (= scalar property).

static create(prop_type, num_particles)

Static factory function that creates a new ParticleProperty instance for a standard particle property. To create a new user-defined property, use create_user() instead.

Note that this factory function is a low-level method. If you want to add a new particle property to an existing DataCollection, you can do so using the high-level method create_particle_property() instead.

Parameters:
  • prop_type (ParticleProperty.Type) – The standard particle property to create. See the type attribute for a list of possible values.
  • num_particles (int) – The number of particles. This determines the size of the allocated data array.
Returns:

A newly created instance of the ParticleProperty class or one of its sub-classes.

static create_user(name, data_type, num_particles, num_components=1)

Static factory function that creates a new ParticleProperty instance for a user-defined particle property. To create one of the standard properties, use create() instead.

Note that this factory function is a low-level method. If you want to add a new user-defined particle property to an existing DataCollection, you can do so using the high-level method create_user_particle_property() instead.

Parameters:
  • name (str) – The name of the user-defined particle property to create.
  • data_type (str) – Must be either "int" or "float".
  • num_particles (int) – The number of particles. This determines the size of the allocated data array.
  • num_components (int) – The number of components when creating a vector property.
Returns:

A newly created instance of the ParticleProperty class.

findInState()
marray

This attribute returns a mutable NumPy array providing read/write access to the internal per-particle data.

The returned array is one-dimensional for scalar particle properties (components == 1), or two-dimensional for vector properties (components > 1). The outer length of the array is equal to the number of particles in both cases.

Note

After you are done modifying the data in the returned NumPy array, you must call changed()! Calling this method is necessary to inform the data pipeline system that the input particle data has changed and the modification pipeline needs to be re-evaluated. The reason is that OVITO cannot automatically detect modifications made by the script to the returned NumPy array. Therefore, an explicit call to changed() is necessary.

Example

from ovito.io import import_file
from ovito.modifiers import *

# Load a simulation file.
node = import_file('simulation.dump')
# Set up modification pipeline, which selects and deletes all particle of type 2.
node.modifiers.append(SelectParticleTypeModifier(property='Particle Type', types={2}))
node.modifiers.append(DeleteSelectedParticlesModifier())

# Evaluate modification pipeline the first time.
output1 = node.compute()
print('Number of remaining particles: ', output1.number_of_particles)

# Modify pipeline input by changing the type of the first particle to 2.
node.source.particle_properties.particle_type.marray[0] = 2

# Inform pipeline that input has changed.
# Failing to do so would lead to incorrect results below. OVITO would assume the 
# cached pipeline output is  still valid and wouldn't re-evaluate the modifiers.
node.source.particle_properties.particle_type.changed()

# Evaluate modification pipeline a second time.
# Note that compute() may return cached results if it thinks the 
# pipeline's input hasn't changed since the last call.
output2 = node.compute()
print('Number of remaining particles: ', output2.number_of_particles)
assert(output2.number_of_particles == output1.number_of_particles - 1)
name

The human-readable name of this particle property.

size

The number of particles.

type

The type of the particle property (user-defined or one of the standard types). One of the following constants:

Type constant Property name Data type Component names
ParticleProperty.Type.User (a user-defined property with a non-standard name) int/float  
ParticleProperty.Type.ParticleType Particle Type int  
ParticleProperty.Type.Position Position float X, Y, Z
ParticleProperty.Type.Selection Selection int  
ParticleProperty.Type.Color Color float R, G, B
ParticleProperty.Type.Displacement Displacement float X, Y, Z
ParticleProperty.Type.DisplacementMagnitude Displacement Magnitude float  
ParticleProperty.Type.PotentialEnergy Potential Energy float  
ParticleProperty.Type.KineticEnergy Kinetic Energy float  
ParticleProperty.Type.TotalEnergy Total Energy float  
ParticleProperty.Type.Velocity Velocity float X, Y, Z
ParticleProperty.Type.Radius Radius float  
ParticleProperty.Type.Cluster Cluster int  
ParticleProperty.Type.Coordination Coordination int  
ParticleProperty.Type.StructureType Structure Type int  
ParticleProperty.Type.Identifier Particle Identifier int  
ParticleProperty.Type.StressTensor Stress Tensor float XX, YY, ZZ, XY, XZ, YZ
ParticleProperty.Type.StrainTensor Strain Tensor float XX, YY, ZZ, XY, XZ, YZ
ParticleProperty.Type.DeformationGradient Deformation Gradient float 11, 21, 31, 12, 22, 32, 13, 23, 33
ParticleProperty.Type.Orientation Orientation float X, Y, Z, W
ParticleProperty.Type.Force Force float X, Y, Z
ParticleProperty.Type.Mass Mass float  
ParticleProperty.Type.Charge Charge float  
ParticleProperty.Type.PeriodicImage Periodic Image int X, Y, Z
ParticleProperty.Type.Transparency Transparency float  
ParticleProperty.Type.DipoleOrientation Dipole Orientation float X, Y, Z
ParticleProperty.Type.DipoleMagnitude Dipole Magnitude float  
ParticleProperty.Type.AngularVelocity Angular Velocity float X, Y, Z
ParticleProperty.Type.AngularMomentum Angular Momentum float X, Y, Z
ParticleProperty.Type.Torque Torque float X, Y, Z
ParticleProperty.Type.Spin Spin float  
ParticleProperty.Type.CentroSymmetry Centrosymmetry float  
ParticleProperty.Type.VelocityMagnitude Velocity Magnitude float  
ParticleProperty.Type.Molecule Molecule Identifier int  
ParticleProperty.Type.AsphericalShape Aspherical Shape float X, Y, Z
ParticleProperty.Type.VectorColor Vector Color float R, G, B
ParticleProperty.Type.ElasticStrainTensor Elastic Strain float XX, YY, ZZ, XY, XZ, YZ
ParticleProperty.Type.ElasticDeformationGradient Elastic Deformation Gradient float XX, YX, ZX, XY, YY, ZY, XZ, YZ, ZZ
ParticleProperty.Type.Rotation Rotation float X, Y, Z, W
ParticleProperty.Type.StretchTensor Stretch Tensor float XX, YY, ZZ, XY, XZ, YZ
ParticleProperty.Type.MoleculeType Molecule Type int  
class ovito.data.ParticleType

Stores the properties of a particle type or atom type.

The list of particle types is stored in the ParticleTypeProperty class.

color

The display color to use for particles of this type.

id

The identifier of the particle type.

name

The display name of this particle type.

radius

The display radius to use for particles of this type.

class ovito.data.ParticleTypeProperty
Base class:ovito.data.ParticleProperty

This is a specialization of the ParticleProperty class, which holds a list of ParticleType instances in addition to the per-particle type values.

OVITO encodes the types of particles (chemical and also others) as integer values starting at 1. Like for any other particle property, the numeric type of each particle can be accessed as a NumPy array through the array attribute of the base class, or modified through the mutable marray NumPy interface:

>>> type_property = node.source.particle_properties.particle_type
>>> print(type_property.array)
[1 3 2 ..., 2 1 2]

In addition to these per-particle type values, the ParticleTypeProperty class keeps the type_list, which contains all defined particle types including their names, IDs, display color and radius. Each defined type is represented by an ParticleType instance and has a unique integer ID, a human-readable name (e.g. the chemical symbol) and a display color and radius:

>>> for t in type_property.type_list:
...     print(t.id, t.name, t.color, t.radius)
... 
1 N (0.188 0.313 0.972) 0.74
2 C (0.564 0.564 0.564) 0.77
3 O (1 0.050 0.050) 0.74
4 S (0.97 0.97 0.97) 0.0

Each particle type has a unique numeric ID (typically starting at 1). Note that, in this particular example, types were stored in order of ascending ID in the type_list. This may not always be the case. To quickly look up the ParticleType and its name for a given ID, the get_type_by_id() method is available:

>>> for t in type_property.array:
...     print(type_property.get_type_by_id(t).name)
... 
N
O
C

Conversely, the ParticleType and its numeric ID can be looked by name using the get_type_by_name() method. For example, to count the number of oxygen atoms in a system:

>>> O_type_id = type_property.get_type_by_name('O').id
>>> numpy.count_nonzero(type_property.array == O_type_id)
957

Note that particles may be associated with multiple kinds of types in OVITO. This includes, for example, the chemical type and the structural type. Thus, several type classifications of particles can co-exist, each being represented by a separate instance of the ParticleTypeProperty class and a separate type_list. For example, while the 'Particle Type' property stores the chemical type of atoms (e.g. C, H, Fe, ...), the 'Structure Type' property stores the structural type computed for each atom (e.g. FCC, BCC, ...).

get_type_by_id(id)

Returns the ParticleType with the given numeric ID from the type_list. Raises a KeyError if the ID does not exist.

get_type_by_name(name)

Returns the ParticleType with the given name from the type_list. If multiple types exists with the same name, the first type is returned. Raises a KeyError if there is no type with such a name.

type_list

A (mutable) list of ParticleType instances.

Note that the particle types may be stored in arbitrary order in this type list. Each type has a unique integer ID (given by the ParticleType.id attribute). The numbers stored in the particle type property array refer to these type IDs.

class ovito.data.SimulationCell
Base class:ovito.data.DataObject

Stores the shape and the boundary conditions of the simulation cell.

Each instance of this class is associated with a corresponding SimulationCellDisplay that controls the visual appearance of the simulation cell. It can be accessed through the display attribute of the SimulationCell object, which is defined by the DataObject base class.

The simulation cell of a particle dataset can be accessed via the DataCollection.cell property.

Example:

from ovito.io import import_file
import numpy.linalg

node = import_file("simulation.dump")
cell = node.source.cell

# Compute simulation cell volume by taking the determinant of the
# left 3x3 submatrix:
volume = abs(numpy.linalg.det(cell.matrix[0:3,0:3]))

# Make cell twice as large along the Y direction by scaling the
# second cell vector.
mat = cell.matrix.copy()
mat[:,1] = mat[:,1] * 2.0
cell.matrix = mat

# Change color of simulation cell to red:
cell.display.rendering_color = (1.0, 0.0, 0.0)
is2D

Specifies whether the system is two-dimensional (true) or three-dimensional (false). For two-dimensional systems the PBC flag in the third direction (z) and the third cell vector are ignored.

Default:false
matrix

A 3x4 matrix containing the three edge vectors of the cell (matrix columns 0 to 2) and the cell origin (matrix column 3).

pbc

A tuple with three boolean values, which specify periodic boundary flags of the simulation cell along each cell vector.

volume

Returns the volume of the three-dimensional simulation cell. It is the absolute value of the determinant of the cell matrix.

volume2D

Returns the volume of the two-dimensional simulation cell (see is2D).

class ovito.data.SurfaceMesh
Base class:ovito.data.DataObject

This data object stores the surface mesh computed by a ConstructSurfaceModifier.

Currently, no direct script access to the vertices and faces of the mesh is possible. But you can export the mesh to a VTK text file, which can be further processed by external tools such as ParaView.

The visual appearance of the surface mesh within Ovito is controlled by its attached SurfaceMeshDisplay instance, which is accessible through the display attribute of the DataObject base class or through the mesh_display attribute of the ConstructSurfaceModifier that created the surface mesh.

Example:

from ovito.io import import_file
from ovito.modifiers import ConstructSurfaceModifier

# Load a particle structure and construct its surface mesh:
node = import_file("simulation.dump")
node.modifiers.append(ConstructSurfaceModifier(radius = 2.8))
node.compute()

# Access the computed surface mesh and export it to VTK files for 
# visualization with ParaView.
mesh = node.output.surface
mesh.export_vtk('surface.vtk', node.output.cell)
mesh.export_cap_vtk('surface_cap.vtk', node.output.cell)
export_cap_vtk(filename, cell)

If the surface mesh has been generated from a SimulationCell with periodic boundary conditions, then this method computes the cap polygons from the intersection of the surface mesh with the periodic cell boundaries. The cap polygons are written to a VTK file, which is a simple text-based format and which can be opened with the software ParaView.

export_vtk(filename, cell)

Writes the surface mesh to a VTK file, which is a simple text-based format and which can be opened with the software ParaView. The method takes the output filename and a SimulationCell object as input. The simulation cell information is needed by the method to generate a non-periodic version of the mesh, which is truncated at the periodic boundaries of the simulation cell (if it has any).