File I/O
Python scripts
This chapter shows how to load simulation data from files and how to write computation results to output files.
Loading data files
The import_file() function loads a simulation file and returns a new Pipeline
with the file as input (see Data pipelines):
from ovito.io import import_file
pipeline = import_file("input/simulation.dump")
The function works like the command of the desktop application. It detects the format of the file automatically;
see the list of supported file formats. Files compressed with gzip (.gz) are read directly, and the file location may also be
a remote sftp:// or https:// URL.
Some file formats need additional information to be interpreted correctly, which you provide as keyword arguments to import_file(),
e.g. the atom style of a LAMMPS data file (atom_style='full'). The documentation of import_file() lists all options.
Note
Unlike in the desktop application, import_file() does not insert the new pipeline into the scene.
Call add_to_scene() if you want to render images of the data (see The scene).
File column mapping
OVITO maps the data columns of a particle file to particle properties. For most file formats, this happens automatically,
because the file specifies the meaning of each column. Some formats, e.g. legacy XYZ files, lack this information. Then you have to
specify the mapping explicitly using the columns keyword argument:
pipeline = import_file("output/legacy.xyz",
columns=["Particle Type", "Position.X", "Position.Y", "Position.Z", "Charge"])
The number of entries in the list must match the number of columns in the file. Use standard property names
where possible, so that OVITO knows how to interpret the data; other names create user-defined properties. Use None to skip a file column.
You can also use the columns argument to override the automatic mapping for formats such as LAMMPS dump files.
Loading trajectories
If a file contains a sequence of snapshots, e.g. a LAMMPS dump file with several timesteps, OVITO loads it as a trajectory automatically.
If the simulation code wrote one file per snapshot, specify a filename pattern with a * wildcard in place of the frame number:
pipeline = import_file("input/simulation.*.dump")
print("Number of frames:", pipeline.num_frames)
This loads all files matching the pattern, e.g. simulation.0.dump, simulation.100.dump, etc., as one trajectory, sorted by the numbers in the filenames.
You can also pass an explicit list of files:
pipeline = import_file(["input/first_file.dump", "input/second_file.dump"])
Note
To save time and memory, OVITO does not load all frames of a trajectory at once. import_file() merely scans the files to
discover the available frames. The data of a frame gets loaded when the pipeline is evaluated at that frame, as described in
Processing simulation trajectories.
The FileSource attaches the global attributes SourceFrame and SourceFile to the loaded data, which tell you where it came from:
for data in pipeline.frames:
print(data.attributes["SourceFrame"], data.attributes["SourceFile"])
Many file readers generate additional attributes, e.g. the Timestep attribute containing the simulation timestep number read from a LAMMPS dump file.
Separate topology and trajectory files
Some simulation codes write the static topology of a molecular system (atom types, bonds, etc.) and the atomic trajectories to separate files.
Load the topology file first, then insert a LoadTrajectoryModifier into the pipeline, which loads the time-dependent
particle positions from the trajectory file:
from ovito.modifiers import LoadTrajectoryModifier
# Load the static topology (atom types, bonds) from a LAMMPS data file:
pipeline = import_file("input/input.data", atom_style="bond")
# Load the time-dependent atom positions from a separate LAMMPS dump file:
traj_mod = LoadTrajectoryModifier()
traj_mod.source.load("input/trajectory.dump")
pipeline.modifiers.append(traj_mod)
print("Number of frames:", pipeline.num_frames)
Processing many files in a row
To process a series of independent simulation files the same way, you don’t need to create a new pipeline for each file. Set up the pipeline once,
then replace its input file using the FileSource.load() method, which accepts the same arguments as import_file():
pipeline.source.load("input/second_file.dump")
The following script uses this technique to compute the fraction of fcc atoms in each of a set of files and writes the results to a text file:
import glob
import numpy
from ovito.io import import_file
from ovito.modifiers import CommonNeighborAnalysisModifier
# Set up the processing pipeline once, using the first input file:
files = sorted(glob.glob("input/*.dump"))
pipeline = import_file(files[0])
pipeline.modifiers.append(CommonNeighborAnalysisModifier())
# Process each file with the same pipeline and collect the results in a table:
results = []
for path in files:
pipeline.source.load(path)
data = pipeline.compute()
fcc_fraction = data.attributes["CommonNeighborAnalysis.counts.FCC"] / data.particles.count
results.append((data.particles.count, fcc_fraction))
# Write the table to a text file:
numpy.savetxt("output/fcc_fractions.txt", results, fmt=["%d", "%.4f"], header="atoms fcc_fraction")
Tip
Call ovito.enable_logging() at the beginning of a script to let OVITO print status messages about long-running operations,
such as file loading or modifier computations, to the terminal.
Writing output files
The export_file() function evaluates a pipeline and writes its output to a file in the given format.
For particle file formats, the columns argument selects the particle properties to export:
from ovito.io import export_file
export_file(pipeline, "output/atoms.dump", "lammps/dump",
columns=["Particle Identifier", "Particle Type", "Position", "peatom"])
The documentation of export_file() lists all supported formats and their options. Here are some common use cases.
Exporting trajectories
By default, export_file() exports only the first frame of a trajectory. Use the frame argument to export a different frame:
export_file(pipeline, "output/atoms.xyz", "xyz", frame=1,
columns=["Particle Type", "Position"])
To export all frames, specify multiple_frames=True. Some formats can store all frames in a single file. Alternatively, specify a filename containing
a * wildcard to write one file per frame:
# Write all frames to a single file:
export_file(pipeline, "output/trajectory.dump", "lammps/dump", multiple_frames=True,
columns=["Particle Identifier", "Particle Type", "Position"])
# Write one file per frame; the * gets replaced with the frame number:
export_file(pipeline, "output/frame.*.data", "lammps/data", multiple_frames=True)
The optional arguments start_frame, end_frame, and every_nth_frame let you export a subrange of the trajectory.
Exporting global attributes as a time series
The txt/attr format writes global attributes to a text file, one line per frame. This is a convenient way to record how
a quantity computed by the pipeline evolves over time:
export_file(pipeline, "output/selection_count.txt", "txt/attr", multiple_frames=True,
columns=["SourceFrame", "ExpressionSelection.count"])
The resulting text file can be plotted with any plotting program:
# "SourceFrame" "ExpressionSelection.count"
0 4181
1 4181
...
Exporting data tables
The txt/table format writes a data table, e.g. a histogram computed by a modifier, to a text file.
The key argument specifies the identifier of the table to export:
pipeline.modifiers.append(HistogramModifier(property="peatom", bin_count=50))
export_file(pipeline, "output/energy_histogram.txt", "txt/table", key="histogram[peatom]")
Exporting a data collection
Instead of a pipeline, you can pass a DataCollection to export_file(). This is useful if you have
modified the data returned by the pipeline:
data = pipeline.compute()
data.particles_.delete_elements(data.particles.selection == 0)
export_file(data, "output/selected_atoms.xyz", "xyz", columns=["Particle Type", "Position"])
Exchanging data with other packages
The following modules convert between OVITO’s DataCollection and the data structures of other Python packages,
without going through a file:
ovito.io.ase– Atomic Simulation Environment (ASE)Atomsobjectsovito.io.pymatgen– pymatgenStructureobjectsovito.io.lammps– live data of a LAMMPS simulation running in the same Python process
The third-party packages must be installed in your Python interpreter to use these modules.
To feed the converted data into a pipeline, wrap it in a StaticSource (see Creating data from scratch).
If you need to read or write a file format that OVITO doesn’t support, you can implement a custom file reader or custom file writer in Python.