ovito.pipeline

This module contains object types that are part of OVITO’s data pipeline system.

Pipelines:

Data sources:

class ovito.pipeline.Pipeline

This class encapsulates a data pipeline, consisting of a data source and a chain of zero or more modifiers, which manipulate the data on the way through the pipeline.

Pipeline creation

A pipeline always has a data source, which loads or dynamically generates the input data entering the pipeline. This source object is accessible through the Pipeline.source field and may be replaced if needed. For pipelines created by the import_file() function, the data source is automatically set to be a FileSource instance, which is responsible for loading the input data from the external file and feeding it into the pipeline. Another type of data source is the StaticSource, which allows to explicitly specify the set of data objects entering the pipeline.

The modifiers that are part of the pipeline are accessible through the Pipeline.modifiers list. This list is initially empty and you can populate it with modifiers of various kinds (see the ovito.modifiers module). Note that it is possible to employ the same Modifier instance in more than one pipeline. And it is valid to share the same data source between several pipelines to let them process the same input data.

Pipeline evaluation

Once the pipeline is set up, an evaluation can be requested by calling compute(), which means that the input data will be loaded/generated by the source and all modifiers of the pipeline are applied to the data one after the other. The compute() method returns a new DataCollection containing all the data objects produced by the pipeline. Under the hood, an automatic caching system ensure that unnecessary file accesses and computations are avoided. Repeatedly calling compute() will not trigger a recalculation of the pipeline’s results unless you alter the pipeline’s source, the sequence of modifiers or any of the modifier’s parameters.

Usage example

The following code example shows how to create a new pipeline by importing an MD simulation file and inserting a SliceModifier to cut away some of the particles. Finally, the total number of remaining particles is printed.

from ovito.io import import_file
from ovito.modifiers import SliceModifier

# Import a simulation file. This creates a Pipeline object.
pipeline = import_file('input/simulation.dump')

# Insert a modifier that operates on the data:
pipeline.modifiers.append(SliceModifier(normal=(0,0,1), distance=0))

# Compute the effect of the slice modifier by evaluating the pipeline.
output = pipeline.compute()
print("Remaining particle count:", output.particles.count)

Note that you can access the input data of the pipeline by calling the FileSource.compute() method:

# Access the pipeline's input data provided by the FileSource:
input = pipeline.source.compute()
print("Input particle count:", input.particles.count)

Data visualization

If you intend to produce a graphical rendering of a pipeline’s output data, you need to make the pipeline part of the current three-dimensional scene by calling its add_to_scene() method. The visual appearance of the output data is controlled by so-called visual elements, which are generated within the pipeline. The get_vis() method helps you look up a visual element of a particular type.

Data export

To export the generated data of the pipeline to an output file, simply call the ovito.io.export_file() function with the pipeline.

add_to_scene()

Inserts the pipeline into the three-dimensional scene by appending it to the ovito.Scene.pipelines list. The visual representation of the computed data will appear in rendered images and in the interactive viewports of the graphical OVITO version.

You can remove the pipeline from the scene again using remove_from_scene().

compute(frame=None)

Computes and returns the results of this data pipeline.

This method requests an evaluation of the pipeline and blocks until the input data has been obtained from the data source and all modifiers have been applied to the data. When invoking the compute() method repeatedly without changing the pipeline between calls, it may return immediately with cached results from an earlier evaluation.

The optional frame parameter determines at which animation time the pipeline is evaluated. Animation frame numbering starts at 0. If no frame is specified, the current animation position is used (frame 0 by default).

The compute() method raises a RuntimeError when the pipeline could not be successfully evaluated for some reason. This can happen due to invalid modifier parameters or input file parsing errors, for example.

Note: The returned DataCollection contains data objects that are owned by the pipeline. That means it is not safe to modify these objects as this would lead to unexpected side effects. You can however use the DataCollection.copy_if_needed() method to make a copy of data objects that you want to modify in place. See the DataCollection class for more information.

Parameters:frame (int) – The animation frame number at which the pipeline should be evaluated.
Returns:A DataCollection containing the output of the data pipeline.
get_vis(vis_type)

Looks up a visual element of a specified type in this pipeline’s output. This method implicitly calls compute() and visits all data objects in the pipeline’s output until it finds one that has a visual element of the given class type attached.

Parameters:vis_type – The DataVis subclass to be looked up.
Returns:An instance of the given DataVis-derived class; or None if there is no such visual element in this pipeline’s output.

The method can be used to easily access particular visual elements. The following code example demonstrates how the ParticlesVis element that is attached to the Position particle property can be looked up:

from ovito.vis import ParticlesVis

# Access the visual element responsible for the particle display:
pipeline.get_vis(ParticlesVis).radius = 1.3

# Note that get_vis() has returned the ParticlesVis element that is attached 
# to the 'Position' particle property:
assert(pipeline.compute().particles['Position'].vis.radius == 1.3)

See the ovito.vis module for a list of visual element types in OVITO that can be looked up using this method.

modifiers

The sequence of modifiers in the pipeline.

