Advanced topics

This section covers several advanced topics related to OVITO’s scripting interface:

Saving and loading pipelines

The function lets you save the computed output of a pipeline to disk. But how do you save the definition of the pipeline itself, including the modifiers and their parameters, to a file? OVITO can save the entire visualization scene to a .ovito state file using the method. Thus, in order to save a Pipeline you need to first make it part of the scene by calling its add_to_scene() method:

import ovito
from import import_file
from ovito.modifiers import CoordinationAnalysisModifier

pipeline = import_file("input/simulation.dump")
pipeline.modifiers.append(CoordinationAnalysisModifier(cutoff = 3.4))
# ... 

The saved state can be restored by calling the Scene.load() method. This function loads all saved data pipelines and makes them available in the Scene.pipelines list:

import ovito

pipeline = ovito.scene.pipelines[0]
data = pipeline.compute()

Of course, it is also possible to open the .ovito state file with the graphical OVITO application or, conversely, to use the graphical application to create a data pipeline by hand and then save that pipeline to a .ovito file for future use.

You can either load the state file from a script at runtime using the Scene.load() method or preload the state file when running the script using the ovitos integrated interpreter. This is done by specifying the -o command line option:

ovitos -o mypipeline.ovito

The code in will now be executed in an environment where the Scene was already populated with the state loaded from the .ovito scene file. Instead of setting up a new pipeline from scratch, the script can now work with the existing pipeline(s) that were restored from the state file:

import ovito

pipeline = ovito.scene.pipelines[0]

# Replace the data file that serves as pipeline input with a different one:
# Adjust modifier parameters of the existing pipeline:
pipeline.modifiers[0].cutoff = 3.1

data = pipeline.compute()

Controlling how many processor cores OVITO uses

Many computation functions in OVITO have been parallelized in order to make use of all available processor cores. This includes, for example, computationally heavy analysis rountines such as PolyhedralTemplateMatchingModifier, VoronoiAnalysisModifier, ClusterAnalysisModifier, ComputePropertyModifier, and many more. The software-based rendering engines TachyonRenderer and OSPRayRenderer also harness multiple cores in parallel to speed up image generation.

By default, these algorithms will make use of all available cores of your CPU. This default number is determined by OVITO using the function QThread.idealThreadCount(), which can be queried as follows in a Python program:

>>> from ovito.qt_compat import QtCore
>>> print(QtCore.QThread.idealThreadCount())

Sometimes it is desirable to restrict OVITO to a single CPU core only, for example, when running multiple instances of OVITO in parallel on the same node. This can be acocmplished in two ways. The graphical application ovito and the script interpreter ovitos both support the command line parameter --nthreads, which lets you override the number of CPU cores used by parallel algorithms:

ovitos --nthreads 1

Your second option is to set the OVITO_THREAD_COUNT environment variable prior to invoking or importing OVITO. This approach always works, including for Python scripts running in an external Python interpreter and importing the ovito module:


Packaging and installation of user extensions for OVITO

OVITO’s Python interface allows you to implement custom modifiers, file readers, and viewport overlays that seamlessly extend the functionality of OVITO Pro and the standalone OVITO Python package. To make such extensions available to the user in the graphical user interface or in Python programs, they need to be properly installed and registered for the system to automatically find them at runtime.

The automatic discovery of user-defined extension classes is based on Python’s entry point specification. This standard mechanism helps to keep the code of your extension class cleanly separated from the main OVITO software package. That means both may be updated or changed independently, and the standard Python packaging mechanism facilitates the easy deployment of your extension to other OVITO users in case you want to share your work with the community.


To aid you in the development of new extensions, we provide GitHub repository templates for each OVITO extension type, which include step-by-step instructions, an initial directory structure, and a pyproject.toml skeleton that simplifies packaging and distribution of your extension to other users:

Furthermore, the OVITO team hosts a public repository where you can publish your extensions and share them with other users:

OVITO Extensions Directory: A collection of Python extensions submitted by the community, maintained by their respective authors, and curated by the OVITO developers.

In the following, we’ll consider a custom modifier class written for OVITO Pro with the name MyModifier, which will serve as an example for an extension to be registered in the OVITO system. We start with a simple code project layout having the following directory structure:

├── pyproject.toml
└── src/
    └── MyModifier/

The MyModifier class is defined in src/MyModifier/

from import DataCollection
from ovito.pipeline import ModifierInterface

class MyModifier(ModifierInterface):
   def modify(self, data: DataCollection, frame: int, **kwargs):

If you are developing a complex extension, you can also split your code into multiple .py files or nested packages if needed.

The pyproject.toml package metadata file is needed for the installation of MyModifier and any dependencies it requires (e.g. the SciPy package) using pip:

requires = ["setuptools", "wheel"]
build-backend = "setuptools.build_meta"

name = "MyModifier"
version = "1.0"
description = "A custom Python modifier for OVITO."
keywords = ["ovito", "python-file-reader"]
authors = [{name = "Author Name", email = ""}]
maintainers = [{name = "Maintainer", email = ""}]
license = {text = "MIT License"}
readme = ""
requires-python = ">=3.7"
dependencies = [
   "ovito >= 3.9.1"

repository = ""

where = ["src"]

Thanks to this pyproject.toml file, as we will see later, the code of MyModifier can be installed in any Python interpreter (including the OVITO Pro integrated interpreter) using the pip standard utility – just like regular Python packages. After the installation, we could call import MyModifier from a Python program to load and use our module.

However, we still have to tell OVITO Pro that the MyModifier package contains the definition of an OVITO ModifierInterface class (or some other kind of OVITO extension) that should be automatically loaded at runtime and made available in the graphical user interface of OVITO Pro. This requires the definition of an entry point in pyproject.toml (see the setuptools website for more details).

To register our custom modifier class as an entry point in the standard group OVITO.Modifier, we add an entry-points section to pyproject.toml:

"My Modifier" = "MyModifier:MyModifier"

The second line first specifies the human-readable name of our extension to be displayed in the OVITO Pro GUI. The part after the = specifies the module name and the Python class that implements the OVITO extension. In our case, both the module and the class are named MyModifier.

OVITO Pro automatically loads all installed packages that did register entry points in the OVITO.Modifier group and displays them to the user as part of the list of available modifiers. For other extension types similar entry point groups exist:

Python extension class

Entry point group














After preparing the pyproject.toml file, you can now install your extension package locally into OVITO Pro by invoking the pip install command via ovitos:

ovitos -m pip install --user --editable <root-dir>

where <root-dir> is the directory containing the pyproject.toml file. The --editable option ensures that you can still make code changes without the need to reinstall the package. -m tells ovitos to invoke the pip module and run its install command.

If you decide to upload the code of your OVITO extension to a public Git repository, other users can install it directly from your online repository as explained in Installing Python-based extensions for OVITO with pip.