This module contains classes that are part of OVITO’s data pipeline system.
- class ovito.pipeline.FileSource
You normally do not need to create an instance of this class yourself; the
import_file()function does it for you and wires the fully configured
FileSourceto the new
Pipeline. However, if needed, the
FileSource.load()method allows you to load a different input file later on and replace the input of the existing pipeline with a new dataset:
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, you will encounter other
FileSourceobjects in conjunction with certain modifiers that need secondary input data from a separate file. The
CalculateDisplacementsModifier, for example, manages its own
FileSourcefor loading reference particle positions from a separate input file. Another example is the
LoadTrajectoryModifier, which employs its own separate
FileSourceinstance to load the particle trajectories from disk and combine them with the topology data previously loaded by the main
FileSourceof the data pipeline.
FileSourceclass provides two ways of accessing the data that is loaded from the external input file(s). For read-only access to the data, the
FileSource.compute()method should be called. It loads the data of a specific frame from the input simulation trajectory and returns it as a new
# This creates a new Pipeline with an attached FileSource. pipeline = import_file('input/simulation.dump') # Request data of animation frame 0 from the FileSource. data = pipeline.source.compute(0) print(data.particles.positions[...])
To modify or amend the
DataCollectionthat was loaded by the
FileSource, you should insert a user-defined modifier function into the pipeline. A typical use case is assigning the radii and names to particle types loaded from a simulation file that doesn’t contain named atom types:
pipeline = import_file('input/simulation.dump') # User-defined modifier function that assigns names and radii to numeric atom types: def setup_atom_types(frame, data): types = data.particles_.particle_types_ types.type_by_id_(1).name = "Cu" types.type_by_id_(1).radius = 1.35 types.type_by_id_(2).name = "Zr" types.type_by_id_(2).radius = 1.55 pipeline.modifiers.append(setup_atom_types)
Requests data from this data source. The
FileSourcewill 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 time slider position is used (will always be frame 0 for scripts not running in the context of an interactive OVITO session).
FileSourceuses 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.
- property data
This field provides access to the internal
DataCollection, i.e. the master copy of the data loaded from the input file (at frame 0).
- 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 reader. For further information, please see the documentation of the
import_file()function, which has the same function interface as this method.
location (str) – The local file(s) or remote URL to load.
- property 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
- class ovito.pipeline.Modifier
- property enabled
Controls whether the modifier is applied to the data. Disabled modifiers are skipped during evaluation of a data pipeline.
- class ovito.pipeline.ModifierInterface
Abstract base class for Python script modifiers that make use of the advanced programming interface.
New in version 3.8.0.
- 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.
Every pipeline has a data source, which loads or dynamically generates the input data entering the pipeline. This source is accessible through the
Pipeline.sourcefield and may be replaced with a different kind of source object if needed. For pipelines created by the
import_file()function, the data source is automatically set to be a
FileSourceobject, which loads the input data from the external file and feeds it into the pipeline. Another kind of data source is the
StaticSource, which can be used if you want to programmatically specify the input data for the pipeline instead of loading it from a file.
The modifiers that are part of the pipeline are accessible through the
Pipeline.modifiersfield. This list is initially empty and you can populate it with the modifier types found in the
ovito.modifiersmodule. Note that it is possible to employ the same
Modifierinstance in more than one pipeline. And it is okay to use the same data source object for several pipelines, letting them process the same input data.
Once the pipeline is set up, its computation results can be requested by calling
compute(), which means that the input data will be loaded/generated by the
sourceand all modifiers of the pipeline are applied to the data one after the other. The
compute()method returns a new
DataCollectionstoring the data objects produced by the pipeline. Under the hood, an automatic caching system ensures 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 data source, the chain of modifiers, or a modifier’s parameters.
The following code example shows how to create a new pipeline by importing an MD simulation file and inserting a
SliceModifierto 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)
If you would like to access the unmodified input data of the pipeline, i.e. before it has been processed by any of the modifiers, you can call the
# Access the pipeline's input data provided by the FileSource: input = pipeline.source.compute() print("Input particle count:", input.particles.count)
If you intend to produce graphical renderings of a output data produced by a pipeline, you must make the pipeline part of the current three-dimensional scene by calling the
To export the generated data of the pipeline to an output file, simply call the
ovito.io.export_file()function with the pipeline.
Inserts the pipeline into the three-dimensional scene by appending it to the
ovito.Scene.pipelineslist. The visual representation of the pipeline’s output data will appear in rendered images and in the interactive viewports.
You can remove the pipeline from the scene again using
Computes and returns the results of this data pipeline.
This method requests an evaluation of the pipeline and blocks while the input data is being obtained from the data
sourceand all modifiers are applied to the data. If you invoke the
compute()method repeatedly without changing the pipeline between calls, the method may serve subsequent requests by immediately returning a cached pipeline output.
The optional frame parameter specifies the animation time at which the pipeline should be evaluated. Frame numbering starts at 0. If you don’t specify a frame number, the current time slider position of OVITO is used; or frame 0 when execution doesn’t take place in an interactive OVITO session.
compute()method raises a
RuntimeErrorif the pipeline could not be successfully evaluated for some reason. This may happen due to invalid modifier settings or file I/O errors, for example.
frame (int) – The animation frame number at which the pipeline should be evaluated.
DataCollectionproduced by the data pipeline.
This method creates a static snapshot of the results of the current pipeline. The returned
DataCollectionwill not reflect any changes you subsequently make to the pipeline or the modifiers. You have to invoke
compute()again if you want updated results.
DataCollectionbehaves like an independent copy of the pipeline’s output data. If you make changes to the objects in the
DataCollection, the changes will not be visible to the modifiers within the pipeline nor will they be persistent, i.e., subsequent calls to
compute()will not produce data collections containing the same changes.
If your intention is to change the data before it gets passed to the modifiers in the pipeline, insert a user-defined modifier function into the pipeline, which lets you manipulate the
DataCollectionbefore subsequent modifiers in the downstream pipeline see it.
- property 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
deloperations. 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:
Removes the visual representation of the pipeline from the scene by deleting it from the
ovito.Scene.pipelineslist. The output data of the pipeline will disappear from viewports.
- property source
The object that provides the data entering the pipeline. This typically is a
FileSourceinstance 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.pipelinemodule for a list of available pipeline source types. Note that you can even make several pipelines share the same source object.
- class ovito.pipeline.PythonScriptSource
from ovito.pipeline import Pipeline, PythonScriptSource from ovito.io import export_file from ovito.data import Particles, DataCollection import numpy # Define a data source function, which fills an empty DataCollection with # some data objects. def create_particles(frame: int, data: DataCollection): data.particles = Particles(count = 20) coordinates = data.particles_.create_property('Position') coordinates[:,0] = numpy.linspace(0.0, 50.0, data.particles.count) coordinates[:,1] = numpy.cos(coordinates[:,0]/4.0 + frame/5.0) coordinates[:,2] = numpy.sin(coordinates[:,0]/4.0 + frame/5.0) # Create a data pipeline with a PythonScriptSource, which executes our # script function defined above. pipeline = Pipeline(source = PythonScriptSource(function = create_particles)) # Export the results of the data pipeline to an output file. # The system will invoke the Python function defined above once per animation frame. export_file(pipeline, 'output/trajectory.xyz', format='xyz', columns=['Position.X', 'Position.Y', 'Position.Z'], multiple_frames=True, start_frame=0, end_frame=10)
- property function
The Python function to be called each time the data pipeline is evaluated by the system.
The function must have a signature as shown in the example above. The frame parameter specifies the current animation frame number at which the data pipeline is being evaluated. The
DataCollectiondata is initially empty should be populated with data objects by the user-defined source function.
- class ovito.pipeline.ReferenceConfigurationModifier
This is the common base class of analysis modifiers that perform some kind of comparison of the current particle configuration with a reference configuration. For example, the
WignerSeitzAnalysisModifierare modifier types that require a reference configuration as additional input.
Constant and sliding reference configurations
ReferenceConfigurationModifierbase 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_framefield. 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_offsetflag and specifying the desired
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
referencefield contains a
FileSourceobject 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
AtomicStrainModifiercalculate 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, calculating 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
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_mappingproperty controls the type of coordinate mapping that is used.
- property 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:
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.ToReferenceapplies 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.
- property frame_offset
The relative frame offset when using a sliding reference configuration (if
True). Negative frame offsets correspond to reference configurations that precede the current configuration in time.
- property minimum_image_convention
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.
- property reference
sourceobject 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
StaticSourceto this field to specify an explicit reference configuration.
# The modifier that requires a reference config: mod = CalculateDisplacementsModifier() # Load the reference config from a separate input file. mod.reference = FileSource() # Note: You may have to import FileSource from the ovito.pipeline module. mod.reference.load('input/simulation.0.dump')
- property reference_frame
The frame number to use as reference configuration. Ignored if
- property 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_frameparameter) irrespective of the current frame.
- class ovito.pipeline.StaticSource
Serves as a data
DataCollection, which it will pass to the
Pipelineas input data. One typically initializes a
StaticSourcewith a collection of data objects, then wiring it to a
from ovito.pipeline import StaticSource, Pipeline from ovito.data import DataCollection, SimulationCell, Particles 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)) cell[:,0] = (4,0,0) cell[:,1] = (0,2,0) cell[:,2] = (0,0,2) data.objects.append(cell) # Create a Particles object containing two particles: particles = Particles() particles.create_property('Position', data=[[0,0,0],[2,0,0]]) data.objects.append(particles) # Create a new Pipeline with a StaticSource as data source: pipeline = Pipeline(source = StaticSource(data = 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')
frame – This parameter is ignored, because the data of a
StaticSourceis not time-dependent.
DataCollectioncontaining the data stored in this