This list contains any modifiers that are applied to the input data provided by the pipeline’s data source. You can add and remove modifiers as needed using standard Python append() and del operations. The head of the list represents the beginning of the pipeline, i.e. the first modifier receives the data from the data source, manipulates it and passes the results on to the second modifier in the list and so forth.

Example: Adding a new modifier to the end of a data pipeline:

pipeline.modifiers.append(WrapPeriodicImagesModifier())
remove_from_scene()

Removes the visual representation of the pipeline from the scene by deleting it from the ovito.Scene.pipelines list. The output data of the pipeline will disappear from the viewports.

source

The object that provides the data entering the pipeline. This typically is a FileSource instance if the pipeline was created by a call to import_file(). You can assign a new source to the pipeline if needed. See the ovito.pipeline module for a list of available pipeline source types. Note that you can even make several pipelines share the same source object.

class ovito.pipeline.Modifier

This is the base class for all modifier types in OVITO. See the ovito.modifiers module for a list of concrete modifier types that can be inserted into a data Pipeline.

enabled

Controls whether the modifier is applied to the data. Disabled modifiers are skipped during evaluation of a data pipeline.

Default:True
class ovito.pipeline.StaticSource

Serves as a data source for a Pipeline. A StaticSource stores a DataCollection, which will be passed to the Pipeline as input data. One typically fills a StaticSource with some data objects and wires it to a Pipeline as follows:

from ovito.pipeline import StaticSource, Pipeline
from ovito.data import DataCollection, SimulationCell
from ovito.modifiers import CreateBondsModifier
from ovito.io import export_file

# Insert a new SimulationCell object into a data collection:
data = DataCollection()
cell = SimulationCell(pbc = (False, False, False))
with cell:
    cell[:,0] = (4,0,0)
    cell[:,1] = (0,2,0)
    cell[:,2] = (0,0,2)
data.objects.append(cell)

# Create two particles:
xyz = [[0,0,0],[2,0,0]]
data.particles.create_property('Position', data = xyz)

# Create a new Pipeline with a StaticSource as data source:
pipeline = Pipeline(source = StaticSource())
pipeline.source.assign(data)

# Apply a modifier:
pipeline.modifiers.append(CreateBondsModifier(cutoff = 3.0))

# Write pipeline results to an output file:
export_file(pipeline, 'output/structure.data', 'lammps/data', atom_style='bond')
assign(data)

Sets the contents of this StaticSource.

Parameters:data – The DataCollection to be copied into this static source object.
compute(frame=None)

Retrieves the data of this data source, which was previously stored by a call to assign().

Parameters:frame – This parameter is ignored, because the data of a StaticSource is not time-dependent.
Returns:A new DataCollection containing the data stored in this StaticSource.
class ovito.pipeline.FileSource

This object type can serve as a Pipeline.source and takes care of reading the input for the Pipeline from an external data file.

You normally do not need to create an instance of this class yourself; the import_file() function does it for you and wires the configured FileSource to a Pipeline. If desired, the FileSource.load() method allows you to load a different input file later on and replace the inputs of the pipeline:

from ovito.io import import_file

# Create a new pipeline with a FileSource:
pipeline = import_file('input/first_file.dump')

# Get the data from the first file:
data1 = pipeline.compute()

# Use FileSource.load() method to replace the pipeline's input with a different file 
pipeline.source.load('input/second_file.dump')

# Now the pipeline gets its input data from the new file:
data2 = pipeline.compute()

Furthermore, additional FileSource instances are typically employed in conjunction with certain modifiers. The CalculateDisplacementsModifier can make use of a FileSource to load reference particle positions from a separate input file. Another example is the LoadTrajectoryModifier, which employs its own separate FileSource instance to load the particle trajectories from disk and combine them with the topology data previously loaded by the main FileSource of the data pipeline.

Data access

Calling a file source’s compute() method returns a new DataCollection containing the data that was read from the input file. Thus, this method provides access to a Pipeline’s unmodified input data:

# This creates a Pipeline with an attached FileSource.
pipeline = import_file('input/simulation.dump')

# Retrieve the data for the first frame from the FileSource.
data = pipeline.source.compute(0)
print(data.particles['Position'][...])
compute(frame=None)

Requests data from this data source. The FileSource will load it from the external file if needed.

The optional frame parameter determines the frame to retrieve, which must be in the range 0 through (num_frames-1). If no frame number is specified, the current animation position is used (frame 0 by default).

The FileSource uses a caching mechanism to keep the data for one or more frames in memory. Thus, invoking compute() repeatedly to retrieve the same frame will typically be very fast.

Note: The returned DataCollection contains data objects that are owned by the FileSource. That means it is not safe to modify these objects as this would lead to unexpected side effects. You should always use the DataCollection.copy_if_needed() method to make a copy of the data objects that you want to modify. See the DataCollection class for more information.

Parameters:frame (int) – The animation frame number at which the source should be evaluated.
Returns:A DataCollection containing the loaded data.
load(location, **params)

