File I/O

Warning

This section of the manual is out of date! It has not been updated yet to reflect the changes made in the current development version of OVITO.

This section describes how to load simulation data from external files and how to export data computed by OVITO to a file again.

Data import

The standard way of loading external data is calling the global import_file() function:

>>> from ovito.io import import_file
>>> node = import_file("simulation.dump")

This high-level function works similar to the Load File function in OVITO’s graphical user interface. It creates and returns an ObjectNode, whose FileSource is set up to point to the specified file and loads it.

In case you already have an existing ObjectNode, for example after a first call to import_file(), you can subsequently load different simulation files by calling the load() method of the FileSource owned by the node:

>>> node.source.load("next_simulation.dump")

This method takes the same parameters as the import_file() global function, but it doesn’t create a new object node. Any existing modifiers assigned to the object node are preserved, only the input data is replaced.

Note that the same load() method is also used when loading reference configurations for analysis modifiers that require reference particle coordinates, e.g.:

>>> modifier = CalculateDisplacementsModifier()
>>> modifier.reference.load("reference.dump")

Here the reference attribute refers to a second FileSource, which is owned by the CalculateDisplacementsModifier and which is responsible for loading the reference particle positions required for the displacement vector calculation.

Specifying the column-to-property mapping

OVITO automatically detects the format of input files, but both the global import_file() function and the FileSource.load() method accept format-specific keyword arguments that further control the import process. For instance, when loading XYZ files, the mapping of input file columns to OVITO’s particle properties needs to be specified using the columns keyword:

>>> node = import_file("simulation.xyz", columns =
...         ["Particle Type", "Position.X", "Position.Y", "Position.Z", "My Property"])

The number of entries in the columns list must match the number of data columns present in the XYZ input file. See the documentation of the import_file() function for more information on this.

Simulation sequences

So far we only considered loading single simulation snapshots. As you know from the graphical program, OVITO is also able to load sequences of simulation snapshots (trajectories), which can be played back as animations. There are two scenarios:

  1. To load a file containing multiple simulation frames, use the multiple_frames keyword:

    >>> node = import_file("sequence.dump", multiple_frames = True)
    

    OVITO will scan the entire file and discover all contained simulation frames. This works for LAMMPS dump files and XYZ files, for example.

  2. To load a series of simulation files from a directory, following a naming pattern like frame.0.dump, frame.1000.dump, frame.2000.dump, etc., pass a wildcard pattern to the import_file() function:

    >>> node = import_file("frame.*.dump")
    

    OVITO will automatically find all files in the directory belonging to the simulation trajectory.

In both cases you can check how many frames were found by querying the num_frames property of the FileSource, e.g.:

>>> node.source.num_frames
85

Note

To save memory and time, OVITO never loads all frames of a trajectory at once. It only scans the directory (or the multi-frame file) to discover all frames belonging to the sequence and adjusts the internal animation length to match the number of input frames found. The actual simulation data of a frame will only be loaded by the FileSource on demand, e.g., when jumping to a specific frame in the animation or when rendering a movie.

You can loop over the frames of a loaded animation sequence:

# Load a sequence of simulation files 'frame0.dump', 'frame1000.dump', etc.
node = import_file("simulation*.dump")

# Set up data pipeline, apply modifiers as needed, e.g.
node.modifiers.append(CoordinationNumberModifier(cutoff=3.2))

for frame in range(node.source.num_frames):

    # This loads the input data for the current frame and
    # evaluates the applied modifiers:
    output = node.compute(frame)

    # Work with the computation results
    ...

Data export

Exporting particles and other computation results to a file is typically done using the global ovito.io.export_file() function. For example, to export the particles that leave the modification pipeline of an ObjectNode to a LAMMPS dump file, one would write:

>>> export_file(node, "outputfile.dump", "lammps/dump",
...    columns = ["Position.X", "Position.Y", "Position.Z", "My Property"])

OVITO automatically evaluates the node’s modification pipeline to obtain the computation results and writes them to the file. Of course, if the node’s modification pipeline contains no modifiers, then the original data loaded via import_file() is exported.

The second function parameter specifies the output filename, and the third parameter selects the output format. For a list of supported file formats, see the export_file() documentation. Depending on the selected output format, additional keyword arguments may need to be specified. For instance, in the example above the columns parameter specifies the list of particle properties to be exported.

In addition to particles, export_file() can also export other types of data computed by OVITO. One example are global attributes, which are data values generated by modifiers during the pipeline evaluation. In other words, unlike particle properties, attributes are computation results that are associated with a particle dataset as a whole. For example, the ExpressionSelectionModifier outputs an attribute with the name SelectExpression.num_selected to report the number of particles that matched the given selection criterion.

You can export the value of this computed attribute to a text file, typically for all frames of a simulation as a table, to graphically plot the time evolution using an external program. For this purpose the export_file() function supports the txt output format:

node = import_file("simulation*.dump")

node.modifiers.append(ExpressionSelectionModifier(expression="PotentialEnergy<-3.9"))

export_file(node, "potenergy.txt", "txt", multiple_frames=True,
         columns = ["Frame", "SelectExpression.num_selected"])

This produces a text file potenergy.txt containing one line per simulation frame and two columns:

0 531
1 540
2 522
3 502
...

The first column is the animation frame number (starting at 0) and the second column contains the value of the SelectExpression.num_selected attribute output by the ExpressionSelectionModifier.

Typically, attributes are generated by modifiers in the pipeline, but some may also be defined during file import. For example, an attributed named Timestep is set by OVITO when importing a LAMMPS dump file, which specifies the simulation timestep number of the loaded snapshots. This makes it possible, for example, to replace the animation frame number in the first column above (corresponding to the predefined attribute Frame) with the actual timestep number from the simulation. See ovito.data.DataCollection.attributes for more information.