Reading and writing files¶
mdapy.io.read reads one frame of a file into a System, and
mdapy.io.write writes one or more systems to a file. To go through the frames
of a file one at a time, see Trajectories. The format is found from
the file name, and compressed files are handled transparently.
import mdapy as mp
from mdapy.io import formats, read, write
water = mp.System(
positions=[[0.0, 0.0, 0.0], [0.96, 0.0, 0.0], [-0.24, 0.93, 0.0]],
box=mp.Box(10.0),
elements=["O", "H", "H"],
info={"energy": -14.2},
)
write("water.xyz", water)
same = read("water.xyz")
assert same.table.equals(water.table.select(same.table.columns))
write("frames.xyz.gz", [water, water.with_columns(positions=water["positions"] + 1.0)])
last = read("frames.xyz.gz", frame=-1)
formats() # the formats mdapy can read and write
Reading¶
mdapy.io.read(path, format=None, *, frame=0, **options)
| Name | Type | Default | Meaning |
|---|---|---|---|
path |
str or path | The file. | |
format |
str | from the name | Format name; see Formats. |
frame |
int32 | 0 |
Frame to read from a file that holds several; negative values count from the end. |
**options |
Options of the format, listed on its page. |
It returns a System. Compressed files are recognized from their first
bytes, whatever their name: gzip, bzip2, xz, and zstd with Python 3.14 or
newer.
Reading frame k skips the frames before it without reading their atoms;
frame=-1 goes through the whole file. Of an uncompressed file only the
parts that are read are loaded; a compressed file is decompressed into
memory first.
Writing¶
mdapy.io.write(path, systems, format=None, **options)
| Name | Type | Default | Meaning |
|---|---|---|---|
path |
str or path | The file; it is replaced if it exists. | |
systems |
System or iterable of System |
One system, or several for a format that holds several frames. | |
format |
str | from the name | Format name. |
**options |
Options of the format, listed on its page. |
An iterator of systems, such as a generator, is written one system at a
time, so a long trajectory need not fit in memory. A name ending in .gz,
.bz2, .xz or .zst compresses the file. If writing fails, the
incomplete file is removed.
Formats¶
| Name | Extensions | Read | Write | Frames | Page |
|---|---|---|---|---|---|
cif |
.cif |
yes | no | several | CIF |
extxyz |
.xyz, .extxyz |
yes | yes | several | Extended XYZ |
lammps-data |
.data, .lmp, names data.* |
yes | yes | one | LAMMPS data |
lammps-dump |
.dump, .lammpstrj, names dump.* |
yes | yes | several | LAMMPS dump |
outcar |
.outcar, names OUTCAR* |
yes | no | several | VASP OUTCAR |
pdb |
.pdb, .ent |
yes | no | several | PDB |
poscar |
.vasp, .poscar, names POSCAR*, CONTCAR* |
yes | yes | one | VASP POSCAR |
mdapy |
.mdapy |
yes | yes | several | MDAPY files |
mdapy.io.detect_format(path) returns the format of a file name. It ignores a
compression suffix and compares the extension without regard to case; name
patterns such as data.* count only when no extension matches. It
raises UnsupportedFormat
when no format, or more than one, fits the name; pass format= in that case.
mdapy.io.formats() returns this table as a polars DataFrame.
Numbers in text files¶
- Reading gives the double closest to the decimal number in the file,
exactly as Python's
float()does. A decimal point is always., even if the program has set a locale that uses a comma, as GUI toolkits do. - Writing uses the shortest text that reads back to the same double, so a file written by MDAPY reads back to exactly the same numbers.
- Unit conversions by a power of ten, such as velocities in Å/fs in a file and Å/ps in MDAPY, add no rounding and also round-trip exactly.
Errors¶
| Exception | When |
|---|---|
FileFormatError |
The file does not follow its format. The message starts with file:line:, and the exception has path and line attributes. |
UnsupportedFormat |
Unknown format name, a format that cannot be read or written, or zstd before Python 3.14. |
InvalidParameter |
The frame does not exist, or a system cannot be written in the format. |
FileNotFoundError |
The file does not exist. |