Sets a new input file, from which this data source will retrieve its data from.

The function accepts additional keyword arguments, which are forwarded to the format-specific file importer. For further information, please see the documentation of the import_file() function, which has the same function interface as this method.

Parameters:location (str) – The local file(s) or remote sftp:// URL to load.
num_frames

This read-only attribute reports the number of frames found in the input file or sequence of input files. The data for the individual frames can be obtained using the compute() method.

source_path

This read-only attribute returns the path(s) or URL(s) of the file(s) where this FileSource retrieves its input data from. You can change the source path by calling load().

class ovito.pipeline.ReferenceConfigurationModifier
Base class:ovito.pipeline.Modifier

This is the common base class of analyis modifiers that perform some kind of comparison of the current particle configuration with a reference configuration. For example, the CalculateDisplacementsModifier, the AtomicStrainModifier and the WignerSeitzAnalysisModifier are modifier types that require a reference configuration as additional input.

Constant and sliding reference configurations

The ReferenceConfigurationModifier base class provides various fields that allow you to specify the reference particle configuration. By default, frame 0 of the currently loaded simulation sequence is used as reference. You can select any other frame with the reference_frame field. Sometimes an incremental analysis is desired, instead of a fixed reference configuration. That means the sliding reference configuration and the current configuration are separated along the time axis by a constant period (delta t). The incremental analysis mode is activated by setting the use_frame_offset flag and specifying the desired frame_offset.

External reference configuration file

By default, the reference particle positions are obtained by evaluating the same data pipeline that also provides the current particle positions, i.e. which the modifier is part of. That means any modifiers preceding this modifier in the pipeline will also act upon the reference particle configuration, but not modifiers that follow in the pipeline.

Instead of taking it from the same data pipeline, you can explicitly provide a reference configuration by loading it from a separate data file. To this end the reference field contains a FileSource object and you can use its load() method to load the reference particle positions from a separate file.

Handling of periodic boundary conditions and cell deformations

Certain analysis modifiers such as the CalculateDisplacementsModifier and the AtomicStrainModifier calculate the displacements particles experienced between the reference and the current configuration. Since particle coordinates in periodic simulation cells are often stored in a wrapped form, caculating the displacement vectors is non-trivial when particles have crossed the periodic boundaries. By default, the minimum image convention is used in these cases, but you can turn if off by setting minimum_image_convention to False, for example if the input particle coordinates are given in unwrapped form.

Furthermore, if the simulation cell of the reference and the current configuration are different, it makes a slight difference whether displacements are calculated in the reference or in the current frame. The affine_mapping property controls the type of coordinate mapping that is used.

affine_mapping
Selects the type of affine deformation applied to the particle coordinates of either the reference or the current configuration prior to the actual analysis computation. Must be one of the following modes:
  • ReferenceConfigurationModifier.AffineMapping.Off
  • ReferenceConfigurationModifier.AffineMapping.ToReference
  • ReferenceConfigurationModifier.AffineMapping.ToCurrent

When affine mapping is disabled (AffineMapping.Off), particle displacement vectors are simply calculated from the difference of current and reference positions, irrespective of the cell shape the reference and current configuration. Note that this can introduce a small geometric error if the shape of the periodic simulation cell changes considerably. The mode AffineMapping.ToReference applies an affine transformation to the current configuration such that all particle positions are first mapped to the reference cell before calculating the displacement vectors. The last option, AffineMapping.ToCurrent, does the reverse: it maps the reference particle positions to the deformed cell before calculating the displacements.

Default:ReferenceConfigurationModifier.AffineMapping.Off
frame_offset

The relative frame offset when using a sliding reference configuration (if use_frame_offset == True). Negative frame offsets correspond to reference configurations that precede the current configuration in time.

Default:-1
minimum_image_convention

If False, then displacements are calculated from the particle coordinates in the reference and the current configuration as is. Note that in this case the calculated displacements of particles that have crossed a periodic simulation cell boundary will be wrong if their coordinates are stored in a wrapped form. If True, then the minimum image convention is applied when calculating the displacements of particles that have crossed a periodic boundary.

Default:True
reference

A pipeline source object that provides the reference particle positions. By default this field is None, in which case the modifier obtains the reference particle positions from data pipeline it is part of. You can explicitly assign a data source object such as a FileSource or a StaticSource to this field to specify an explicit reference configuration.

For backward compatibility reasons with older OVITO versions, a FileSource instance is automatically created for you on the first read access to this field. You can call its load() method to load the reference particle positions from a data file.

# The modifier that requires a reference config:
mod = CalculateDisplacementsModifier()

# Load the reference config from a separate input file.
mod.reference = FileSource()
mod.reference.load('input/simulation.0.dump')
Default:None
reference_frame

The frame number to use as reference configuration. Ignored if use_frame_offset is set.

Default:0
use_frame_offset

Determines whether a sliding reference configuration is taken at a constant time offset (specified by frame_offset) relative to the current frame. If False, a constant reference configuration is used (set by the reference_frame parameter) irrespective of the current frame.

Default:False